<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://randygaul.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://randygaul.github.io/" rel="alternate" type="text/html" /><updated>2026-02-23T22:22:15+00:00</updated><id>https://randygaul.github.io/feed.xml</id><title type="html">Randy Gaul’s Game Programming Blog</title><subtitle>C++ and Games development discussion and ideas</subtitle><entry><title type="html">AI Assisted Coding</title><link href="https://randygaul.github.io/coding/2026/02/23/AI-Assisted-Coding.html" rel="alternate" type="text/html" title="AI Assisted Coding" /><published>2026-02-23T00:00:00+00:00</published><updated>2026-02-23T00:00:00+00:00</updated><id>https://randygaul.github.io/coding/2026/02/23/AI-Assisted-Coding</id><content type="html" xml:base="https://randygaul.github.io/coding/2026/02/23/AI-Assisted-Coding.html"><![CDATA[<p>I recently had an AI implement a brand new lighting algorithm from a 2025 white paper, one-shot, producing visible soft-shadows and constant-time global illumination on the first try. Before that it one-shot an entire compute shader backend for my game engine. Tasks that used to take months took under an hour.</p>

<p>I’d been trying out AI for coding since ChatGPT dropped in 2022. Back then it was pretty trivial stuff – converting enums from one format to another, scanning documentation for easy fixes, generating an initial documentation pass for a new function. Codex was a step up and could make pull requests straight to github. I used it to implement an OpenGL ES3 backend for my renderer, a pretty mechanical port just for emscripten. Codex actually one-shot an entire backend renderer by using my SDL_Gpu backend as a reference, and was able to mimic SDL_Gpu’s <em>resource ring-buffer</em> API design for feature parity. Pretty cool. But it struggled with anything that wasn’t so mechanical. Anything new, or anything requiring significant aesthetic/design oriented tradeoffs. I quickly gave up and went back to hand-coding.</p>

<p>With Claude Opus 4.5 I noticed something fundamentally changed. I’m not exactly sure what it was, maybe a few different things, like agentic technology becoming a little more mature, context window getting just large enough, and the LLM maturing enough. Who knows. All I know is after trying out a variety of AI tools this one has hit some kind of quality bar that unlocks some stunning results. You can take on significant coding tasks by describing context and auditing the AI implementation plans, and this more often than not takes much less time than manually editing text files.</p>

<h1 id="no-going-back">No Going Back</h1>

<p>The genie really is out of the bottle on this one, and if you aren’t using AI in some way for coding you’re just falling behind. I get we all like different tools, have different styles, or whatever. Sure. Now I wasn’t really alive in the 80s when C was gaining popularity, but from stories I’ve heard there was a lot of discussion in that decade about moving from assembly/fortran to C, a higher level language that automates a lot of the mechanical, bit-twiddling minutiae of managing CPU registers. And well, it won – today we don’t really hand-roll assembly except for odd cases, and most people don’t even write in C anymore, opting for other higher level technology.</p>

<p>AI assisted coding is the next rung of that same ladder. The mechanical minutiae of managing functions, expressions, and statements gets taken over by a new abstraction. I still <em>can</em> write it all by hand, but I’d rather think in terms of context, design, and direction, and rely on AI to deal with wiring things together, mechanical refactors, boilerplate, etc.</p>

<p>There’s a Pinocchio analogy here that I keep coming back to. Geppetto gets swallowed by the whale and survives by fishing inside its belly. He adapts just enough to not die, but he’s stuck – married to his crystallized knowledge of survival, unable to escape on his own. It takes Pinocchio, who is willing to try something genuinely new and unfamiliar, to actually get them out.</p>

<div style="text-align: center;">
  <img src="/assets/whale.png" alt="whale" />
</div>

<p>If you’re still not using AI for software engineering you’re getting swallowed by a whale. Just kidding :)</p>

<h1 id="examples">Examples</h1>

<p>I had Claude implement compute shader support in <a href="https://github.com/RandyGaul/cute_framework">Cute Framework</a> (the code powering my game project), something that had been frequently requested as a feature for years. This was a one-shot by Claude, of course with some pretty involved prompting, guidance, planning, etc. But still, what was taking years of procrastination to get done was finished in like… idk 30 minutes from inception to <code class="language-plaintext highlighter-rouge">git push</code>? Amazing.</p>

<p>The biggest single-task I’ve had Claude take on so far is to implement <a href="https://arxiv.org/pdf/2505.02041">Holographic Radiance Cascades</a> (HRC), a new lighting algorithm published in late 2025. There’s no way an AI could have trained on this paper prior and gotten released by the time I tried implementing, so it was all fairly new stuff, a pretty good test for the AI.</p>

<p>To help Claude out I actually took the pdf file of the white paper and had Claude help me read all the Greek, because well I don’t speak white-paper, nor do I want to learn. Turns out all of the fancy equations are either function calls or for loops. Once converted to .txt and doing my best to help verify the transcription was accurate, I used the txt file version of the paper PDF as context for Claude to implement HRC. I basically had Claude go equation-by-equation and sketch out small structs or functions to build up small abstractions for the compute shaders.</p>

<p>After doing so it got the more complex merge functions, and I sort of just gave up following at that point to let Claude handle it. I figured if Claude could get out something that sort of worked I could tweak the shader code with the help of online shader hotloading, visually see the differences live, and work backwards to understand wtf was going on. And turns out this was a really time-efficient way to ramp up on understanding the algorithm and paper. In this way the AI was able to transcribe the language of white paper to the language of C and GLSL, languages I was actually familiar with already. This made the whole task of implementing the paper accessible to someone like me who is allergic to LaTeX.</p>

<p>The whole thing was coded about 90% by Claude, the last 10% being bugfixes, optimizations, customizations, etc. That first 90% was one-shot and <em>got something visible and coherent on the screen</em>. Here is the result after a Claude one-shot:</p>

<div style="text-align: center;">
  <img src="/assets/hrc_one_shot.png" alt="one_shot" />
</div>

<p>Now obviously this screenshot is carefully cropped to hide all the bugs, but it certainly did produce some kind of soft-shadows, constant-time global illumination. And well, the results speak for themselves:</p>

<div style="display: flex; justify-content: center;">
  <blockquote class="twitter-tweet">
    <a href="https://twitter.com/RandyPGaul/status/2023576821904896113"></a>
  </blockquote>
</div>

<h1 id="rethinking-code-maintenance-cost">Rethinking Code Maintenance Cost</h1>

<p>There are plenty of other examples, such as solving bugs at work, accelerated code-search, cross-sectional design analysis of other popular games, the list goes on. Claude is <em>so damn good</em> at solving mechanical, task-oriented problems I started to realize I can shift my coding strategy to become way more effective in a weird way. I had a discussion with a friend of mine about hotloading assets in our game projects. I was describing how I had a pretty naive file-scanner for detecting if shader files are changed to hotload them while the game is running. This is a development-only feature, so who cares if it’s pretty slow, right? My game doesn’t have <em>that</em> many shaders, and SSDs today are pretty fast, right? I got away with this for a year or so until I started writing a lot more shaders. After some profiling I realized this was starting to take up like 1/3rd of my game’s frame time.</p>

<p>I asked my friend about this situation, and they responded with what traditionally I would consider an extremely based take: “Just bind a keystroke like ctrl + R to reload all the shaders and do that each time you make an edit”. Yes, this is an extremely simple, very robust way to do hotloading without affecting every single frame’s performance. And usually I would agree, that anything more complex than this is just not worth the effort, specifically over the development of a game, which usually lasts years – you absolutely can not afford extra things to spend energy on or split focus.</p>

<p>However, with AI today that’s just not the same value proposition, and especially not the same risk any longer. AI is extremely good at implementing any technology that has somewhat aged, something with lots of old online documentation, blog posts, etc. So MSDN is basically free for the taking. I prompted Claude to write a file event watcher against the win32 API, something I really wouldn’t ever tackle as a solo dev because it’s just so far removed from the player experience. However, Claude can one-shot this super easily, and in the event of bugs popping up it’s easy to prompt Claude about the bug and fix it in a matter of minutes. Which did end up happening, as later I noticed double-events were getting reported for some reason, and who cares what the root cause is, I just prompt Claude about it and it fixes the issue. This is only like 35 lines of code, dev-only, Windows only, so who cares. Honestly, it’s just trivial with AI to deal with that kind of issue, an otherwise unholy concept pre-AI.</p>

<p>More generally, Claude is extremely good at writing small C programs to take on annoying tasks. You can just write a C program, stick it into your pre-build step in CMake, and rely on Claude to maintain that system over time as your dumb fucking CMake scripts magically decay for no reason, or you modify your project which cascades into little refactors for these C tools – no problem. Claude can just do those refactors one at a time trivially, and it takes almost no time to do so. You can easily have AI setup regression unit tests as well, and have it run those itself, and even setup debug loops in the case of regressions that are almost nearly automated.</p>

<p>For example I went and downloaded some 2d tileset art packs as placeholder art for a game I’m working on. A common task. It’s pretty time consuming though to use placeholder art made by someone outside of your immediate dev team because the art is never in the format you expect. Things need to be chopped up, shuffled around, and little tools are usually needed to facilitate the compatibility pipeline to get shit into the game. Use Claude for this. Describe the format verbally, explain specifically how to understand the engine format by merely pointing Claude to your source files, and just write a converter. This takes like 3 minutes, produces a standalone executable tool, and you can either check it into source or just throw it away. It doesn’t even really matter, because producing a new one on-demand is still trivial, and will be trivial tomorrow, and will be trivial in 10 years.</p>

<p>I downloaded some Wang tilesets in dual-grid format, all to say they organized these 32x32 pixel tiles but the actual tiles I wanted to render were 16x16, and the ordering was all different compared to the custom ordering I had already defined pre-AI. I prompted Claude to write a C converter to chop up the image into 16x16 tiles, throw away tiles with no content (fully transparent tiles), and then reshuffle + keep the tiles I cared about that are compatible with my already defined in-engine format. One-shot, no problems. I simply checked in the converted tileset to git and moved on to the next task. This took maybe 5 minutes of my time.</p>

<p>All this to say, what once was too much burden to maintain becomes often unlockable with AI. The burden now moreso becomes the design of your architecture, the features you’re implementing or planning, aka the actual project in your mind becomes the focus. This is much like scaling up your own little game studio and hiring employees – you start delegating smaller scoped tasks, or tasks that contain less ambiguity and more specificity to others, freeing up your time to focus on something else.</p>

<h1 id="ai-coding-flow">AI Coding Flow</h1>

<p>Let’s compare traditional and AI assisted coding flows:</p>

<div style="text-align: center;">
<pre style="display: inline-block; text-align: left;">
              TRADITIONAL HAND-CODING
    ┌─────────────────────────────────────────┐
    │                                         │
    │  Understand ──► Design ──► Write Code   │
    │   Problem       Solution   Line-by-Line │
    │                                 │       │
    │                      ┌──────────┘       │
    │                      ▼                  │
    │                 Debug &amp; Test            │
    │                      │                  │
    │               ┌──────┴──────┐           │
    │               ▼             │           │
    │           Ship It       bugs│           │
    │               │             │           │
    │               ▼             │           │
    │     ┌───────────────────┐   │           │
    │     │  Maintain Forever │───┘           │
    │     │  (refactors,      │               │
    │     │   bit-rot, CMake  │               │
    │     │   decay, compat)  │               │
    │     └─────────┬─────────┘               │
    │               ▼                         │
    │   ┌───────────────────────┐             │
    │   │ "Is this feature      │             │
    │   │  worth building AND   │             │
    │   │  maintaining?"        │             │
    │   │                       │             │
    │   │  Often: NO ──► not    │             │
    │   │           built       │             │
    │   └───────────────────────┘             │
    │                                         │
    └─────────────────────────────────────────┘
</pre>
</div>

<p>The really expensive bits are when you’re stuck in a loop of debug &amp; test/bugs and have to repeatedly go back to design/write by hand. The by-hand or line-by-line part is very time consuming and honestly is a lot of hard work. At the end of the day, in order to really maximize your own time efficiency you have to be really brutal about tradeoffs. Code starts to look <em>extremely expensive</em>, less code is better, ease of maintenance is priority, lowering risk over time is priority. These are all still true even with AI coding, but… Well just look:</p>

<div style="text-align: center;">
<pre style="display: inline-block; text-align: left;">
               AI-ASSISTED CODING
    ┌─────────────────────────────────────────┐
    │                                         │
    │   Describe Context ──► AI Plans &amp;       │
    │   &amp; Direction          Generates Code   │
    │        ▲                    │           │
    │        │                    ▼           │
    │        │            ┌──────────────┐    │
    │        │            │ Review &amp;     │    │
    │        └────────────│ Audit Output │    │
    │        refine       └──────┬───────┘    │
    │        prompt              │            │
    │                     ┌──────┴──────┐     │
    │                     ▼             │     │
    │                  Ship It     regen│     │
    │                     │        from │     │
    │                     ▼        desc.│     │
    │           ┌──────────────────┐    │     │
    │           │ Maintain?        │    │     │
    │           │ Or just regen    │────┘     │
    │           │ on demand.       │          │
    │           │ Cost ≈ trivial.  │          │
    │           └─────────┬────────┘          │
    │                     ▼                   │
    │       ┌───────────────────────┐         │
    │       │ "Is this feature      │         │
    │       │  worth describing     │         │
    │       │  clearly?"            │         │
    │       │                       │         │
    │       │  Usually: YES ──►     │         │
    │       │       gets built      │         │
    │       └───────────────────────┘         │
    └─────────────────────────────────────────┘
</pre>
</div>

<p>You just have this undying minion who never tires, always available to plow through the dirty work. It’s like growing 10 arms and 3 brains or something. Time efficiency just goes way up because iteration time between specifying the problem and shipping a thing gets just absolutely smashed by AI. Here’s another visual for you, rare footage of Claude smashing bugs:</p>

<div style="text-align: center;">
  <video src="/assets/myjzZzDHltHD.mp4" autoplay="" loop="" muted="" playsinline=""></video>
</div>

<p>When faced with problems, bugs, refactors, etc. it’s just usually pretty trivial to generate prompts to investigate further, debug, refactor, or try different strategies. Typically once a problem is described with clarity there’s a cascade of simplicity and clarity that follows through the implementation. Bugginess, instability, or otherwise code issues usually stem from inherent design or approach flaws. By focusing on the clarity of “documentation” the problem transforms from many verbose but mechanically simple operations, to a higher level form where we more just talk like a humans talk to each other.</p>

<p>All this to say, problem solving gets lifted up into a new paradigm. You can work more as a code or problem designer, and think more in terms of product or implementation strategy. The cost of trying out a refactor is now often lower than actual penciling out every detail beforehand. Often I find myself just telling Claude to try out an idea or specification before I fully understand all the implications, because I realized I can just open my game project and try it out empirically. If it looks promising, <em>then</em> I can invest precious human time to review and think through implications – often prompting followup reimplementations or designs, but <em>more informed</em> reimplementations or designs.</p>

<h1 id="conclusion">Conclusion</h1>

<p>For me the conclusion is solid here: I’ve been able to smash dozens of open source issues/bugs/tickets that would otherwise have taken years to get through in my spare time, all in one weekend. Tasks that would normally take 1-2 months to ship (implement, test for bugs, verify robustness) took usually under an hour. Given a well specified problem Claude can just churn through tasks, wire things up, and otherwise interpolate between the rest of your code as reference points. I would be a little wary setting up an entirely new project purely with Claude, but for working in a pre-existing codebase with a lot of prior pattern references Claude can nail about 95% of prompts I throw at it first try, writing code <em>very close to what I would otherwise have written myself by hand</em>.</p>

<p>And to me that last part is crucial: I really feel like it’s been able to get extremely close to code I would actually have written by-hand in practice. I do wish corporate environments I work in would catch up in terms of policy and security, because at least for my own projects I’ve saved months and months of time, and actually have gotten to a point where I’ve <em>run out of coding tasks</em> and have to start hard-pivoting into design and content creation mode to <em>generate more coding tasks</em> for AI to smash through. I’ve never in my life been in this position. The bottleneck has always been implementation speed and maintenance cost. It’s just such a shock to have that bottleneck shift to some other domain.</p>

<p>The advent of AI isn’t some passing fad, it’s a fundamental shift in daily life and will pervade most aspects of life, kind of like the advent of the internet. Or in our AI coding case, kind of like the advent of compilers to produce assembly. Don’t be Geppetto.</p>

<h1 id="some-parting-ai-tips">Some Parting AI Tips</h1>

<p>Claude’s bottleneck is, in my opinion, memory of the context window. It’s only 100k tokens, whatever that means, and it ain’t much. I’ve found a trick to help here is write a claude.md file for your project that points to files to reference. At first I tried writing actual documentation briefs in claude.md, and found it would read those and then just voluntarily go read the source files anyways for more of a concrete look. Which you know, fair enough. I’d do the same, personally! So in the end just routing AI straight to the relevant source files saves a lot of parallel-scan sub-agents from spawning.</p>

<p>However, that parallel-scan of sub-agents is going to happen one way or another. The AI needs its precious context, and who are you to deny Gollum his precious? Don’t deny Gollum of his precious. Feed the little mouse its cookie and soak up 20-30% of your context window as the session begins. Once you approach that devastating 10% until the auto-compact, your life isn’t actually over. Just use the <code class="language-plaintext highlighter-rouge">/rewind</code> feature and select <code class="language-plaintext highlighter-rouge">conversation only</code> to keep your code changes. Back up just to the point where Claude did its initial breadth-context-scan and keep that. Reuse your session to solve the next problem, next iteration, etc. and avoid that apocalyptic conversation compaction.</p>

<p>Another really nice couple of features are the <code class="language-plaintext highlighter-rouge">/plan</code> mode, really my favorite way to make sure to stave off Claude’s retardation. And yes, it does have like 95% correctness in most cases, as in, 95% of the code or plan is what I would have done myself by-hand, but that 5% is real and does compound. If I let in 4 tasks at 95% correctness that will compound down to 81% correctness, and it does continue decaying. Human vigilance is required. <code class="language-plaintext highlighter-rouge">/plan</code> is great for that. Another way to help with plans or task-specificity is to tell Claude to drill down on ambiguity with the AskUserQuestion tool. It’s also just fun to use the tool because it asks you multiple choice questions. And often asks good questions, like the kind it would have otherwise taken unspoken assumption on (often that 5% of retardation comes from weird assumptions Claude gets married to in the dark).</p>

<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>]]></content><author><name></name></author><category term="coding" /><summary type="html"><![CDATA[I recently had an AI implement a brand new lighting algorithm from a 2025 white paper, one-shot, producing visible soft-shadows and constant-time global illumination on the first try. Before that it one-shot an entire compute shader backend for my game engine. Tasks that used to take months took under an hour.]]></summary></entry><entry><title type="html">2D Rendering with SDF’s and Atlases</title><link href="https://randygaul.github.io/graphics/2025/03/04/2D-Rendering-SDF-and-Atlases.html" rel="alternate" type="text/html" title="2D Rendering with SDF’s and Atlases" /><published>2025-03-04T00:00:00+00:00</published><updated>2025-03-04T00:00:00+00:00</updated><id>https://randygaul.github.io/graphics/2025/03/04/2D-Rendering-SDF-and-Atlases</id><content type="html" xml:base="https://randygaul.github.io/graphics/2025/03/04/2D-Rendering-SDF-and-Atlases.html"><![CDATA[<h1 id="sprite-packing">Sprite Packing</h1>

<p>In 2D game development, texture atlases are commonly used to reduce draw calls and optimize GPU performance. Traditionally, atlases are generated as a build-time preprocessing step, avoiding runtime overhead.</p>

<p>However, this approach complicates the artist workflow. Artists must manually sort images into atlases, slowing iteration and increasing risk when updating assets. If they could instead work with individual image files, iteration would be faster and more flexible.</p>

<p>With modern hardware—more RAM and widespread SSD adoption—we can shift atlas generation to runtime without noticeable performance impact. A sprite or shape-drawing API only needs transform data and a way to fetch pixels. Atlases can be compiled on demand, grouping assets dynamically based on actual draw usage. Unused assets can also be ejected from atlases as needed, optimizing memory without rigid preprocessing constraints.</p>

<p>This is a way to improve asset handling, balancing performance and workflow efficiency for artists and developers alike.</p>

<h1 id="run-time-atlas-api">Run-Time Atlas API</h1>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Sprite</span> <span class="n">sprite</span> <span class="o">=</span> <span class="n">make_sprite</span><span class="p">(</span><span class="s">"path"</span><span class="p">);</span>
<span class="n">sprite</span><span class="p">.</span><span class="n">draw</span><span class="p">(</span><span class="n">at</span><span class="p">);</span>
</code></pre></div></div>

<p>Pros</p>
<ul>
  <li>Dead-simple drawing API</li>
  <li>No preprocessing or build step complications (no abstraction leaks)</li>
  <li>Things are always atlased together when drawn together</li>
</ul>

<p>Cons</p>
<ul>
  <li>More RAM consumption to hold assets in memory for adjusting atlases as-needed</li>
  <li>Minor perf hit for bookkeeping</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">sprite.draw</code> can simply push plain-old-data (structs) into a buffer. The buffer can be processed as-needed by the sprite API to produce draw calls. The sprite API can, internally, figure out how to deal with texture atlases.</p>

<h1 id="text">Text</h1>

<p>A full-featured rendering API in 2D would have three key drawable types: sprites, shapes, and text. We’ve already covered sprites so far. Text can be rendered in the same way sprites are rendered, by pushing sprites into the sprite API for rendering. A function such as <code class="language-plaintext highlighter-rouge">draw_text("hello")</code> works well. Each character can be decoded from a UTF8 input string one at a time. The character can map to a glyph within a font, where each glyph has a pre-rasterized image from the font file. <code class="language-plaintext highlighter-rouge">stb_truetype.h</code> is a good library to perform this font loading and rasterization step.</p>

<p>A great side-effect of our runtime sprite API is we can inject new sprites whenever we like without worrying about atlases. This includes applying prerendered effects for text such as blurring. This means only glyphs that are actually rendered need be uploaded to the GPU, and only glyphs that are blurred need be uploaded to the GPU. This creates a highly flexible system with very low VRAM requirements. Other more rigid text systems typically prerender glyphs onto atlases on-disk, and require some input to decide which glyphs the game will actually use at run-time. This is essentially an abstraction leak that leaks all the way into the asset pipeline.</p>

<h1 id="shapes">Shapes</h1>

<p>Shapes can be rendered alongside the sprite/text API. A traditional 2D shape rendering approach could achieve antialiasing by generating skirt geometry around the borders of shapes, creating slightly opaque feathered edges. The skirts themselves must be calculated carefully, requiring custom code for each new type of shape to be rendered. This gets especially tricky for shapes like polylines. It gets especially complex when trying to round shape corners. Now imagine throwing in stroked shapes (drawing just the border with an empty interior). You’re now in for an explosion of explicit code cases to write out by hand.</p>

<p>Example of drawing rounded, annular (stroked) shapes with and without antialias:</p>

<div style="text-align: center;">
  <img src="/assets/aa_boxes.gif" alt="aa_boxes" />
</div>

<p>Instead, a simpler way to render shapes that naturally lends itself to both rounding and antialiasing is the concept of signed-distance functions, focusing on finding the isosurface of a shape. Take for example a circle. We can, for each pixel, calculate the distance of the pixel to the circle’s surface:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">float</span> <span class="nf">sdf_circle</span><span class="p">(</span><span class="n">vec2</span> <span class="n">center</span><span class="p">,</span> <span class="kt">float</span> <span class="n">radius</span><span class="p">,</span> <span class="n">vec2</span> <span class="n">p</span><span class="p">)</span>
<span class="p">{</span>
	<span class="k">return</span> <span class="n">distance</span><span class="p">(</span><span class="n">center</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">-</span> <span class="n">radius</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>It turns out Inigo Quilez has created a <a href="https://iquilezles.org/articles/distfunctions2d/">nice collection of SDF functions for implicitly defined 2D shapes</a>. Fragment shaders are good at determining the distance of each pixel to a particular shape. Given the distance you decide if a fragment is inside the shape (negative distance), outside the shape (positive distance), or close to the border (within some absolute tolerance). However, the shadertoy examples provided by Inigo run full-screen. To make practical use of this technique it’s important to try and reduce pixel overdraw.</p>

<p>For 2D games pixel overdraw can become a serious bottleneck. This happens when the GPU is saturated with too many writes to the same pixel, causing performance loss. By wrapping each shape in a tightly bound quad pixel overdraw can be largely mitigated. The data we send to the GPU can look something like this design sketch:</p>

<p>Vertex attributes:</p>
<ul>
  <li>Point for the quad (in world space)</li>
  <li>Homogeous point for the quad (transformed by the camera)</li>
  <li>Point for the circle (in world space)</li>
</ul>

<p>Hardware interpolation between the vertex and fragment shaders should be used for these attributes. The homogenous point would be the output of the vertex shader for actual rasterization of the quad wrapping the shape. The other two attributes are fed into the SDF to calculate a distance.</p>

<p>To perform final rendering in the fragment shader a simple ternary works great to fill in the shape.</p>

<div class="language-glsl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">float</span> <span class="n">d</span> <span class="o">=</span> <span class="n">distance</span><span class="p">(</span><span class="n">center</span><span class="p">,</span> <span class="n">radius</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
<span class="n">out_color</span> <span class="o">=</span> <span class="n">d</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">.</span><span class="mi">0</span> <span class="o">?</span> <span class="kt">vec4</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">:</span> <span class="kt">vec4</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</code></pre></div></div>

<p>This ternary will not produce branching or cause any significant performance overhead. Hardware acceleration will be used to select the correct result.</p>

<p>To round the shape simply adjust the surface of the shape by a constant. This inflates the shape. Examples can be seen over at <a href="https://iquilezles.org/articles/distfunctions2d/">Inigo’s work</a>. The same goes for antialiasing – simply blur between boundaries over the region of distance near zero. <code class="language-plaintext highlighter-rouge">smoothstep</code> works great for this. Here are some examples of shape inflating:</p>

<div style="text-align: center;">
  <img src="/assets/chubiness.gif" alt="chubiness" />
</div>

<div style="text-align: center;">
  <img src="/assets/chubiness_triangle.gif" alt="chubiness_triangle" />
</div>

<p>Here’s an example of drawing a blurred shape:</p>

<div style="text-align: center;">
  <img src="/assets/aa_scale.gif" alt="aa_scale" />
</div>

<p>Here’s an example of polygon rendering (up to 8 vertices):</p>

<div style="text-align: center;">
  <img src="/assets/polygon_cf2.gif" alt="polygon_cf2" />
</div>

<p>Using the SDF technique all shape variety becomes isolated down to the SDF itself. Most other aspects of rendering shapes becomes agnostic to the shape type itself. This helps scale up the number of shapes to be supported without incurring too much of a development or maintenance cost. Here’s a quick summary of how all these pieces fit together:</p>

<ol>
  <li>Wrap the shape in a tight-fitting quad</li>
  <li>Attach attributes to each quad’s vertices for the shape’s information, as the fragment shader needs to know the full geometry of the shape in question</li>
  <li>Send off draw calls</li>
  <li>Evaluate the SDF for each shape</li>
  <li>Apply shape rounding, antialiasing, or stroke effects</li>
</ol>

<p>Steps 1, 2, and 3 require different code paths for different shapes. However, these steps are much simpler to implement compared to generating traditional feather geometry or traditional shape rounding/stroke geometry.</p>

<h1 id="batching">Batching</h1>

<p>One final consideration is how to fit different kinds of shapes into a single draw call, alongside text and sprites. Wouldn’t it be cool to draw your whole game in just a couple of draw calls, including beautifully rendered antialiased shapes, sprites, and text all at once?</p>

<p>If we expand the attributes to include up to 8 different points all kinds of shapes can be represented. Triangles, line segments, circles, capsules, and polygons (up to 8 vertices) can all be rendered “together”. I say “together” since in practice each shape type will get rendered serially, as the GPU will have to branch on shape types. However, in practice most games generally render just a couple major shape types, and lots of them. The low batch counts and overall performance will still be highly competitive.</p>

<p>The branching happens by passing in the type of shape as another vertex attribute. A simple if-else chain can be figure out what shape each vertex belongs to and map to the appropriate SDF.</p>

<div class="language-glsl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span> <span class="n">is_sprite</span>  <span class="o">=</span> <span class="n">v_type</span> <span class="o">&gt;=</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">0</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">v_type</span> <span class="o">&lt;</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span>
<span class="kt">bool</span> <span class="n">is_text</span>    <span class="o">=</span> <span class="n">v_type</span> <span class="o">&gt;</span>  <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">v_type</span> <span class="o">&lt;</span> <span class="p">(</span><span class="mi">1</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span>
<span class="kt">bool</span> <span class="n">is_box</span>     <span class="o">=</span> <span class="n">v_type</span> <span class="o">&gt;</span>  <span class="p">(</span><span class="mi">1</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">v_type</span> <span class="o">&lt;</span> <span class="p">(</span><span class="mi">2</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span>
<span class="kt">bool</span> <span class="n">is_seg</span>     <span class="o">=</span> <span class="n">v_type</span> <span class="o">&gt;</span>  <span class="p">(</span><span class="mi">2</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">v_type</span> <span class="o">&lt;</span> <span class="p">(</span><span class="mi">3</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span>
<span class="kt">bool</span> <span class="n">is_tri</span>     <span class="o">=</span> <span class="n">v_type</span> <span class="o">&gt;</span>  <span class="p">(</span><span class="mi">3</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">v_type</span> <span class="o">&lt;</span> <span class="p">(</span><span class="mi">4</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span>
<span class="kt">bool</span> <span class="n">is_tri_sdf</span> <span class="o">=</span> <span class="n">v_type</span> <span class="o">&gt;</span>  <span class="p">(</span><span class="mi">4</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">v_type</span> <span class="o">&lt;</span> <span class="p">(</span><span class="mi">5</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span>
<span class="kt">bool</span> <span class="n">is_poly</span>    <span class="o">=</span> <span class="n">v_type</span> <span class="o">&gt;</span>  <span class="p">(</span><span class="mi">5</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">v_type</span> <span class="o">&lt;</span> <span class="p">(</span><span class="mi">6</span><span class="p">.</span><span class="mi">5</span><span class="o">/</span><span class="mi">255</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span>
</code></pre></div></div>

<p>In the above example 0 maps to sprite, 1 maps to text, 2 maps to box, and so on. Talking about performance, it’s best to try and sort the internals of your draw call based on shape type as much as possible. The main performance hit from branching here comes from warp divergence. A GPU warp (or wavefront on AMD) is a group of parallel threads to compute the same instruction many time simultaneously. It’s like a form of very wide SIMD. There’s a tradeoff here of lower CPU driver overhead and stronger throughput (less and bigger draw calls). Let’s outline a full pro/con list in terms of performance.</p>

<p>Pros</p>
<ul>
  <li>Heavily reduced implementation complexity</li>
  <li>Fewer draw calls</li>
  <li>Strong memory coherence</li>
</ul>

<p>Cons</p>
<ul>
  <li>Potential warp divergence</li>
  <li>Attribute bloat</li>
  <li>Potential pixel overdraw</li>
</ul>

<p>I’ve gotten away with ~144 bytes per-vertex for a full-featured 2D renderer. This is really quite reasonable, and can be paired down by stripping some features (polygon SDF rendering being the biggest culprit). As for warp divergence, in practice this really hasn’t been an issue for any game I’ve seen so far. Games tend to draw a lot of the same shape type, such as many sprites, or many circles/lines. This lends itself to very high performance.</p>

<h1 id="polylines">Polylines</h1>

<p>One difficulty I encountered with rendering polylines is coming up with a good triangulation that doesn’t produce pixel gaps between segments. The core issue with polyline rendering is each segment in the chain of segments must be rendered with perfectly adjacent triangles. Vertex calculations must be done in a deterministic that doesn’t produce slightly different results between segments. Not only this, but the SDF itself must be queried from one segment to another with the exact same inputs on the fragment shader. Failure to follow these rules results in missing and popping pixels along the seams between lines.</p>

<p>The strategy I went with produces a quad per segment, and potentially a wedge for narrow corners. Side note: hopefully you don’t see the bugs in certain cases in this gif:</p>

<div style="text-align: center;">
  <img src="/assets/aa_lines_geom.gif" alt="aa_lines_geom" />
</div>

<p>Bugs aside, as long as adjacent vertices from one segment to another are identical you can achieve a perfect render. For the SDF’s themselves I pass in each segment’s start and end position, but also the start position of the next segment, for three points total. This defines an oriented corner about the polyline. The SDF for two edges forming a single corner can be queried and merged pretty easily all at once by taking the mininum of each SDF.</p>

<p>The result are these perfectly antialiased and rounded polylines, all drawn with just a small number of tightly wrapped quads.</p>

<div style="text-align: center;">
  <img src="/assets/aa_lines_translucent.gif" alt="aa_lines_translucent" />
</div>

<p>Bugs aside (apologies again for that) this style of polyline rendering handles all but self-intersecting cases of disparate corners. However, self-intersecting corners are gracefully handled due to SDF merging in the fragment shader. It’s really an amazing strategy to get perfcetly rounded, antialiased lines going. You can even support annular/stroked lines (outlines with empty interiors) with this method without any additional code complexity. It gracefully handles thin lines less than a pixel in width (you can clamp to some visual distance, e.g. half a pixel width) all the way up to, and beyond, very fat lines spanning the screen.</p>

<p>Here’s what they look like opaque:</p>

<div style="text-align: center;">
  <img src="/assets/aa_lines.gif" alt="aa_lines" />
</div>

<h1 id="other-shape-effects">Other Shape Effects</h1>

<p>Since the shape rendering is largely controlled by SDF’s it’s entirely possible to modulate rendering based on, for example, environmental factors. If a particular fragment is say, far away you can tone down transparency, blur, adjust color, or even offset positions based on a texture mask. Since rendering happens in the fragment shader the essence of the shape itself is available for tweaking, and plays very nicely generally speaking.</p>]]></content><author><name></name></author><category term="graphics" /><summary type="html"><![CDATA[Sprite Packing]]></summary></entry><entry><title type="html">Data Structures in C and Allocating</title><link href="https://randygaul.github.io/data-structures/memory/2024/10/13/Data-Structures-In-C-And-Allocating.html" rel="alternate" type="text/html" title="Data Structures in C and Allocating" /><published>2024-10-13T00:00:00+00:00</published><updated>2024-10-13T00:00:00+00:00</updated><id>https://randygaul.github.io/data-structures/memory/2024/10/13/Data-Structures-In-C-And-Allocating</id><content type="html" xml:base="https://randygaul.github.io/data-structures/memory/2024/10/13/Data-Structures-In-C-And-Allocating.html"><![CDATA[<p>I’ve been researching ways to make C more ergonomic. After years of trial and error, I’ve found that the most maintainable code is typically pure, portable C. However, one major pain point keeping me in C++ is simplifying user code when dealing with data structures. While C++ allows defining classes with custom semantics, C lacks that kind of flexibility—or so I thought.</p>

<p>Let’s build a C API for dynamic buffers that feels natural to use, supports static allocation, and can grow into heap memory when needed. The goal is to improve ergonomics while maintaining performance. We’ll also introduce a way to map static buffers to unique call sites, reducing memory consumption to a minimum. With this approach, we can write high-performance C code without sacrificing developer flow.</p>

<p>Many readers may already be familiar with <a href="https://github.com/nothings/stb/blob/master/deprecated/stretchy_buffer.txt">stretchy buffers</a>. By hiding a small struct behind a user pointer and using macros, we can mimic some of the ergonomic benefits of C++’s polymorphism in C. This technique allows us to operate on pointers directly with a clean array API, minimizing distractions and keeping the focus on solving problems, not on memory management details.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="k">struct</span> <span class="n">v2</span> <span class="p">{</span> <span class="kt">float</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">;</span> <span class="p">}</span> <span class="n">v2</span><span class="p">;</span>
<span class="n">v2</span> <span class="nf">V2</span><span class="p">(</span><span class="kt">float</span> <span class="n">x</span><span class="p">,</span> <span class="kt">float</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="p">(</span><span class="n">v2</span><span class="p">){</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="p">};</span> <span class="p">}</span>

<span class="n">v2</span><span class="o">*</span> <span class="n">pts</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">apush</span><span class="p">(</span><span class="n">pts</span><span class="p">,</span> <span class="n">V2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">));</span>
<span class="n">apush</span><span class="p">(</span><span class="n">pts</span><span class="p">,</span> <span class="n">V2</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">));</span>
<span class="n">apush</span><span class="p">(</span><span class="n">pts</span><span class="p">,</span> <span class="n">V2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">));</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">asize</span><span class="p">(</span><span class="n">pts</span><span class="p">);</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">printf</span><span class="p">(</span><span class="s">"%f,%f</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">pts</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">x</span><span class="p">,</span> <span class="n">pts</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">y</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">afree</span><span class="p">(</span><span class="n">pts</span><span class="p">);</span>
</code></pre></div></div>

<p>A remaining issue with this approach is the frequent <code class="language-plaintext highlighter-rouge">malloc</code> and <code class="language-plaintext highlighter-rouge">free</code> calls under <code class="language-plaintext highlighter-rouge">apush</code> and <code class="language-plaintext highlighter-rouge">afree</code>. In games, we often build dynamic lists for queries like collisions, process the list, and then <code class="language-plaintext highlighter-rouge">free</code> it. Doing this many times per frame can lead to performance bottlenecks, especially due to lock contention in <code class="language-plaintext highlighter-rouge">malloc</code> and potential cache thrashing. Modern <code class="language-plaintext highlighter-rouge">malloc</code> implementations mitigate cache issues to some extent, but you’re still dependent on the underlying implemenation.</p>

<p>To maintain flow and avoid low-level tedium, we need an allocation scheme that efficiently handles these temporary data structures while remaining ergonomic for the developer. Let’s take a look at a common use case: querying for collisions.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">N</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">Entity</span><span class="o">*</span> <span class="n">ids</span> <span class="o">=</span> <span class="n">query</span><span class="p">(</span><span class="n">box</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">N</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">N</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">on_collide</span><span class="p">(</span><span class="n">my_id</span><span class="p">,</span> <span class="n">ids</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="n">free</span><span class="p">(</span><span class="n">ids</span><span class="p">);</span>
</code></pre></div></div>

<p>This code doesn’t use stretchy buffers. It’s highly annoying to create the variable <code class="language-plaintext highlighter-rouge">N</code>, take the address of it, and then call <code class="language-plaintext highlighter-rouge">free</code>. You know you’re performing a <code class="language-plaintext highlighter-rouge">malloc</code> and <code class="language-plaintext highlighter-rouge">free</code> for every single query. This fact sits in the back of your mind, causing anxiety, eroding your flow-state until eventually you capitulate and try thinking of a way to pre-allocate memory for your collision queries. Maybe you even succeed, and come up with some hand-coded API that caches memory for queries and dynamically grows it as-needed. This works, you’re happy. Until you implement some other feature somewhere else, performing the same pattern. You perform a different kind of query on something else, build a list, traverse the list, and free the list. This other query also happens many times per game-tick. Anxiety rises slowly, and flow-state is broken once again.</p>

<p>Instead, each call-site requiring an array can be uniquely identified. A global temp-space buffer can be allocated once upon game initialization. Each unique call-site can allocate a static buffer from the global scratch space. Each subsequent call will simply return you the same buffer of temp-space memory. At the end of the frame all of these temporary allocations can be cleared all at once using a stack-based allocator, or <a href="https://github.com/pervognsen/bitwise/blob/master/ion/common.c#L172-L209">arena allocator</a>. This link is a nice arena implementation by Per Vognsen on GitHub you can check out if you haven’t seen the technique before. There isn’t much to it – just a stack based allocator.</p>

<p>Combining an arena, and the stretchy buffer technique for polymorphism, we can create an initial statically allocated array that grows onto the heap as-needed. Here’s the API I’ve come up with:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Entity</span><span class="o">*</span> <span class="n">ids</span> <span class="o">=</span> <span class="n">atmp</span><span class="p">(</span><span class="n">Entity</span><span class="p">,</span> <span class="mi">32</span><span class="p">);</span>
<span class="n">ids</span> <span class="o">=</span> <span class="n">query</span><span class="p">(</span><span class="n">ids</span><span class="p">,</span> <span class="n">box</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">asize</span><span class="p">(</span><span class="n">ids</span><span class="p">);</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">on_collide</span><span class="p">(</span><span class="n">my_id</span><span class="p">,</span> <span class="n">ids</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="n">afree</span><span class="p">(</span><span class="n">ids</span><span class="p">);</span>
</code></pre></div></div>

<p>The macro <code class="language-plaintext highlighter-rouge">atmp</code> uniquely identifies itself at the call-site. This lets the backing implementation cache the static buffer allocated from a global arena. Each subsequent call, for this particular query code, will fetch the same underlying buffer (assuming it doesn’t overflow and allocate itself onto the heap). <code class="language-plaintext highlighter-rouge">afree</code> only calls <code class="language-plaintext highlighter-rouge">free</code> if the array has grown onto the heap, otherwise it’s just an if-check no-op.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Allocates a static array using the global tmp allocator `tmp_alloc` (reset at end of frame).</span>
<span class="c1">// ...Uniquely identifies the callsite and continuously returns the same buffer.</span>
<span class="c1">// ...Simply call `afree` when done, as the array may grow beyond the intial static storage.</span>
<span class="c1">// ...Not thread-safe for now, but easily refactored.</span>
<span class="cp">#define atmp(T, n) (T*)atmp_impl(__COUNTER__, sizeof(T), n)
</span><span class="n">FORCE_INLINE</span> <span class="kt">void</span><span class="o">*</span> <span class="nf">atmp_impl</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">alloc_id</span><span class="p">,</span> <span class="kt">int</span> <span class="n">item_size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">void</span><span class="o">*</span> <span class="n">a</span> <span class="o">=</span> <span class="n">g_tmp_cache</span> <span class="o">?</span> <span class="n">hget</span><span class="p">(</span><span class="n">g_tmp_cache</span><span class="p">,</span> <span class="n">alloc_id</span><span class="p">)</span> <span class="o">:</span> <span class="nb">NULL</span><span class="p">;</span>
	<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">a</span><span class="p">)</span> <span class="p">{</span>
		<span class="kt">int</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">item_size</span> <span class="o">*</span> <span class="n">n</span><span class="p">;</span>
		<span class="n">a</span> <span class="o">=</span> <span class="n">astatic</span><span class="p">(</span><span class="n">tmp_alloc</span><span class="p">(</span><span class="n">bytes</span><span class="p">),</span> <span class="n">bytes</span><span class="p">,</span> <span class="n">item_size</span><span class="p">);</span>
		<span class="n">hset</span><span class="p">(</span><span class="n">g_tmp_cache</span><span class="p">,</span> <span class="n">alloc_id</span><span class="p">,</span> <span class="n">a</span><span class="p">);</span>
	<span class="p">}</span>
	<span class="k">return</span> <span class="n">a</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>In the above snippet <code class="language-plaintext highlighter-rouge">hget</code> simply does a hashtable lookup, while <code class="language-plaintext highlighter-rouge">hset</code> simply sets a key-value pair within a global hash table. You should be able to easily adapt this to your own codebase. Of course there are threading concerns hitting a global hashtable, but, that’s easily refactorable, and generally not a concern for most kinds of games.</p>

<p>At the end of the game-tick the global table <code class="language-plaintext highlighter-rouge">g_tmp_cache</code> can be cleared, along with the arena <code class="language-plaintext highlighter-rouge">tmp_alloc</code> is allocating from. All the callsites will simply fetch new static buffers as-needed, keeping memory consumption down to mostly just what’s needed on a frame-to-frame basis.</p>

<p>But why bother uniquely identifying the callsite at all? Why not just return a new statically allocated buffer upon each <code class="language-plaintext highlighter-rouge">atmp</code> call? The reason is ergonomics. The underlying design of dynamically allocated arrays don’t quite map onto arena style allocators. If the array needs to grow itself larger it requires a <code class="language-plaintext highlighter-rouge">realloc</code> or similar, which doesn’t map well onto linearly allocated arenas/stacks, unless you’re willing to simply drop your old memory and allocate more. This will cause your game to allocate quite a lot more memory than necessary.</p>

<p>In practice, this reduces memory usage significantly. Imagine a scenario with 1,000 calls to a collision query. Normally, each call would require a new allocation, but with this approach, memory usage stays constant, and only one allocation occurs per unique call site. In the above example memory consumption drops from ~20kb to 256 bytes.</p>

<p>Another downside is the use of <code class="language-plaintext highlighter-rouge">__COUNTER__</code> to uniquely identify callsites. <code class="language-plaintext highlighter-rouge">__COUNTER__</code> is non-standard C, but supported by GCC, Clang, and MSVC (all the big ones). It’s possible to use a different, more portable solution involving static variables, assigning unique ids at runtime. However, it would require <code class="language-plaintext highlighter-rouge">atmp</code> to be called on a different line than the initialized array, which is unfortunately just annoying an less ergonomic.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">v2</span><span class="o">*</span> <span class="n">pts</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">atmp</span><span class="p">(</span><span class="n">pts</span><span class="p">,</span> <span class="mi">32</span><span class="p">);</span>
</code></pre></div></div>

<p>The implementation of <code class="language-plaintext highlighter-rouge">atmp</code> could then hide a unique id in a static variable, something like so:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define atmp(a, n) do { static int id = g_id_gen++; a = atmp_impl(id, sizeof(a), n); } while(0)
</span></code></pre></div></div>

<p>The final downside here is the buffer is semantically static, a lot like the <code class="language-plaintext highlighter-rouge">static</code> keyword. You won’t be getting unique buffers each time a function is called, which restricts it’s usage. In the event you want to return an actual unique buffer that will persist, get handed around to other functions, then simply allocating directly from the arena without a caching mechanism is preferred. A different macro can provide this quite easily, directly calling into the equivalent of <code class="language-plaintext highlighter-rouge">tmp_alloc</code> in your own codebase.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Similar to `atmp` but does not uniquely identify the callsite.</span>
<span class="c1">// ...Simply returns a statically allocated buffer.</span>
<span class="cp">#define ascratch(T, n) (T*)ascratch_impl(sizeof(T), n)
</span><span class="n">FORCE_INLINE</span> <span class="kt">void</span><span class="o">*</span> <span class="nf">ascratch_impl</span><span class="p">(</span><span class="kt">int</span> <span class="n">item_size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">int</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">item_size</span> <span class="o">*</span> <span class="n">n</span><span class="p">;</span>
	<span class="kt">void</span><span class="o">*</span> <span class="n">a</span> <span class="o">=</span> <span class="n">astatic</span><span class="p">(</span><span class="n">tmp_alloc</span><span class="p">(</span><span class="n">bytes</span><span class="p">),</span> <span class="n">bytes</span><span class="p">,</span> <span class="n">item_size</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">a</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>And there you have it! It’s nothing particularly new or special, just a mishmash of a few different techniques and careful API design. The vast majority of dynamic arrays are reduced to a few if-checks and a single hashtable hit. Only in worst-case scenarios is <code class="language-plaintext highlighter-rouge">malloc</code> and <code class="language-plaintext highlighter-rouge">free</code> ever touched, and memory consumption scales relative to the number of unique callsites, instead of by how many times individual functions are called.</p>]]></content><author><name></name></author><category term="data-structures" /><category term="memory" /><summary type="html"><![CDATA[I’ve been researching ways to make C more ergonomic. After years of trial and error, I’ve found that the most maintainable code is typically pure, portable C. However, one major pain point keeping me in C++ is simplifying user code when dealing with data structures. While C++ allows defining classes with custom semantics, C lacks that kind of flexibility—or so I thought.]]></summary></entry><entry><title type="html">Game Math 101, Writing your Own 2D Math in C++</title><link href="https://randygaul.github.io/math/2022/09/18/Game-Math-101-Writing-your-Own-2D-Math-in-CPP.html" rel="alternate" type="text/html" title="Game Math 101, Writing your Own 2D Math in C++" /><published>2022-09-18T00:00:00+00:00</published><updated>2022-09-18T00:00:00+00:00</updated><id>https://randygaul.github.io/math/2022/09/18/Game-Math-101-Writing-your-Own-2D-Math-in-CPP</id><content type="html" xml:base="https://randygaul.github.io/math/2022/09/18/Game-Math-101-Writing-your-Own-2D-Math-in-CPP.html"><![CDATA[<p>Do you want to make a game but don’t know any math? Do you want to skip endless hours of reading arcane math texts and go straight to the useful stuff? Good! Me too. Let’s just skip straight ahead to the useful stuff. Sit back, grab yourself a lunchable, and get ready to become a wizard.</p>

<p>We will be using C++ and writing our own math to create some demonstrations and animations from scratch. By the end of this article you will produce an interactive experience like the one seen just here below in this cute gif!</p>

<p>gif here</p>

<p><a href="https://github.com/RandyGaul/game_math_101">C source code here</a></p>

<p><a href="https://github.com/RandyGaul/randygaul.github.io">This webpage’s source</a> in case you want to post any edits/suggestions/discussion for the article.</p>

<h2 id="table-of-contents">Table of Contents</h2>

<ul>
  <li><a href="#prerequisites">Prerequisites</a></li>
  <li><a href="#get-a-compiler">Get a Compiler</a></li>
  <li><a href="#grab-a-copy-of-tigr">Grab a Copy of tigr</a></li>
  <li><a href="#build-and-run-the-math-101-program">Build and Run the Math 101 Program</a></li>
  <li><a href="#drawing-some-lines">Drawing some Lines</a></li>
  <li><a href="#positions-points-and-vectors">Positions (points) and Vectors</a></li>
  <li><a href="#drawing-some-points">Drawing some Points</a></li>
  <li><a href="#animating">Animating</a></li>
  <li><a href="#transforming-to-screen-space">Transforming to Screen Space</a></li>
  <li><a href="#rotations">Rotations</a></li>
  <li><a href="#unit-vectors--normalization">Unit Vectors + Normalization</a></li>
  <li><a href="#dot-product">Dot Product</a></li>
  <li><a href="#cross-product-aka-2d-determinant">Cross Product (aka 2D Determinant)</a></li>
  <li><a href="#distance-and-planes">Distance and Planes</a></li>
  <li><a href="#bezier-curves-and-lerp">Bezier Curves and Lerp</a></li>
  <li><a href="#matrices">Matrices</a></li>
  <li><a href="#transforms">Transforms</a></li>
  <li><a href="#raycasting-basics">Raycasting Basics</a></li>
  <li><a href="#collision-detection-basics">Collision Detection Basics</a></li>
  <li><a href="#toy-demo">Toy Demo</a></li>
</ul>

<h2 id="prerequisites">Prerequisites</h2>

<p>You’ll need to know some basic C++ (well, more like just some basic C stuff), but not much so don’t be worried. If you’re not quite comfortable feel free to visit some online C++ tutorials and then come back here later to try again. At a minimum I’d recommend learning about these topics:</p>

<ul>
  <li>Loops</li>
  <li>If-statements</li>
  <li>Functions</li>
  <li>Structs</li>
</ul>

<h2 id="get-a-compiler">Get a Compiler</h2>

<p>Since we’re using C++ we need a compiler. If you already have one and are familiar with how to use them, skip ahead. For those on Mac/Windows here’s how I recommend setting up the <code class="language-plaintext highlighter-rouge">g++</code> compiler.</p>

<h3 id="make-a-folder-for-this-article">Make a Folder for this Article</h3>

<p>Go ahead and make your own personal folder for holding all the files for this article. I’d recommend naming it <code class="language-plaintext highlighter-rouge">math_101</code>.</p>

<h3 id="windows">Windows</h3>

<p>If you’re on Windows I recommend to use <a href="https://jmeubank.github.io/tdm-gcc/download/">TDM-GCC</a>, a dead-simple compiler distribution for <code class="language-plaintext highlighter-rouge">g++</code>. Just download the installer and open up a command prompt <strong><em>after you install the compiler</em></strong>. Here’s a gif showing how to open a command prompt in a specific window (below). You can also use the <a href="https://www.youtube.com/watch?v=BfXh11ryBJg">cd command</a> to move the command prompt to another folder. Move it to your <code class="language-plaintext highlighter-rouge">math_101</code> folder.</p>

<p><img src="/assets/command_prompt.gif" alt="command_prompt" /></p>

<h3 id="mac">Mac</h3>

<p>On Mac just download Xcode from the App Store. This will automatically install the command line tools for you, including <code class="language-plaintext highlighter-rouge">g++</code>. Open up the terminal application <strong><em>after you install Xcode</em></strong>. You can also use the <a href="https://www.youtube.com/watch?v=DvwWJw6Ppns">cd command</a> to move the terminal to another folder. Move it to your <code class="language-plaintext highlighter-rouge">math_101</code> folder.</p>

<p>Most people reading this article will be using a Windows machine. One Windows they use command prompt instead of Terminal. Later when reading, if you see “command prompt” just think Terminal instead. The rest of the steps are 99% the same, despite this difference.</p>

<h3 id="linux">Linux</h3>

<p>If you’re on Linux then I’ll assume you’re already quite familiar with C/C++ and compilers.</p>

<h2 id="grab-a-copy-of-tigr">Grab a Copy of tigr</h2>

<p>We’re using the tigr library. It’s the easiest possible graphics library to get running and use. It handles a bunch of <a href="https://en.wikipedia.org/wiki/OpenGL">OpenGL</a> stuff for us, in case you were curious. It consists of merely one header file and one source file. Grab a copy of each and put them into your <code class="language-plaintext highlighter-rouge">math_101</code> folder.</p>

<ul>
  <li><a href="https://raw.githubusercontent.com/erkkah/tigr/master/tigr.h">tigr.h</a></li>
  <li><a href="https://raw.githubusercontent.com/erkkah/tigr/master/tigr.c">tigr.c</a></li>
</ul>

<h2 id="build-and-run-the-math-101-program">Build and Run the Math 101 Program</h2>

<p>Make a file called <code class="language-plaintext highlighter-rouge">main.cpp</code> in your <code class="language-plaintext highlighter-rouge">math_101</code> folder. Copy + paste this code snippet into your <code class="language-plaintext highlighter-rouge">main.cpp</code> file.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">"tigr.h"</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">Tigr</span><span class="o">*</span> <span class="n">screen</span> <span class="o">=</span> <span class="n">tigrWindow</span><span class="p">(</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">,</span> <span class="s">"Math 101"</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">tigrClosed</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">tigrKeyDown</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">TK_ESCAPE</span><span class="p">))</span> <span class="p">{</span>
		<span class="n">tigrClear</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0x80</span><span class="p">,</span> <span class="mh">0x90</span><span class="p">,</span> <span class="mh">0xa0</span><span class="p">));</span>
		<span class="n">tigrUpdate</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">tigrFree</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>This code sets up our nice little window to create cool animations and visualize our math as we learn. We must compile this code to create an executable. Make sure your command prompt is opened in the <code class="language-plaintext highlighter-rouge">math_101</code> folder along with tigr.c, tigr.h and main.cpp. It should look something like this (you can ignore the <code class="language-plaintext highlighter-rouge">.git</code> file).</p>

<p><img src="/assets/math_101_folder.png" alt="math_101_folder" /></p>

<p>Here is the command we will use to compile the code on Windows.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>g++ main.cpp tigr.c -o math_101_program -s -lopengl32 -lgdi32
</code></pre></div></div>

<p>And here is the one for Mac.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>g++ main.cpp tigr.c -o math_101_program -framework OpenGL -framework Cocoa
</code></pre></div></div>

<p>And finally for you Linux weirdos (joking, haha).</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>g++ main.cpp tigr.c -o math_101_program -s -lGLU -lGL -lX11
</code></pre></div></div>

<p>If you already know how to use a <a href="https://www.gnu.org/software/make/manual/make.html">make and a makefile</a> you can optionally use this makefile. But this is completely optional and not necessary.</p>

<figure class="highlight"><pre><code class="language-make" data-lang="make"><span class="k">ifeq</span> <span class="nv">($(OS),Windows_NT)</span>
	<span class="nv">LDFLAGS</span> <span class="o">=</span> <span class="nt">-s</span> <span class="nt">-lopengl32</span> <span class="nt">-lgdi32</span>
<span class="k">else</span>
	<span class="nv">UNAME_S</span> <span class="o">:=</span> <span class="nf">$(</span><span class="nb">shell</span> <span class="nb">uname</span> <span class="nt">-s</span><span class="nf">)</span>
	<span class="k">ifeq</span> <span class="nv">($(UNAME_S),Darwin)</span>
		<span class="nv">LDFLAGS</span> <span class="o">=</span> <span class="nt">-framework</span> OpenGL <span class="nt">-framework</span> Cocoa
	<span class="err">else</span> <span class="k">ifeq</span> <span class="nv">($(UNAME_S),Linux)</span>
		<span class="nv">LDFLAGS</span> <span class="o">=</span> <span class="nt">-s</span> <span class="nt">-lGLU</span> <span class="nt">-lGL</span> <span class="nt">-lX11</span>
	<span class="k">endif</span>
<span class="k">endif</span>

<span class="nl">demo </span><span class="o">:</span> <span class="nf">demo.cpp tigr.c</span>
	g++ <span class="nv">$^</span> <span class="nt">-Os</span> <span class="nt">-o</span> <span class="nv">$@</span> <span class="nv">$(CFLAGS)</span> <span class="nv">$(LDFLAGS)</span></code></pre></figure>

<p>This will produce an executable file called <code class="language-plaintext highlighter-rouge">math_101_program</code>. Go ahead and run it! You should see a nice ugly window like this one.</p>

<p><img src="/assets/math_101_program.png" alt="math_101_program" /></p>

<p>Congrats!</p>

<h2 id="drawing-some-lines">Drawing some Lines</h2>

<p>The function <code class="language-plaintext highlighter-rouge">tigrLine</code> will draw us lines. All we need to do is specify where the line starts, ends, and it’s color. Here’s the function signature from the header file along with the documentation comments found in tigr.h.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="c1">// Draws a line.</span>
<span class="c1">// Start pixel is drawn, end pixel is not.</span>
<span class="c1">// Clips and blends.</span>
<span class="kt">void</span> <span class="nf">tigrLine</span><span class="p">(</span><span class="n">Tigr</span> <span class="o">*</span><span class="n">bmp</span><span class="p">,</span> <span class="kt">int</span> <span class="n">x0</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y0</span><span class="p">,</span> <span class="kt">int</span> <span class="n">x1</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y1</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">);</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">x0</code> and <code class="language-plaintext highlighter-rouge">y0</code> is the first point of the line, while <code class="language-plaintext highlighter-rouge">x1</code> and <code class="language-plaintext highlighter-rouge">y</code> are the end point. Add a few calls to <code class="language-plaintext highlighter-rouge">tigrLine</code> to our main.cpp program like so:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">"tigr.h"</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">Tigr</span><span class="o">*</span> <span class="n">screen</span> <span class="o">=</span> <span class="n">tigrWindow</span><span class="p">(</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">,</span> <span class="s">"Math 101"</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">tigrClosed</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">tigrKeyDown</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">TK_ESCAPE</span><span class="p">))</span> <span class="p">{</span>
		<span class="n">tigrClear</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0x80</span><span class="p">,</span> <span class="mh">0x90</span><span class="p">,</span> <span class="mh">0xa0</span><span class="p">));</span>

        	<span class="c1">// Add these two lines here!</span>
		<span class="n">tigrLine</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">));</span>
		<span class="n">tigrLine</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">200</span><span class="p">,</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">));</span>

		<span class="n">tigrUpdate</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">tigrFree</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>It should look like this:</p>

<p><img src="/assets/math_101_lines.png" alt="math_101_lines" /></p>

<h2 id="positions-points-and-vectors">Positions (points) and Vectors</h2>

<p>You’ve already used them in the last section on drawing lines! A vector is just a collection of numbers, each number called a component. For games it’s very common to use 2D, 3D, and occassionally 4D vectors. For this article let’s just stick with 2D vectors. Usually we use vectors to represent positions, velocities, and directions. For each of these vectors there would be an x and y a component.</p>

<p>We can write a vector like <code class="language-plaintext highlighter-rouge">{x, y}</code>, or <code class="language-plaintext highlighter-rouge">(x, y)</code>, or even just <code class="language-plaintext highlighter-rouge">v</code>. In our program we can use a struct to represent a vector as a pair of two floats.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">v2</span>
<span class="p">{</span>
    <span class="n">v2</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
    <span class="n">v2</span><span class="p">(</span><span class="kt">float</span> <span class="n">x</span><span class="p">,</span> <span class="kt">float</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">x</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">y</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span> <span class="p">}</span>
	<span class="kt">float</span> <span class="n">x</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">y</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">v2</code> stands for vector 2, for a 2D vector. We will be writing v2 a lot so it’s best to choose a very short and convenient name. Many other folks like to use <code class="language-plaintext highlighter-rouge">vec2</code> or <code class="language-plaintext highlighter-rouge">Vec2</code>, but I’ll recommend a nice a clean <code class="language-plaintext highlighter-rouge">v2</code>.</p>

<p>Operations on vectors are what make them useful. The simplest ones are addition and subtraction. We can add two vectors together or subtract two vectors from each other by adding and subtracting their components. By using operator overloading we can easily implement these operations in C++.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">v2</span> <span class="k">operator</span><span class="o">-</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>Though from here on out let’s just pack these functions up onto a single line each. We’re going to write a lot of them!</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">-</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span></code></pre></figure>

<p>In our program the coordinate (0, 0) represents the origin of the screen and sits a the top-left. The positive x-axis points to the right, while the positive y-axis points down.</p>

<p><img src="/assets/math_101_origin_top_left.png" alt="math_101_origin_top_left" /></p>

<p>When we drew lines in the last section we actually used vectors. Technically speaking a vector is a direction while a <em>point</em> has a position (or location). (0, 0) is a point at the origin, and (100, 100) is also a point at the end of one of our lines. The difference between these two points is a vector. In this way we can say the vector (a direction) of (100, 100) is used to point at the position (100, 100) from the position (0, 0).</p>

<p>If we wanted to be completely strict about our distinction of points and vectors we could adjust our type definitions and operators. We’re not going to <em>actually</em> do this though, because it’s just not practical. But for learning it’s critical to really nail the difference of points and vectors. Here are a couple quick rules:</p>

<ol>
  <li>A position has two components and represents a point in 2D space. We can write it as (x, y), and represent it in code as a <code class="language-plaintext highlighter-rouge">v2</code> float pair. For example, the top-left pixel in our program (the origin) has the position of (0, 0).</li>
  <li>A position has no orientation or direction. It’s merely a point. An infinitesimally tiny spot.</li>
  <li>A vector also has two components, and as far as the computer is concerned it looks the same as vector: two floats as a pair, such as (x, y).</li>
  <li>A vector is a direction, as if it points in a certain direction. For example, so far the direction (0, 1) in our program point straight donwnward.</li>
  <li>A vector has no position.</li>
</ol>

<p>So a position has no direction, and a direction has no position. To be somewhere in the world we need a position. To know where something else is in the world, we need not only a position but a direction. Directions are like differences between positions.</p>

<p>When we drew a line in the last section, we could say we drew a vector between two input points (x0, y0) and (x1, y1). However, we could also say we drew a point and vector, or a vector and a point. These are all mathematically equivalent. Let us name a couple variables.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pa = (30, 50)
pb = (200, 350)
</code></pre></div></div>

<p>We have pa and pb, standing for point A and point B. We can subtract two points to get a vector.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>v = pb - ab
-v = pa - pb
</code></pre></div></div>

<p>In the above example v would have the value of (170, 300). If we do <code class="language-plaintext highlighter-rouge">pb - pa</code> this should read like so: <em>the vector between two points is the endpoint minus the start point</em>. Memorize this and burn it into your skull. If we flip the terms around and do <code class="language-plaintext highlighter-rouge">pa - pb</code> we get a negative vector (-170, -300). Some more rules pop up!</p>

<ol>
  <li>The difference (subtraction) of two points is a vector.</li>
  <li>The vector between two points is the endpoint minus the start point.</li>
</ol>

<p>Similarly we can move a points position by addition. We can add a vector to a point and get a new point. Much like how we can subtract a vector from a point and get a new point.</p>

<ol>
  <li>A point added with a vector moves the point along the vector.</li>
  <li>A point subtracted with a vector moves the point along the negative vector.</li>
</ol>

<h2 id="drawing-some-points">Drawing some Points</h2>

<p>We can draw a single pixel at a specified point with the function <code class="language-plaintext highlighter-rouge">tigrPlot</code>. Here’s the signature and docs from the header tigr.h:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="c1">// Plots a pixel.</span>
<span class="c1">// Clips and blends.</span>
<span class="c1">// For high performance, just access bmp-&gt;pix directly.</span>
<span class="kt">void</span> <span class="nf">tigrPlot</span><span class="p">(</span><span class="n">Tigr</span> <span class="o">*</span><span class="n">bmp</span><span class="p">,</span> <span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">pix</span><span class="p">);</span></code></pre></figure>

<p>Let’s use this function to draw a couple pixels. The color of the background is set to black and the points will be white pixels, so we can see them a little easier. <code class="language-plaintext highlighter-rouge">tigrPlot</code> takes integers to draw an exact pixel while our <code class="language-plaintext highlighter-rouge">v2</code> struct is floats. We can just typecast the floats to ints to snap each float to specific pixel and draw it as a point.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">void</span> <span class="nf">draw_point</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">tigrPlot</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>Go ahead and add it to our program, along with our math functions. Let’s also add in some convenience functions to define specific colors for us, like <code class="language-plaintext highlighter-rouge">color_white</code> and <code class="language-plaintext highlighter-rouge">color_black</code>.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">"tigr.h"</span><span class="cp">
</span>
<span class="k">struct</span> <span class="nc">v2</span>
<span class="p">{</span>
	<span class="n">v2</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">v2</span><span class="p">(</span><span class="kt">float</span> <span class="n">x</span><span class="p">,</span> <span class="kt">float</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">x</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">y</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span> <span class="p">}</span>
	<span class="kt">float</span> <span class="n">x</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">y</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">v2</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">-</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>

<span class="n">Tigr</span><span class="o">*</span> <span class="n">screen</span><span class="p">;</span>

<span class="kt">void</span> <span class="n">draw_point</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">tigrPlot</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">TPixel</span> <span class="n">color_white</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_black</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">screen</span> <span class="o">=</span> <span class="n">tigrWindow</span><span class="p">(</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">,</span> <span class="s">"Math 101"</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">tigrClosed</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">tigrKeyDown</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">TK_ESCAPE</span><span class="p">))</span> <span class="p">{</span>
		<span class="n">tigrClear</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">color_black</span><span class="p">());</span>
  
        <span class="n">v2</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="mi">300</span><span class="p">);</span>
        <span class="n">v2</span> <span class="n">b</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">150</span><span class="p">);</span>
        <span class="n">v2</span> <span class="n">c</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">600</span><span class="p">,</span> <span class="mi">400</span><span class="p">);</span>

		<span class="n">draw_point</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>
		<span class="n">draw_point</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>
		<span class="n">draw_point</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>

		<span class="n">tigrUpdate</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">tigrFree</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p><img src="/assets/math_101_points.png" alt="math_101_points" /></p>

<p>We can use the above rules to move these points. We can add or subtract a vector. Here’s a program to move all three white points and draw the moved ones as green offset to the right by 20 pixels.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">"tigr.h"</span><span class="cp">
</span>
<span class="k">struct</span> <span class="nc">v2</span>
<span class="p">{</span>
	<span class="n">v2</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">v2</span><span class="p">(</span><span class="kt">float</span> <span class="n">x</span><span class="p">,</span> <span class="kt">float</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">x</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">y</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span> <span class="p">}</span>
	<span class="kt">float</span> <span class="n">x</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">y</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">v2</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">-</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>

<span class="n">Tigr</span><span class="o">*</span> <span class="n">screen</span><span class="p">;</span>

<span class="kt">void</span> <span class="n">draw_point</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">tigrPlot</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">TPixel</span> <span class="n">color_white</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_black</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_red</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0xFF</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_green</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_blue</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">);</span> <span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">screen</span> <span class="o">=</span> <span class="n">tigrWindow</span><span class="p">(</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">,</span> <span class="s">"Math 101"</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">tigrClosed</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">tigrKeyDown</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">TK_ESCAPE</span><span class="p">))</span> <span class="p">{</span>
		<span class="n">tigrClear</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">color_black</span><span class="p">());</span>

		<span class="n">v2</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="mi">300</span><span class="p">);</span>
		<span class="n">v2</span> <span class="n">b</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">150</span><span class="p">);</span>
		<span class="n">v2</span> <span class="n">c</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">600</span><span class="p">,</span> <span class="mi">400</span><span class="p">);</span>

		<span class="n">draw_point</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>
		<span class="n">draw_point</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>
		<span class="n">draw_point</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>

		<span class="c1">// Draw our points moved by the `offset` with green.</span>
		<span class="n">v2</span> <span class="n">offset</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

		<span class="n">draw_point</span><span class="p">(</span><span class="n">a</span> <span class="o">+</span> <span class="n">offset</span><span class="p">,</span> <span class="n">color_green</span><span class="p">());</span>
		<span class="n">draw_point</span><span class="p">(</span><span class="n">b</span> <span class="o">+</span> <span class="n">offset</span><span class="p">,</span> <span class="n">color_green</span><span class="p">());</span>
		<span class="n">draw_point</span><span class="p">(</span><span class="n">c</span> <span class="o">+</span> <span class="n">offset</span><span class="p">,</span> <span class="n">color_green</span><span class="p">());</span>

		<span class="n">tigrUpdate</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">tigrFree</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p><img src="/assets/math_101_point_offset.png" alt="math_101_point_offset" /></p>

<h2 id="animating">Animating</h2>

<p>In games we often used what’s called an axis-aligned bounding box (or aabb for short). It means a box that’s aligned onto the x and y axis. We can define an aabb struct in a few ways by using our knowledge of points (positions) and vectors (direction).</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="c1">// Option 1.</span>
<span class="k">struct</span> <span class="nc">aabb</span>
<span class="p">{</span>
    <span class="n">v2</span> <span class="n">min</span><span class="p">;</span>
    <span class="n">v2</span> <span class="n">max</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// Option 2.</span>
<span class="k">struct</span> <span class="nc">aabb</span>
<span class="p">{</span>
    <span class="n">v2</span> <span class="n">p</span><span class="p">;</span>    <span class="c1">// position</span>
    <span class="kt">float</span> <span class="n">w</span><span class="p">;</span> <span class="c1">// width</span>
    <span class="kt">float</span> <span class="n">h</span><span class="p">;</span> <span class="c1">// height</span>
<span class="p">};</span>

<span class="c1">// Option 3.</span>
<span class="k">struct</span> <span class="nc">aabb</span>
<span class="p">{</span>
    <span class="n">v2</span> <span class="n">p</span><span class="p">;</span> <span class="c1">// position</span>
    <span class="n">v2</span> <span class="n">e</span><span class="p">;</span> <span class="c1">// extent vector (width, height)</span>
<span class="p">};</span>

<span class="c1">// Option 4.</span>
<span class="k">struct</span> <span class="nc">aabb</span>
<span class="p">{</span>
    <span class="n">v2</span> <span class="n">p</span><span class="p">;</span>  <span class="c1">// position</span>
    <span class="n">v2</span> <span class="n">he</span><span class="p">;</span> <span class="c1">// half-extent vector (width * 0.5, height * 0.5)</span>
<span class="p">};</span></code></pre></figure>

<p>Each option is functionally equivalent, but which we choose is largely up to preference. By storing 4 floats we can store the minimum amount of information necessary to represent the entire box. Since an axis aligned bounding box has four corners and a location we only need to know two opposing corners and can calculate the others from that info.</p>

<p>Option 1 stores two opposing corners, the lowest x and lowest y as a pair, and the highest x and highest y as a pair. This is my personal favorite, so let’s go with that. We can also define some useful functions for the aabb:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">float</span> <span class="nf">width</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">float</span> <span class="n">height</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">y</span><span class="p">;</span> <span class="p">}</span>
<span class="n">v2</span> <span class="n">center</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span><span class="p">;</span> <span class="p">}</span></code></pre></figure>

<p>However, for that last function to work properly we must expand our vector operations. It’s possible to multiply a vector with a scalar. A scalar means a single component number, or a float. Simply multiply with the x component, and then the y component. This adjusts the size, or scale of a vector (also known as magnitude).</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="k">operator</span><span class="o">*</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="kt">float</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">b</span><span class="p">);</span> <span class="p">}</span></code></pre></figure>

<p>In math notation the length of a vector v is <code class="language-plaintext highlighter-rouge">|v|</code>.</p>

<ul>
  <li>Magnitude is the same as length of a vector v <code class="language-plaintext highlighter-rouge">|v|</code></li>
  <li>Scale is the same as length of a vector v <code class="language-plaintext highlighter-rouge">|v|</code></li>
  <li>These terms are all synonymous</li>
</ul>

<p>When we multiply a vector v, we are multiplying each component, which in turn scales the length by the same value. We can calculate the length of a vector by utilizing the Pythagorean Theorem <code class="language-plaintext highlighter-rouge">a^2 + b^c = c^2</code>, where a, b and c are sides of a right triangle.</p>

<p><img src="/assets/pythagorean.png" alt="pythagorean" /></p>

<p>We can think of our vector’s length as c, where a and b are equal to our vectors individual components x and y. We can write down a function to solve for the hypotenuse (or the length of our vector, also known as the <em>magnitude</em>).</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;math.h&gt;</span><span class="c1"> // For sqrtf function.</span><span class="cp">
</span>
<span class="kt">float</span> <span class="nf">length</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">float</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
    <span class="kt">float</span> <span class="n">b</span> <span class="o">=</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>
    <span class="kt">float</span> <span class="n">c</span> <span class="o">=</span> <span class="n">sqrtf</span><span class="p">(</span><span class="n">a</span> <span class="o">*</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span> <span class="o">*</span> <span class="n">b</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">c</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>Or the shortened version:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">float</span> <span class="nf">len</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">sqrtf</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span></code></pre></figure>

<p>We will make use of this <code class="language-plaintext highlighter-rouge">len</code> function later. Now, back to our box drawing function, which will make use of a nifty line drawing function.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">void</span> <span class="nf">draw_line</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">tigrLine</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">a</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">a</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="n">draw_box</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">w</span> <span class="o">=</span> <span class="n">width</span><span class="p">(</span><span class="n">box</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">h</span> <span class="o">=</span> <span class="n">height</span><span class="p">(</span><span class="n">box</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">),</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">h</span><span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">),</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">h</span><span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>Make a quick mental note that the docs for <code class="language-plaintext highlighter-rouge">tigrLine</code> made it clear the last pixel is <em>not drawn</em>, so we add +1 to w/h values to draw one pixel farther.</p>

<p>And here’s the program for drawing our box.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;math.h&gt;</span><span class="cp">
#include</span> <span class="cpf">"tigr.h"</span><span class="cp">
</span>
<span class="k">struct</span> <span class="nc">v2</span>
<span class="p">{</span>
	<span class="n">v2</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">v2</span><span class="p">(</span><span class="kt">float</span> <span class="n">x</span><span class="p">,</span> <span class="kt">float</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">x</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">y</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span> <span class="p">}</span>
	<span class="kt">float</span> <span class="n">x</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">y</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">v2</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">-</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">*</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="kt">float</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">b</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">float</span> <span class="n">len</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">sqrtf</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>

<span class="k">struct</span> <span class="nc">aabb</span>
<span class="p">{</span>
	<span class="n">aabb</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">aabb</span><span class="p">(</span><span class="n">v2</span> <span class="n">min</span><span class="p">,</span> <span class="n">v2</span> <span class="n">max</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">min</span> <span class="o">=</span> <span class="n">min</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">max</span> <span class="o">=</span> <span class="n">max</span><span class="p">;</span> <span class="p">}</span>
	<span class="n">v2</span> <span class="n">min</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">max</span><span class="p">;</span>
<span class="p">};</span>

<span class="kt">float</span> <span class="n">width</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">float</span> <span class="n">height</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">y</span><span class="p">;</span> <span class="p">}</span>
<span class="n">v2</span> <span class="n">center</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span><span class="p">;</span> <span class="p">}</span>

<span class="n">Tigr</span><span class="o">*</span> <span class="n">screen</span><span class="p">;</span>

<span class="kt">void</span> <span class="n">draw_point</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span> <span class="p">{</span> <span class="n">tigrPlot</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">void</span> <span class="n">draw_line</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span> <span class="p">{</span> <span class="n">tigrLine</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">a</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">a</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span> <span class="p">}</span>

<span class="kt">void</span> <span class="n">draw_box</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">w</span> <span class="o">=</span> <span class="n">width</span><span class="p">(</span><span class="n">box</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">h</span> <span class="o">=</span> <span class="n">height</span><span class="p">(</span><span class="n">box</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">h</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">h</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">TPixel</span> <span class="n">color_white</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_black</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_red</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0xFF</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_green</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_blue</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">);</span> <span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">screen</span> <span class="o">=</span> <span class="n">tigrWindow</span><span class="p">(</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">,</span> <span class="s">"Math 101"</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">tigrClosed</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">tigrKeyDown</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">TK_ESCAPE</span><span class="p">))</span> <span class="p">{</span>
		<span class="n">tigrClear</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">color_black</span><span class="p">());</span>

		<span class="n">aabb</span> <span class="n">box</span> <span class="o">=</span> <span class="n">aabb</span><span class="p">(</span><span class="n">v2</span><span class="p">(</span><span class="mi">120</span><span class="p">,</span> <span class="mi">120</span><span class="p">),</span> <span class="n">v2</span><span class="p">(</span><span class="mi">540</span><span class="p">,</span> <span class="mi">360</span><span class="p">));</span>
		<span class="n">draw_box</span><span class="p">(</span><span class="n">box</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>

		<span class="n">tigrUpdate</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">tigrFree</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p><img src="/assets/draw_box.png" alt="draw_box" /></p>

<p>And finally let’s animate this box a bit. It’s time to introduce, time… Haha. I’m practicing my dad jokes. <code class="language-plaintext highlighter-rouge">tigrTime</code> is a nice function that returns the number of seconds since it was last called as a float. We can use it to calculate a <code class="language-plaintext highlighter-rouge">dt</code> variable once per game loop, standing for <code class="language-plaintext highlighter-rouge">delta time</code>. This will be used a whole lot later in this article for animating things and calculating movements.</p>

<p>For now we can use time and pass it into cosine and sine functions <code class="language-plaintext highlighter-rouge">cosf</code> and <code class="language-plaintext highlighter-rouge">sinf</code> from the <code class="language-plaintext highlighter-rouge">math.h</code> C runtime header. Go ahead and check out these edits to our program. I added <code class="language-plaintext highlighter-rouge">// New code!</code> comments on all the edited lines since the last version.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;math.h&gt;</span><span class="cp">
#include</span> <span class="cpf">"tigr.h"</span><span class="cp">
</span>
<span class="k">struct</span> <span class="nc">v2</span>
<span class="p">{</span>
	<span class="n">v2</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">v2</span><span class="p">(</span><span class="kt">float</span> <span class="n">x</span><span class="p">,</span> <span class="kt">float</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">x</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">y</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span> <span class="p">}</span>
	<span class="kt">float</span> <span class="n">x</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">y</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">v2</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">-</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">*</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="kt">float</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">b</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">float</span> <span class="n">len</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">sqrtf</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>

<span class="k">struct</span> <span class="nc">aabb</span>
<span class="p">{</span>
	<span class="n">aabb</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">aabb</span><span class="p">(</span><span class="n">v2</span> <span class="n">min</span><span class="p">,</span> <span class="n">v2</span> <span class="n">max</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">min</span> <span class="o">=</span> <span class="n">min</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">max</span> <span class="o">=</span> <span class="n">max</span><span class="p">;</span> <span class="p">}</span>
	<span class="n">v2</span> <span class="n">min</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">max</span><span class="p">;</span>
<span class="p">};</span>

<span class="kt">float</span> <span class="n">width</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">float</span> <span class="n">height</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">y</span><span class="p">;</span> <span class="p">}</span>
<span class="n">v2</span> <span class="n">center</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span><span class="p">;</span> <span class="p">}</span>

<span class="n">Tigr</span><span class="o">*</span> <span class="n">screen</span><span class="p">;</span>

<span class="kt">void</span> <span class="n">draw_point</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span> <span class="p">{</span> <span class="n">tigrPlot</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">void</span> <span class="n">draw_line</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span> <span class="p">{</span> <span class="n">tigrLine</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">a</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">a</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span> <span class="p">}</span>

<span class="kt">void</span> <span class="n">draw_box</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">w</span> <span class="o">=</span> <span class="n">width</span><span class="p">(</span><span class="n">box</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">h</span> <span class="o">=</span> <span class="n">height</span><span class="p">(</span><span class="n">box</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">h</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">h</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">TPixel</span> <span class="n">color_white</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_black</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_red</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0xFF</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_green</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_blue</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">);</span> <span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">screen</span> <span class="o">=</span> <span class="n">tigrWindow</span><span class="p">(</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">,</span> <span class="s">"Math 101"</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="kt">float</span> <span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// New code!</span>
	<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">tigrClosed</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">tigrKeyDown</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">TK_ESCAPE</span><span class="p">))</span> <span class="p">{</span>
		<span class="kt">float</span> <span class="n">dt</span> <span class="o">=</span> <span class="n">tigrTime</span><span class="p">();</span> <span class="c1">// New code!</span>
		<span class="n">t</span> <span class="o">+=</span> <span class="n">dt</span><span class="p">;</span> <span class="c1">// New code!</span>
		<span class="n">tigrClear</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">color_black</span><span class="p">());</span>

		<span class="n">aabb</span> <span class="n">box</span> <span class="o">=</span> <span class="n">aabb</span><span class="p">(</span><span class="n">v2</span><span class="p">(</span><span class="mi">120</span><span class="p">,</span> <span class="mi">120</span><span class="p">),</span> <span class="n">v2</span><span class="p">(</span><span class="mi">540</span><span class="p">,</span> <span class="mi">360</span><span class="p">));</span>
		<span class="n">v2</span> <span class="n">offset</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">cosf</span><span class="p">(</span><span class="n">t</span><span class="p">),</span> <span class="n">sinf</span><span class="p">(</span><span class="n">t</span><span class="p">))</span> <span class="o">*</span> <span class="mf">100.0</span><span class="n">f</span><span class="p">;</span> <span class="c1">// New code!</span>
		<span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">=</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span> <span class="c1">// New code!</span>
		<span class="n">box</span><span class="p">.</span><span class="n">max</span> <span class="o">=</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span> <span class="o">+</span> <span class="n">offset</span><span class="p">;</span> <span class="c1">// New code!</span>
		<span class="n">draw_box</span><span class="p">(</span><span class="n">box</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>

		<span class="n">tigrUpdate</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">tigrFree</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p><img src="/assets/morphing_box.gif" alt="morphing_box" /></p>

<h2 id="transforming-to-screen-space">Transforming to Screen Space</h2>

<p>When we’re talking about games and math the word transform means to go from one coordinate space to another. You’re likely already familiar with the <a href="https://en.wikipedia.org/wiki/Cartesian_coordinate_system">traditional 2D cartesian space</a>, whether or not you’re familiar with the terminology. There are two axes, one for x and one for y. However, it’s possible to take that 2D space and transform it to another space.</p>

<p>The types of transformation we will cover later include:</p>

<ul>
  <li>Translation</li>
  <li>Scaling (also includes flipping/mirroring)</li>
  <li>Rotating</li>
</ul>

<p>For now we’ll just cover some translating and flipping. In the math_101 program our coordinate space has the origin at the top-left pixel with the y-axis pointing downward. Though, most games use a different coordinate space for the screen where the origin is at the center, and the y-axis is pointing upwards. We want to use math to transform the screen to this new form.</p>

<p><img src="/assets/screen_basis_transform.png" alt="screen_basis_transform" /></p>

<p>To perform this transformation we can start by negating the y-axis. This will make the y-axis point upwards. We can start writing a function called <code class="language-plaintext highlighter-rouge">world_to_screen</code>, which will take a point in our game world with the origin at center of the screen, to the screen coordinates we’ve been using so far.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">world_to_screen</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">p</span><span class="p">.</span><span class="n">y</span> <span class="o">=</span> <span class="o">-</span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">p</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>The next step would be to offset the point by half the screen width and half the screen height, placing points that were originally at (0, 0) at (screen_width / 2, screen_height / 2).</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">world_to_screen</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">p</span><span class="p">.</span><span class="n">y</span> <span class="o">=</span> <span class="o">-</span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">half_screen_width</span> <span class="o">=</span> <span class="mf">640.0</span><span class="n">f</span> <span class="o">/</span> <span class="mf">2.0</span><span class="n">f</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">half_screen_height</span> <span class="o">=</span> <span class="mf">480.0</span><span class="n">f</span> <span class="o">/</span> <span class="mf">2.0</span><span class="n">f</span><span class="p">;</span>
	<span class="n">p</span><span class="p">.</span><span class="n">x</span> <span class="o">+=</span> <span class="n">half_screen_width</span><span class="p">;</span>
	<span class="n">p</span><span class="p">.</span><span class="n">y</span> <span class="o">+=</span> <span class="n">half_screen_height</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">p</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>Now we can hook this function into all of our drawing functions so far. If it works, we should be able to draw a box centered at (0, 0) and have it appear in the center of the screen. It’s also a convenient time to implement operators for <code class="language-plaintext highlighter-rouge">+=</code>, <code class="language-plaintext highlighter-rouge">-=</code>, <code class="language-plaintext highlighter-rouge">*=</code>, and division operators <code class="language-plaintext highlighter-rouge">/</code> and <code class="language-plaintext highlighter-rouge">/=</code>.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">+=</span><span class="p">(</span><span class="n">v2</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="k">return</span> <span class="n">a</span><span class="p">;</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">-</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">-=</span><span class="p">(</span><span class="n">v2</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="k">return</span> <span class="n">a</span><span class="p">;</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">*</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="kt">float</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">b</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">*=</span><span class="p">(</span><span class="n">v2</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="kt">float</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">b</span><span class="p">);</span> <span class="k">return</span> <span class="n">a</span><span class="p">;</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">/</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="kt">float</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">/</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">/</span> <span class="n">b</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">/=</span><span class="p">(</span><span class="n">v2</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="kt">float</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">/</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">/</span> <span class="n">b</span><span class="p">);</span> <span class="k">return</span> <span class="n">a</span><span class="p">;</span> <span class="p">}</span></code></pre></figure>

<p>Our code is getting a bit big, so for now let’s bundle things up into a header called <code class="language-plaintext highlighter-rouge">math_101.h</code>. We can place all of our math struct types like <code class="language-plaintext highlighter-rouge">v2</code>, <code class="language-plaintext highlighter-rouge">aabb</code>, and any other that come along later. Here is our current version of <code class="language-plaintext highlighter-rouge">math_101.h</code>.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">v2</span>
<span class="p">{</span>
	<span class="n">v2</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">v2</span><span class="p">(</span><span class="kt">float</span> <span class="n">x</span><span class="p">,</span> <span class="kt">float</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">x</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">y</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span> <span class="p">}</span>
	<span class="kt">float</span> <span class="n">x</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">y</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">v2</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">+=</span><span class="p">(</span><span class="n">v2</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="k">return</span> <span class="n">a</span><span class="p">;</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">-</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">-=</span><span class="p">(</span><span class="n">v2</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="k">return</span> <span class="n">a</span><span class="p">;</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">*</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="kt">float</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">b</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">*=</span><span class="p">(</span><span class="n">v2</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="kt">float</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">b</span><span class="p">);</span> <span class="k">return</span> <span class="n">a</span><span class="p">;</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">/</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="kt">float</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">/</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">/</span> <span class="n">b</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="k">operator</span><span class="o">/=</span><span class="p">(</span><span class="n">v2</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="kt">float</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">/</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">/</span> <span class="n">b</span><span class="p">);</span> <span class="k">return</span> <span class="n">a</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">float</span> <span class="n">len</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">sqrtf</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>

<span class="k">struct</span> <span class="nc">aabb</span>
<span class="p">{</span>
	<span class="n">aabb</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">aabb</span><span class="p">(</span><span class="n">v2</span> <span class="n">min</span><span class="p">,</span> <span class="n">v2</span> <span class="n">max</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">min</span> <span class="o">=</span> <span class="n">min</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">max</span> <span class="o">=</span> <span class="n">max</span><span class="p">;</span> <span class="p">}</span>
	<span class="n">v2</span> <span class="n">min</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">max</span><span class="p">;</span>
<span class="p">};</span>

<span class="kt">float</span> <span class="n">width</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">float</span> <span class="n">height</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">y</span><span class="p">;</span> <span class="p">}</span>
<span class="n">v2</span> <span class="n">center</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span><span class="p">;</span> <span class="p">}</span></code></pre></figure>

<p>The drawing functions can be placed into a header file called <code class="language-plaintext highlighter-rouge">draw.h</code> that looks like this:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">Tigr</span><span class="o">*</span> <span class="n">screen</span><span class="p">;</span>

<span class="n">v2</span> <span class="nf">world_to_screen</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">p</span><span class="p">.</span><span class="n">y</span> <span class="o">=</span> <span class="o">-</span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">half_screen_width</span> <span class="o">=</span> <span class="mf">640.0</span><span class="n">f</span> <span class="o">/</span> <span class="mf">2.0</span><span class="n">f</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">half_screen_height</span> <span class="o">=</span> <span class="mf">480.0</span><span class="n">f</span> <span class="o">/</span> <span class="mf">2.0</span><span class="n">f</span><span class="p">;</span>
	<span class="n">p</span><span class="p">.</span><span class="n">x</span> <span class="o">+=</span> <span class="n">half_screen_width</span><span class="p">;</span>
	<span class="n">p</span><span class="p">.</span><span class="n">y</span> <span class="o">+=</span> <span class="n">half_screen_height</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">p</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="n">draw_point</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">p</span> <span class="o">=</span> <span class="n">world_to_screen</span><span class="p">(</span><span class="n">p</span><span class="p">);</span>
	<span class="n">tigrPlot</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="n">draw_line</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">a</span> <span class="o">=</span> <span class="n">world_to_screen</span><span class="p">(</span><span class="n">a</span><span class="p">);</span>
	<span class="n">b</span> <span class="o">=</span> <span class="n">world_to_screen</span><span class="p">(</span><span class="n">b</span><span class="p">);</span>
	<span class="n">tigrLine</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">a</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">a</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="n">draw_box</span><span class="p">(</span><span class="n">aabb</span> <span class="n">box</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">w</span> <span class="o">=</span> <span class="n">width</span><span class="p">(</span><span class="n">box</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">h</span> <span class="o">=</span> <span class="n">height</span><span class="p">(</span><span class="n">box</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">min</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">h</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">box</span><span class="p">.</span><span class="n">max</span><span class="p">,</span> <span class="n">box</span><span class="p">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">h</span><span class="p">),</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">TPixel</span> <span class="n">color_white</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_black</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_red</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mh">0xFF</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_green</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span>
<span class="n">TPixel</span> <span class="n">color_blue</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">tigrRGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">);</span> <span class="p">}</span></code></pre></figure>

<p>And our current <code class="language-plaintext highlighter-rouge">main.cpp</code> program looks like this:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;math.h&gt;</span><span class="cp">
#include</span> <span class="cpf">"tigr.h"</span><span class="cp">
#include</span> <span class="cpf">"math_101.h"</span><span class="cp">
#include</span> <span class="cpf">"draw.h"</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">screen</span> <span class="o">=</span> <span class="n">tigrWindow</span><span class="p">(</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">,</span> <span class="s">"Math 101"</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="n">aabb</span> <span class="n">red_box</span> <span class="o">=</span> <span class="n">aabb</span><span class="p">(</span><span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mi">50</span><span class="p">,</span> <span class="o">-</span><span class="mi">50</span><span class="p">),</span> <span class="n">v2</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span> <span class="mi">50</span><span class="p">));</span>
	<span class="n">aabb</span> <span class="n">blue_box</span> <span class="o">=</span> <span class="n">aabb</span><span class="p">(</span><span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mi">50</span><span class="p">,</span> <span class="o">-</span><span class="mi">50</span><span class="p">),</span> <span class="n">v2</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span> <span class="mi">50</span><span class="p">));</span>
	<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">tigrClosed</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">tigrKeyDown</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">TK_ESCAPE</span><span class="p">))</span> <span class="p">{</span>
		<span class="kt">float</span> <span class="n">dt</span> <span class="o">=</span> <span class="n">tigrTime</span><span class="p">();</span>
		<span class="n">tigrClear</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">color_black</span><span class="p">());</span>

		<span class="n">red_box</span><span class="p">.</span><span class="n">min</span> <span class="o">+=</span> <span class="n">v2</span><span class="p">(</span><span class="mf">30.0</span><span class="n">f</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">*</span> <span class="n">dt</span><span class="p">;</span>
		<span class="n">red_box</span><span class="p">.</span><span class="n">max</span> <span class="o">+=</span> <span class="n">v2</span><span class="p">(</span><span class="mf">30.0</span><span class="n">f</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">*</span> <span class="n">dt</span><span class="p">;</span>
		<span class="n">blue_box</span><span class="p">.</span><span class="n">min</span> <span class="o">+=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">30.0</span><span class="n">f</span><span class="p">)</span> <span class="o">*</span> <span class="n">dt</span><span class="p">;</span>
		<span class="n">blue_box</span><span class="p">.</span><span class="n">max</span> <span class="o">+=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">30.0</span><span class="n">f</span><span class="p">)</span> <span class="o">*</span> <span class="n">dt</span><span class="p">;</span>
		<span class="n">draw_box</span><span class="p">(</span><span class="n">red_box</span><span class="p">,</span> <span class="n">color_red</span><span class="p">());</span>
		<span class="n">draw_box</span><span class="p">(</span><span class="n">blue_box</span><span class="p">,</span> <span class="n">color_blue</span><span class="p">());</span>

		<span class="n">tigrUpdate</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">tigrFree</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>When run it will show a red box traveling along our new x-axis starting at the origin, and a blue box traveling along the new y-axis at our new origin.</p>

<p><img src="/assets/box_axes_visualize.gif" alt="box_axes_visualize.gif" /></p>

<p>From here on when we write new math code you can follow along and place it into the <code class="language-plaintext highlighter-rouge">math_101.h</code> header! Drawing related functions can go into <code class="language-plaintext highlighter-rouge">draw.h</code>. The red box is traveling at 30 pixels per second. We can see this from the expression <code class="language-plaintext highlighter-rouge">v2(30.0f, 0) * dt</code>. Whenever we multiply something by dt, it can be read like “over one second”. In this case it’s 30 pixels per second.</p>

<blockquote>
  <p>NOTE: Those more familiar with C might notice no include guards were used. Don’t worry about this for now; it’s more important to just focus on the math and pump out more code. Our program is just one-file conceptually, and we’re only splitting it up into different files to make following this article easier. TODO - Link to GitHub repo of final demo.</p>
</blockquote>

<h2 id="rotations">Rotations</h2>

<p>Rotations are actually much more easy to perform than they are to learn about. Here comes another one of those rules to burn into your mind: <em>rotations are always done about the origin</em>. This is the truth. Here is how we rotate a vector or point about the origin given an angle in <a href="https://mathworld.wolfram.com/Radian.html#:~:text=The%20radian%20is%20a%20unit,or%2057.">radians</a>.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">rotate</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">,</span> <span class="kt">float</span> <span class="n">radians</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">s</span> <span class="o">=</span> <span class="n">sinf</span><span class="p">(</span><span class="n">radians</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">c</span> <span class="o">=</span> <span class="n">cosf</span><span class="p">(</span><span class="n">radians</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">c</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">s</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">s</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">c</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>The first step to understanding rotations is to understand sin and cos functions. For a quick refresher I recommend this page over at <a href="https://www.mathsisfun.com/geometry/unit-circle.html">mathisfun on the unit circle</a>.</p>

<p><img src="/assets/unit_circle.png" alt="unit_circle.png" /></p>

<p>For any vector on the unit circle its length is 1. We can calculate the x and y components of this unit vector with the sin and cos function by providing the angle in radians.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">vector_on_unit_circle_from_angle</span><span class="p">(</span><span class="kt">float</span> <span class="n">radians</span><span class="p">)</span>
<span class="p">{</span>
	<span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">cosf</span><span class="p">(</span><span class="n">radians</span><span class="p">),</span> <span class="n">sinf</span><span class="p">(</span><span class="n">radians</span><span class="p">));</span>
<span class="p">}</span></code></pre></figure>

<p>We can think of this as rotating the x-axis (1, 0) by an angle (remember, when writing code <code class="language-plaintext highlighter-rouge">cosf</code> and <code class="language-plaintext highlighter-rouge">sinf</code> functions work in radians mode). Similarly, we can think about how to rotate the y-axis by the same angle, and we would get a similar result of (-sin(radians), cos(radians)). One way to realize this is from a useful function called <code class="language-plaintext highlighter-rouge">skew</code>.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">skew</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="n">a</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">x</span><span class="p">);</span> <span class="p">}</span></code></pre></figure>

<p><img src="/assets/skew_2d.png" alt="skew_2d.png" /></p>

<p>It returns vector rotated by 90 degrees counter-clockwise. To rotate a vector 90 degrees counter-clockwise we flip the x and y components, and negate the x final component. It comes from the concept of a skew-symmetric matrix, one that can <a href="https://en.wikipedia.org/wiki/Skew-symmetric_matrix#Cross_product">perform a cross-product</a>. Other names include pseudo-cross product, or perp-dot product (standing for perpendicular). We won’t really go over these, I’m just mentioning them for anyone curious what the names mean.</p>

<p>As it turns out, whenever we write down any vector, a such as (1, 2) or (10, -13) we are using what’s called a <a href="https://en.wikipedia.org/wiki/Basis_(linear_algebra)">basis</a>, or a <a href="https://findnerd.com/list/view/Computer-Graphics-Different-Spaces/6982/">space</a>. Our vectors are not merely (1, 2) or (10, -13), they are actually expressed as multipliers of the x and y axes.</p>

<p>(1, 2) and (10, -13) aren’t special vectors or anything, I just chose them as random examples.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>10 * x-axis + -13 * y-axis
</code></pre></div></div>

<p>Thinking about how the x-axis is (1, 0) and the y-axis is (0, 1) we can substitute in these values (which are just 1).</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>10 * (1, 0) + -13 * (0, 1)
=  (10 * 1, -13 * 1)
=  (10, -13)
</code></pre></div></div>

<p>And that gets us back to where we started.</p>

<p>Seems pretty silly, right? All that extra work for nothing! Well, when we think about rotations we’re actually rotating the entire coordinate system. The coordinate system (the <a href="https://en.wikipedia.org/wiki/Cartesian_coordinate_system">cartesian grid</a> we talked about earlier) is defined by the x-axis and the y-axis, so we’re actually rotating these two axes when we do a rotation.</p>

<p><img src="/assets/basis_rotation.png" alt="basis_rotation.png" /></p>

<p>Let’s use the terms i and j for representing a number relative to a basis. Taking our example vector of (10, -13) we can write it down as it would be shown in left-hand diagram as 10 * i + -13 * j. So what would i and j be for the rotated basis (x’, 0) + (0, y’) by an angle <code class="language-plaintext highlighter-rouge">a</code>? From our understanding of the unit circle the x-axis would be (cos(a), sin(a)). We can use this for our i vector. To get the j vector we rotate the x-axis by 90 degrees counter-clockwise using our skew function and get (-sin(a), cos(a)). To represent (10, -13) relative to our new i and j vectors we just use the formula from earlier.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>10 * i + -13 * j
i = (cos(a), sin(a))
j = (-sin(a), cos(a))

substitute in =&gt;

10 * (cos(a), sin(a))
-13 * (-sin(a), cos(a)))
</code></pre></div></div>

<p>And there we have it! Rotating a vector by an angle is the same as expressing the vector in a rotated coordinate frame (or basis). We can rotate any vector by changing 10 and -13 to x and y input variables to arrive back at our original function.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">rotate</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">,</span> <span class="kt">float</span> <span class="n">a</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">s</span> <span class="o">=</span> <span class="n">sinf</span><span class="p">(</span><span class="n">a</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">c</span> <span class="o">=</span> <span class="n">cosf</span><span class="p">(</span><span class="n">a</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">c</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">s</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">s</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">c</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>If this was all over your head don’t sweat it. You can just use the <code class="language-plaintext highlighter-rouge">rotate</code> function as a black-box without understanding the internals and that’s a totally valid way to make games. As long as you memorize the rules you’ll be good to go, such as the rule we mentioned at the beginning of this section: <em>rotations are always performed about the origin</em>.</p>

<p>But what if we want to rotate around some other point? For example say we want to create a special effect where a ball of light is circling around an enemy somewhere on the screen other than the origin? It turns out there’s a very simple solution. Just translate the enemy’s location to the origin, apply the rotation, then translate back.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">rotate_point_a_around_point_b</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="kt">float</span> <span class="n">radians</span><span class="p">)</span>
<span class="p">{</span>
	<span class="c1">// Compute cosine and sine values for our i and j vectors.</span>
	<span class="kt">float</span> <span class="n">c</span> <span class="o">=</span> <span class="n">cosf</span><span class="p">(</span><span class="n">radians</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">s</span> <span class="o">=</span> <span class="n">sinf</span><span class="p">(</span><span class="n">radians</span><span class="p">);</span>

	<span class="c1">// Translate so that b is the origin.</span>
	<span class="n">a</span> <span class="o">=</span> <span class="n">a</span> <span class="o">-</span> <span class="n">b</span><span class="p">;</span> 

	<span class="c1">// Rotate a around the origin.</span>
	<span class="c1">// a' = a.x * i + a.y * j</span>
	<span class="c1">// where i = (c, s), j = (-s, c)</span>
	<span class="c1">// substitute =&gt;</span>
	<span class="c1">// a' = a.x * (c, s) + a.y * (-s, c)</span>
	<span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">c</span> <span class="o">*</span> <span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">s</span> <span class="o">*</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">s</span> <span class="o">*</span> <span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">c</span> <span class="o">*</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span><span class="p">);</span>

	<span class="c1">// Translate back to b.</span>
	<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>The functions <code class="language-plaintext highlighter-rouge">cosf</code> and <code class="language-plaintext highlighter-rouge">sinf</code> are quite fast on modern processors, but still should be thought of as an order of magnitude (10x) slower than a normal float multiply. Therefore it’s going to be preferable to precompute these values whenever we can and store them. A good way for our math library to make use of rotations is to make a struct representing a rotation. It can be multiplied with vectors to rotate them by an angle.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">rotation</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">s</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">c</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">rotation</span> <span class="n">sincos</span><span class="p">(</span><span class="kt">float</span> <span class="n">a</span><span class="p">)</span> <span class="p">{</span> <span class="n">rotation</span> <span class="n">r</span><span class="p">;</span> <span class="n">r</span><span class="p">.</span><span class="n">c</span> <span class="o">=</span> <span class="n">cosf</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> <span class="n">r</span><span class="p">.</span><span class="n">s</span> <span class="o">=</span> <span class="n">sinf</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> <span class="k">return</span> <span class="n">r</span><span class="p">;</span> <span class="p">}</span>
<span class="n">v2</span> <span class="n">mul</span><span class="p">(</span><span class="n">rotation</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">c</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">a</span><span class="p">.</span><span class="n">s</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">s</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">a</span><span class="p">.</span><span class="n">c</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span></code></pre></figure>

<p>We can build a <code class="language-plaintext highlighter-rouge">rotation</code> by calling <code class="language-plaintext highlighter-rouge">sincos</code>, and then rotate a vector with it by calling <code class="language-plaintext highlighter-rouge">mul</code>. Alternatively you could implement an <code class="language-plaintext highlighter-rouge">operator*</code> to perform rotations, however I recommend using a <code class="language-plaintext highlighter-rouge">mul</code> function for a few reasons.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">mul</code> can be easily overloaded without modifying the “class definition”. Just simply add more <code class="language-plaintext highlighter-rouge">mul</code> functions later on for different kinds of operations.</li>
  <li>Post-multiplication or pre-multiplication (e.g. 5 * x vs x * 5) can be expressed in a more explicit manner. For example if we write a * b * c, what is the order of operations supposed to be? Of course the C/C++ programming languages clearly define the order of operations, but if we’re writing down hand-written math notes and want to transcribe it into code, it’s in my opinion more clear what the intent is if we write down mul(a, mul(b, c)) or mul(mul(a, b), c). This distinction matters a lot later down the line when we are dealing with transforms and matrices, where multiplication is <a href="https://en.wikipedia.org/wiki/Commutative_property">non-commutative</a>.</li>
</ul>

<p>It’s time to throw our rotation functions into practice and generate a bunch lines rotated around the origin like the spokes of a bicycle wheel.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;math.h&gt;</span><span class="cp">
#include</span> <span class="cpf">"tigr.h"</span><span class="cp">
#include</span> <span class="cpf">"math_101.h"</span><span class="cp">
#include</span> <span class="cpf">"draw.h"</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">screen</span> <span class="o">=</span> <span class="n">tigrWindow</span><span class="p">(</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">,</span> <span class="s">"Math 101"</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="kt">float</span> <span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">tigrClosed</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">tigrKeyDown</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">TK_ESCAPE</span><span class="p">))</span> <span class="p">{</span>
		<span class="kt">float</span> <span class="n">dt</span> <span class="o">=</span> <span class="n">tigrTime</span><span class="p">();</span>
		<span class="n">t</span> <span class="o">+=</span> <span class="n">dt</span><span class="p">;</span>
		<span class="n">tigrClear</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">color_black</span><span class="p">());</span>

		<span class="n">v2</span> <span class="n">p</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mf">100.0</span><span class="n">f</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
		<span class="n">rotation</span> <span class="n">r</span> <span class="o">=</span> <span class="n">sincos</span><span class="p">(</span><span class="n">t</span> <span class="o">*</span> <span class="mf">0.01</span><span class="n">f</span><span class="p">);</span>
		<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">32</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">draw_line</span><span class="p">(</span><span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">p</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>
			<span class="n">p</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
		<span class="p">}</span>

		<span class="n">tigrUpdate</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">tigrFree</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p><img src="/assets/spokes.gif" alt="spokes.gif" /></p>

<h2 id="unit-vectors--normalization">Unit Vectors + Normalization</h2>

<p>You must have this super useful vector drawing function in your rendering arsenal. Used to visualize vectors at a specific location (remember, a vector is merely a direction, as drawing a vector must happen at a location), the vector drawing function can save us from many headaches down the line whenever we must debug our code and figure out what’s going on.</p>

<p>By taking an input vector and position we can draw an arrow shape on the screen. The arrowhead will show us which way the vector is facing. We can provide a scale factor to the function to adjust the size of the arrowhead. The way it works is we calculate by-hand the arrow’s position when it’s sitting along the x-axis. Using our newfound knowledge on rotations we can then rotate all of the points that define the arrow about the origin, and then translate them to the position as a final step. Remember, <em>rotations always happen about the origin</em>. If we translate first then rotate the results will be wrong. I encourage you to try this out as an experiment and see what it looks like!</p>

<p>We need some help from a helpful function called <a href="https://en.wikipedia.org/wiki/Atan2">atan2</a>, the function used to compute the angle from the x-axis to a vector.</p>

<p><img src="/assets/atan2.png" alt="atan2.png" /></p>

<p>Since atan2 returns a number from pi to -pi it’s often helpful to remap this from 0 to 2 * pi by adding pi to the result of atan2. Let’s implement a few overloads for our own <code class="language-plaintext highlighter-rouge">atan2_360</code> function, which returns a value from 0 to 2 * pi (or 360 degrees). It’s definitely appropriate to black-box the atan2 function and not worry too much about how it works.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">float</span> <span class="nf">atan2_360</span><span class="p">(</span><span class="kt">float</span> <span class="n">y</span><span class="p">,</span> <span class="kt">float</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">atan2f</span><span class="p">(</span><span class="o">-</span><span class="n">y</span><span class="p">,</span> <span class="o">-</span><span class="n">x</span><span class="p">)</span> <span class="o">+</span> <span class="mf">3.14159265</span><span class="n">f</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">float</span> <span class="n">atan2_360</span><span class="p">(</span><span class="n">rotation</span> <span class="n">r</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">atan2_360</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">s</span><span class="p">,</span> <span class="n">r</span><span class="p">.</span><span class="n">c</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">float</span> <span class="n">atan2_360</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">atan2f</span><span class="p">(</span><span class="o">-</span><span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="o">-</span><span class="n">v</span><span class="p">.</span><span class="n">x</span><span class="p">)</span> <span class="o">+</span> <span class="mf">3.14159265</span><span class="n">f</span><span class="p">;</span> <span class="p">}</span></code></pre></figure>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">void</span> <span class="nf">draw_vector</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">v2</span> <span class="n">v</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">arrow</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
		<span class="n">v2</span><span class="p">(</span><span class="mf">0.0</span><span class="n">f</span><span class="p">,</span> <span class="mf">0.0</span><span class="n">f</span><span class="p">),</span>
		<span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mf">5.0</span><span class="n">f</span><span class="p">,</span> <span class="mf">5.0</span><span class="n">f</span><span class="p">),</span>
		<span class="n">v2</span><span class="p">(</span><span class="mf">0.0</span><span class="n">f</span><span class="p">,</span> <span class="mf">0.0</span><span class="n">f</span><span class="p">),</span>
		<span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mf">5.0</span><span class="n">f</span><span class="p">,</span> <span class="o">-</span><span class="mf">5.0</span><span class="n">f</span><span class="p">),</span>
	<span class="p">};</span>
	<span class="n">rotation</span> <span class="n">r</span> <span class="o">=</span> <span class="n">sincos</span><span class="p">(</span><span class="n">atan2_360</span><span class="p">(</span><span class="n">v</span><span class="p">));</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">arrow</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">arrow</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
		<span class="n">arrow</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">p</span> <span class="o">+</span> <span class="n">v</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">arrow</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">arrow</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">arrow</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">arrow</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">p</span> <span class="o">+</span> <span class="n">v</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p><img src="/assets/draw_arrow.png" alt="draw_arrow.png" /></p>

<p>However, we can optimize the <code class="language-plaintext highlighter-rouge">draw_vector</code> function by not using atan2 at all. We can calculate the rotation directly with a little bit of math. Using the knowledge from the previous section about rotations we can just write down the formula for sin and cos values needed to rotate the x-axis to an any vector without calling into <code class="language-plaintext highlighter-rouge">cosf</code>, <code class="language-plaintext highlighter-rouge">sinf</code> or <code class="language-plaintext highlighter-rouge">atan2f</code>.</p>

<p>Recall from the previous section on rotations for how to rotate the x-axis by an angle.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x = (1, 0) // The x-axis.
a = angle
x' = (1 * cos(a) - 0 * sin(a), 1 * sin(a) + 0 * cos(a))
</code></pre></div></div>

<p>We already know x’, it’s the <code class="language-plaintext highlighter-rouge">v</code> vector we want to draw. We can see that v.x = cos(a) and v.y = sin(a). Since we already know sin(a) and cos(a) we can skip atan2 and directly create a rotation. However, our function <code class="language-plaintext highlighter-rouge">draw_vector</code> works with non-unit vectors <code class="language-plaintext highlighter-rouge">v</code>. We can deal with non-unit vectors (vectors whose lengths are not 1) by normalizing the v. Normalization is the process of computing a vector’s length then dividing the vector by the length. This returns a unit vector pointing in the direction the original vector was pointing. Let’s call it <code class="language-plaintext highlighter-rouge">norm</code> for shorthand.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">norm</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="kt">float</span> <span class="n">l</span> <span class="o">=</span> <span class="n">len</span><span class="p">(</span><span class="n">v</span><span class="p">);</span> <span class="k">return</span> <span class="n">v</span> <span class="o">*</span> <span class="p">(</span><span class="mf">1.0</span><span class="n">f</span> <span class="o">/</span> <span class="n">l</span><span class="p">);</span> <span class="p">}</span></code></pre></figure>

<p>We can normalize v before grabbing it’s x and y components and treating them as sin/cos values.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="c1">// In math_101.h ...</span>
<span class="k">struct</span> <span class="nc">rotation</span>
<span class="p">{</span>
	<span class="c1">// Add some constructors here.</span>
	<span class="n">rotation</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">rotation</span><span class="p">(</span><span class="kt">float</span> <span class="n">angle</span><span class="p">)</span> <span class="p">{</span> <span class="n">s</span> <span class="o">=</span> <span class="n">sinf</span><span class="p">(</span><span class="n">angle</span><span class="p">);</span> <span class="n">c</span> <span class="o">=</span> <span class="n">sinf</span><span class="p">(</span><span class="n">angle</span><span class="p">);</span> <span class="p">}</span>
	<span class="n">rotation</span><span class="p">(</span><span class="kt">float</span> <span class="n">s</span><span class="p">,</span> <span class="kt">float</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">s</span> <span class="o">=</span> <span class="n">s</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">c</span> <span class="o">=</span> <span class="n">c</span><span class="p">;</span> <span class="p">}</span>
	<span class="kt">float</span> <span class="n">s</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">c</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// In draw.h ...</span>
<span class="kt">void</span> <span class="n">draw_vector</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">v2</span> <span class="n">v</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">arrow</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
		<span class="n">v2</span><span class="p">(</span><span class="mf">0.0</span><span class="n">f</span><span class="p">,</span> <span class="mf">0.0</span><span class="n">f</span><span class="p">),</span>
		<span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mf">5.0</span><span class="n">f</span><span class="p">,</span> <span class="mf">5.0</span><span class="n">f</span><span class="p">),</span>
		<span class="n">v2</span><span class="p">(</span><span class="mf">0.0</span><span class="n">f</span><span class="p">,</span> <span class="mf">0.0</span><span class="n">f</span><span class="p">),</span>
		<span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mf">5.0</span><span class="n">f</span><span class="p">,</span> <span class="o">-</span><span class="mf">5.0</span><span class="n">f</span><span class="p">),</span>
	<span class="p">};</span>
	<span class="n">v2</span> <span class="n">n</span> <span class="o">=</span> <span class="n">norm</span><span class="p">(</span><span class="n">v</span><span class="p">);</span>
	<span class="n">rotation</span> <span class="n">r</span> <span class="o">=</span> <span class="n">rotation</span><span class="p">(</span><span class="n">n</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">n</span><span class="p">.</span><span class="n">x</span><span class="p">);</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">arrow</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">arrow</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
		<span class="n">arrow</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">p</span> <span class="o">+</span> <span class="n">v</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">arrow</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">arrow</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">arrow</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">arrow</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">p</span> <span class="o">+</span> <span class="n">v</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>Congratulations! You just optimized away <code class="language-plaintext highlighter-rouge">atan2f</code>, <code class="language-plaintext highlighter-rouge">sinf</code> and <code class="language-plaintext highlighter-rouge">cosf</code> calls and replaced them with a single <code class="language-plaintext highlighter-rouge">sqrtf</code> call (inside of our <code class="language-plaintext highlighter-rouge">len</code> and <code class="language-plaintext highlighter-rouge">norm</code> functions)!</p>

<p>The final thing we can change is adding in a scale value. Recall from earlier that scaling a vector is merely multiplying it’s components by the scale factor. Sear this rule into your brain: <em>scaling happens about the origin</em>. Period. If you wish to scale about another point simply translate to the origin first, then translate back after.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">void</span> <span class="nf">draw_vector</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">v2</span> <span class="n">v</span><span class="p">,</span> <span class="n">TPixel</span> <span class="n">color</span><span class="p">,</span> <span class="kt">float</span> <span class="n">scale</span> <span class="o">=</span> <span class="mf">5.0</span><span class="n">f</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">arrow</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
		<span class="n">v2</span><span class="p">(</span><span class="mf">0.0</span><span class="n">f</span><span class="p">,</span> <span class="mf">0.0</span><span class="n">f</span><span class="p">),</span>
		<span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mf">1.0</span><span class="n">f</span><span class="p">,</span> <span class="mf">1.0</span><span class="n">f</span><span class="p">),</span>
		<span class="n">v2</span><span class="p">(</span><span class="mf">0.0</span><span class="n">f</span><span class="p">,</span> <span class="mf">0.0</span><span class="n">f</span><span class="p">),</span>
		<span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mf">1.0</span><span class="n">f</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.0</span><span class="n">f</span><span class="p">),</span>
	<span class="p">};</span>
	<span class="n">v2</span> <span class="n">n</span> <span class="o">=</span> <span class="n">norm</span><span class="p">(</span><span class="n">v</span><span class="p">);</span>
	<span class="n">rotation</span> <span class="n">r</span> <span class="o">=</span> <span class="n">rotation</span><span class="p">(</span><span class="n">n</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">n</span><span class="p">.</span><span class="n">x</span><span class="p">);</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">arrow</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="n">scale</span><span class="p">;</span>           <span class="c1">// Scale first (about the origin).</span>
		<span class="n">arrow</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">arrow</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> <span class="c1">// Then rotate (about the origin).</span>
		<span class="n">arrow</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">p</span> <span class="o">+</span> <span class="n">v</span><span class="p">;</span>           <span class="c1">// And finally translate.</span>
	<span class="p">}</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">arrow</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">arrow</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">arrow</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">arrow</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="n">color</span><span class="p">);</span>
	<span class="n">draw_line</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">p</span> <span class="o">+</span> <span class="n">v</span><span class="p">,</span> <span class="n">color</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>This function scales the arrowhead about the origin, then rotate’s about the origin, and finally translates.</p>

<h2 id="dot-product">Dot Product</h2>

<p>If you were asked what the most critical math function in call of gamedev is, what might the answer be? It better darned be the dot product! The core math function used in almost every geometric calculation ever, it’s used to calculate some information about how two vectors relate to each other. It can be used to understand the angle between vectors, wether vectors are facing each other or not, and as an optimized was to compute the cos of the angle between two vectors without actually calling the <code class="language-plaintext highlighter-rouge">cosf</code> function.</p>

<p>The dot product comes from the <a href="http://en.wikipedia.org/wiki/Law_of_cosines">law of cosines</a>. Here’s the formula:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Equation 1

c^2 = a^2 + b^2 – 2ab * cos(γ)
</code></pre></div></div>

<p>This is just an equation that relates the cosine of an angle within a triangle to its various side lengths a, b and c. The Wikipedia page on the law of cosines (link above) does a nice job of explaining this in excrutiating detail. Equation 1 can be rewritten as:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Equation 2

c^2 – a^2 – b^2 = -2ab * cos(γ)
</code></pre></div></div>

<p>The right hand side equation Equation 2 is interesting! Lets say that instead of writing the equation with side lengths a, b and c, it is written with two vectors: u and v. The third side can be represented as u – v. Recall that <code class="language-plaintext highlighter-rouge">|v|</code> means the length of v, computed by using the <a href="https://en.wikipedia.org/wiki/Pythagorean_theorem">Pythagorean Thereom</a>. Re-writing equation Equation 2 in vector notation yields:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Equation 3

|u - v|^2 – |u|^2 – |v|^2 = -2|u||v| * cos(γ)
</code></pre></div></div>

<p>Which can be expressed in scalar form as:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Equation 4

(u.x - v.x)^2 + (u.y - v.y)^2 + (u.z - v.z)^2 -
((u.x)^2 + (u.y)^2 + (u.z)^2) - ((v.x)^2 + (v.y)^2 + (v.z)^2) =
-2|u||v| * cos(γ)
</code></pre></div></div>

<p>By crossing out some redundant terms, and getting rid of the -2 on each side of the equation, this ugly equation can be turned into a much more approachable version:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Equation 5

u.x * v.x + u.y * v.y + u.z * v.z = |u||v| * cos(γ)
</code></pre></div></div>

<p>Equation 5 is the equation for the dot product. If both u and v are unit vectors then the equation will simplify to:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Equation 6

dot(u, v) = cos(γ)
</code></pre></div></div>

<p>If u and v are not unit vectors equation 5 says that the dot product between both vectors is equal to <code class="language-plaintext highlighter-rouge">cos(γ)</code> that has been scaled by the lengths of u and v. This is a nice thing to know! For example: the squared length of a vector is just itself dotted with itself. We can use this knowledge to rewrite our <code class="language-plaintext highlighter-rouge">len</code> function with the dot product.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">float</span> <span class="nf">len</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">sqrtf</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="c1">// =&gt;</span>
<span class="kt">float</span> <span class="n">dot</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">float</span> <span class="n">len</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">sqrtf</span><span class="p">(</span><span class="n">dot</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">v</span><span class="p">));</span> <span class="p">}</span></code></pre></figure>

<p>If u is a unit vector and v is not, then <code class="language-plaintext highlighter-rouge">dot(u, v)</code> will return the distance in which v travels in the u direction. We will make prolific use of the dot product later! Here are the footnotes of some useful dot product properties:</p>

<ol>
  <li>The dot product is commutative! dot(a, b) == dot(b, a).</li>
  <li>You can algebraically manipulate scalars in and out of dot products. Example: given two vectors a and b, and a scalar s, we can see: s * dot(a, b) == dot(s * a, s * b).</li>
  <li>Given two vectors u and v, if u is unit (length of 1), then dot(u, v) == the distance v travels along u.</li>
  <li>If two vectors u and v are unit vectors, dot(u, v) == cos(angle between u and v).</li>
  <li>Given two vectors u and v, whether or not they are unit, sign(dot(u, v)) will tell you if the vectors are facing each other or away from each other.</li>
  <li>The dot product of perpendicular vectors is 0.</li>
</ol>

<p>Point 5) begs some extra attention. The sign function means like this:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">float</span> <span class="nf">sign</span><span class="p">(</span><span class="kt">float</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">x</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="mf">1.0</span><span class="n">f</span> <span class="o">:</span> <span class="o">-</span><span class="mf">1.0</span><span class="n">f</span><span class="p">;</span> <span class="p">}</span></code></pre></figure>

<p>If the sign of dot(u, v) is positive the vectors are facing in the same direction. If dot(u, v) is negative, the vectors are facing away from each other! Therefore it’s quite useful to have a <code class="language-plaintext highlighter-rouge">len_squared</code> function laying around that skips the <code class="language-plaintext highlighter-rouge">sqrtf</code> function; if you only need to check the sign then it’s totally fine if the resulting angle is scaled.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">float</span> <span class="nf">len_squared</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">dot</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">v</span><span class="p">);</span> <span class="p">}</span></code></pre></figure>

<h2 id="cross-product-aka-2d-determinant">Cross Product (aka 2D Determinant)</h2>

<p>The cross product is the sibling of the dot product. It computes the sin of the angle between two vectors (scaled by the length of each vector), as opposed to the cos like the dot product. It looks quite similar, though we won’t get into the derivation for the sake of brevity. In 2D games it’s not quite as useful as the dot product, but does make its appearance occasionally. Note that the cross between two parallel vectors is 0.</p>

<p>My favorite example would be a function to compute the angle between two vectors. Or more specifically, the shortest angle between two vectors. Using point 5) from the last section we can write a function called <code class="language-plaintext highlighter-rouge">shortest_arc</code> from two vectors a and b. It returns the smallest angle needed to rotate a to b. We will name the cross product <code class="language-plaintext highlighter-rouge">det2</code> for “determinant of a 2D matrix”, which will make more sense later on.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">float</span> <span class="nf">det2</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">a</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">a</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="p">}</span></code></pre></figure>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">float</span> <span class="nf">shortest_arc</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">a</span> <span class="o">=</span> <span class="n">norm</span><span class="p">(</span><span class="n">a</span><span class="p">);</span>
	<span class="n">b</span> <span class="o">=</span> <span class="n">norm</span><span class="p">(</span><span class="n">b</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">c</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">s</span> <span class="o">=</span> <span class="n">det2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">theta</span> <span class="o">=</span> <span class="n">acosf</span><span class="p">(</span><span class="n">c</span><span class="p">);</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">s</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">theta</span><span class="p">;</span>
	<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
		<span class="k">return</span> <span class="o">-</span><span class="n">theta</span><span class="p">;</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></figure>

<p>First we use the dot product to compute cos(theta), where theta is the angle between a and b. Unfortunately the function cos mere returns a number from -1 to 1, and that’s it. It’s just one angle. <em>We don’t know which side of a that b points to</em>.</p>

<p><img src="/assets/dot_sides_same.png" alt="dot_sides_same.png" /></p>

<p>In the above picture the u vector is reflected perfectly across the v vector. In both cases the dot product will return the same value, because the angle is the same in both cases! Luckily we can use det2 in a very similar way to the dot product. We can look at the sign of the cross product to see if the vector u is pointing to the left (counter-clockwise) or the right (clockwise) of the vector v. Be careful about operator order though, as det2(u, v) is not the same as det2(v, u) – in fact the sign will be flipped in these cases!</p>

<p>By checking the sin of det2 we know which side b is from a, wich determines the sign of the cos(theta) to resolve the mirroring issue. Please note that if you know a and b are unit vectors then the norm function calls do not need to happen. If a and b are non-unit vectors you’re likely to get a nasty <a href="https://en.wikipedia.org/wiki/NaN">NaN value</a> from acosf.</p>

<p>This arc function can be used to implement all kinds of cool effects, such as an “aimer” that will track an object smoothly over time. Here’s a demonstration of tracking the mouse over time. We can call <code class="language-plaintext highlighter-rouge">tigrMouse</code> to get the mouse coordinate in screen space. By carefully inverting the order of operations and all the operations of <code class="language-plaintext highlighter-rouge">world_to_screen</code> we can implement <code class="language-plaintext highlighter-rouge">screen_to_mouse</code>.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">screen_to_world</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">p</span> <span class="o">=</span> <span class="n">v2</span><span class="p">((</span><span class="kt">float</span><span class="p">)</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="n">y</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">half_screen_width</span> <span class="o">=</span> <span class="mf">640.0</span><span class="n">f</span> <span class="o">/</span> <span class="mf">2.0</span><span class="n">f</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">half_screen_height</span> <span class="o">=</span> <span class="mf">480.0</span><span class="n">f</span> <span class="o">/</span> <span class="mf">2.0</span><span class="n">f</span><span class="p">;</span>
	<span class="n">p</span><span class="p">.</span><span class="n">x</span> <span class="o">-=</span> <span class="n">half_screen_width</span><span class="p">;</span>
	<span class="n">p</span><span class="p">.</span><span class="n">y</span> <span class="o">-=</span> <span class="n">half_screen_height</span><span class="p">;</span>
	<span class="n">p</span><span class="p">.</span><span class="n">y</span> <span class="o">=</span> <span class="o">-</span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">p</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">v2</span> <span class="n">mouse</span><span class="p">()</span>
<span class="p">{</span>
	<span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">buttons</span><span class="p">;</span>
	<span class="n">tigrMouse</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">x</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">y</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">buttons</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">screen_to_world</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;math.h&gt;</span><span class="cp">
#include</span> <span class="cpf">"tigr.h"</span><span class="cp">
#include</span> <span class="cpf">"math_101.h"</span><span class="cp">
#include</span> <span class="cpf">"draw.h"</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">screen</span> <span class="o">=</span> <span class="n">tigrWindow</span><span class="p">(</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">,</span> <span class="s">"Math 101"</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="kt">float</span> <span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">aim</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
	<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">tigrClosed</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">tigrKeyDown</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">TK_ESCAPE</span><span class="p">))</span> <span class="p">{</span>
		<span class="kt">float</span> <span class="n">dt</span> <span class="o">=</span> <span class="n">tigrTime</span><span class="p">();</span>
		<span class="n">t</span> <span class="o">+=</span> <span class="n">dt</span><span class="p">;</span>
		<span class="n">tigrClear</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">color_black</span><span class="p">());</span>

		<span class="n">v2</span> <span class="n">m</span> <span class="o">=</span> <span class="n">mouse</span><span class="p">();</span>
		<span class="n">draw_box</span><span class="p">(</span><span class="n">aabb</span><span class="p">(</span><span class="n">m</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="mf">10.0</span><span class="n">f</span><span class="p">,</span> <span class="mf">10.0</span><span class="n">f</span><span class="p">),</span> <span class="n">m</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="mf">10.0</span><span class="n">f</span><span class="p">,</span> <span class="mf">10.0</span><span class="n">f</span><span class="p">)),</span> <span class="n">color_white</span><span class="p">());</span>
		<span class="kt">float</span> <span class="n">angle</span> <span class="o">=</span> <span class="n">shortest_arc</span><span class="p">(</span><span class="n">aim</span><span class="p">,</span> <span class="n">m</span><span class="p">);</span>
		<span class="n">aim</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">sincos</span><span class="p">(</span><span class="n">angle</span> <span class="o">*</span> <span class="n">dt</span> <span class="o">*</span> <span class="mf">2.0</span><span class="n">f</span><span class="p">),</span> <span class="n">aim</span><span class="p">);</span>
		<span class="n">draw_vector</span><span class="p">(</span><span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">aim</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>

		<span class="n">tigrUpdate</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">tigrFree</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p><img src="/assets/angle_tracking.gif" alt="angle_tracking.gif" /></p>

<h2 id="distance-and-planes">Distance and Planes</h2>

<p>A plane in 2D is just a line. A fancy name for a line. In 3D however, planes are like infinitely large flat sheets of paper. Another name for a plane is halfspace, because they slice all of space perfectly in half. All of these terms can be used interchangebly in 2D.</p>

<p>You’re probably familiar with the slope-form equation of a line.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>y = mx + b
</code></pre></div></div>

<p>Where m is the slope factor, and b is the offset from the origin where the line crosses the y-axis. However, there’s a couple different forms of the line equation. One is called the plane equation (my favorite).</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ax + by - c = 0
</code></pre></div></div>

<p><img src="/assets/plane_equation.png" alt="plane_equation.png" /></p>

<p>Where (a, b) is a vector called the plane normal, while (x, y) are parameters to uniquely identify any point on the plane. c is an offset from the origin, like a distance value of the plane from the origin (scaled by the length of normal (a, b)). Oftentimes the normal (a, b) is normalized to be a unit vector, this makes c the actual distance of the plane to the origin. In practice most times planes are used with unit normal vectors.</p>

<p>Finally there’s a parametric form which uses a single point on the line, and a vector to another point on the line.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>p' = p + n * t
</code></pre></div></div>

<p>Where p’ is any point on the plane, p is a given point on the plane, and t is a parameter to pick a unique point on the plane. My favorite format is the plane equation ax + by - c = 0, or ax + by = c. We can make a plane type in our code, though I’d recommend calling it halfspace. Reason being: plane is often used as an identifier in other areas of the code, so we probably can avoid naming clashes by calling it a halfspace instead.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">halfspace</span>
<span class="p">{</span>
	<span class="n">halfspace</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">halfspace</span><span class="p">(</span><span class="n">v2</span> <span class="n">n</span><span class="p">,</span> <span class="n">v2</span> <span class="n">p</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">n</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span> <span class="n">c</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span> <span class="p">}</span>
	<span class="n">halfspace</span><span class="p">(</span><span class="n">v2</span> <span class="n">n</span><span class="p">,</span> <span class="kt">float</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">n</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">c</span> <span class="o">=</span> <span class="n">c</span><span class="p">;</span> <span class="p">}</span>
	<span class="n">v2</span> <span class="n">n</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">c</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<p>Here are some extremely useful operations you can do with planes.</p>

<ol>
  <li>Compute the distance of a point to a plane (or just see which side of a plane a point is by looking at the sign of the distance).</li>
  <li>Project a point onto the surface of a plane.</li>
  <li>Compute the intersection of a line to a plane (like a raycast, more on raycasting later).</li>
</ol>

<h3 id="distance-point-to-plane">Distance Point to Plane</h3>

<p>First up is to compute the distance of a point to a plane. Let us assume the n vector (the normal vector orthogonal to the plane’s surface, telling us which way the plane is facing) of the plane is normalized. Simply plug the point into the plane equation.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>distance of point p to a halfspace (plane)
ax + by - c = 0
=&gt;
n.x * p.x + n.y * p.y - c = distance
</code></pre></div></div>

<p>Note that the part n.x * p.x + n.y * p.y is a dot product. We can rewrite this as a dot product.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dot(n, p) - c = distance
</code></pre></div></div>

<p>And so we can write down a useful distance function for planes.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">float</span> <span class="nf">distance</span><span class="p">(</span><span class="n">halfspace</span> <span class="n">h</span><span class="p">,</span> <span class="n">v2</span> <span class="n">p</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">dot</span><span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">n</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">-</span> <span class="n">h</span><span class="p">.</span><span class="n">c</span><span class="p">;</span> <span class="p">}</span></code></pre></figure>

<p>If the distance is positive then p is on the side of the plane the normal is facing, negative otherwise.</p>

<h3 id="project-point-onto-plane">Project Point onto Plane</h3>

<p>Projecting a point onto a plane means moving the point to the plane’s surface by moving it the shortest distance possible. The shortest distance is along the plane’s normal vector. Therefore all we do is compute the distance to the plane, then move the point along the normal by that negated distance.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">project</span><span class="p">(</span><span class="n">halfspace</span> <span class="n">h</span><span class="p">,</span> <span class="n">v2</span> <span class="n">p</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">p</span> <span class="o">-</span> <span class="n">h</span><span class="p">.</span><span class="n">n</span> <span class="o">*</span> <span class="n">distance</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span> <span class="p">}</span></code></pre></figure>

<h3 id="intersection-of-a-line-and-a-plane">Intersection of a Line and a Plane</h3>

<p>This one is also quite easy if you visualize it with a drawing, but there’s also the algebraic derivation. Let’s start with the algebra. Choosing the parametric form for a line is an easy way to do it. Just note <a href="https://en.wikipedia.org/wiki/Dot_product#Properties">the dot product is bilinear</a>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>line = p' = p + q * t
plane = ax + by - c = 0, or in vector form dot(n, q) - c = 0 where q is an input point

plug line equation into the plane equation
solve for t
=&gt;
dot(n, p + q * t) - c = 0
dot(n, p) + t * dot(n, q) - c = 0
t * dot(n, q) = c - dot(n, p)
t = (c - dot(n, p)) / dot(n, q)

plug our solution for t back into the line equation to calculate p'
p' is the intersection point
=&gt;
p' = p + q * t
</code></pre></div></div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">intersect</span><span class="p">(</span><span class="n">halfspace</span> <span class="n">h</span><span class="p">,</span> <span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">v2</span> <span class="n">q</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">t</span> <span class="o">=</span> <span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">c</span> <span class="o">-</span> <span class="n">dot</span><span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">n</span><span class="p">,</span> <span class="n">p</span><span class="p">)))</span> <span class="o">/</span> <span class="n">dot</span><span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">n</span><span class="p">,</span> <span class="n">q</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">p</span> <span class="o">+</span> <span class="n">q</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>You’ll have trouble if the denomitator is zero (divide by zero error), which can happen if the line is parallel to the plane (recall the dot product of vectors is zero if they are perpendicular).</p>

<p>One thing to notice here is the numerator <code class="language-plaintext highlighter-rouge">c - dot(n, p)</code>. This is the distance function we wrote earlier! It’s dividing the distance of the plane itself to the origin by the distance of p (the point on the line) to the origin. Recall: <em>dotting a point with a vector gives you the distance the point travels along the vector from the origin</em> (scaled by the vector’s length, of course).</p>

<p>Another way to figure out a solution is geometrically (just looking at the picture) if the line is given by two inputs points rather than parametric form (as in, the line that passes through both points).</p>

<p><img src="/assets/p_q_plane.png" alt="p_q_plane.png" /></p>

<p>The first term <code class="language-plaintext highlighter-rouge">dot(Q, n) - c</code> we can call dq standing for distance of q to the plane. Similarly we have dp for distance of p to the plane.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">intersect</span><span class="p">(</span><span class="n">halfspace</span> <span class="n">h</span><span class="p">,</span> <span class="n">v2</span> <span class="n">q</span><span class="p">,</span> <span class="n">v2</span> <span class="n">p</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">dq</span> <span class="o">=</span> <span class="n">distance</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">q</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">dp</span> <span class="o">=</span> <span class="n">distance</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
	<span class="c1">// ...</span>
<span class="p">}</span></code></pre></figure>

<p>Next is to notice we can move q along the vector p - q to find the intersection point. But by how much should we move q? We know it’s some factor between the distance of p and q from the plane. Factor means a ratio or division operator. Therefore we can calculate how far along the plane’s normal p - q travels, and multiply it by this ratio to compute the intersection.</p>

<p><img src="/assets/line_plane_solution.png" alt="line_plane_solution.png" /></p>

<p>Similarly this function will fail (divide by zero) if the line is parallel to the plane, seeing the denominator for dp - dq will be zero if they are equivalent.</p>

<p>Another way of thinking about this is <a href="https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/a-brief-introduction-to-lerp-r4954/">lerping</a> from p to q. We will cover lerping more in detail later. The t value for the lerp function would be <code class="language-plaintext highlighter-rouge">dq / (dq - dp)</code>.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">intersect</span><span class="p">(</span><span class="n">halfspace</span> <span class="n">h</span><span class="p">,</span> <span class="n">v2</span> <span class="n">q</span><span class="p">,</span> <span class="n">v2</span> <span class="n">p</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">dq</span> <span class="o">=</span> <span class="n">distance</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">q</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">dp</span> <span class="o">=</span> <span class="n">distance</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">q</span> <span class="o">+</span> <span class="p">(</span><span class="n">p</span> <span class="o">-</span> <span class="n">q</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">dq</span> <span class="o">/</span> <span class="p">(</span><span class="n">dq</span> <span class="o">-</span> <span class="n">dp</span><span class="p">));</span>
<span class="p">}</span></code></pre></figure>

<h2 id="bezier-curves-and-lerp">Bezier Curves and Lerp</h2>

<p><a href="https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/a-brief-introduction-to-lerp-r4954/">Lerp</a> stands for linear interpolation. It means picking a number between two endpoints (a and b) based on a t value. Usually t is a value from 0 to 1. If t is 0 then you get a, otherwise if 1 you get b. Wikipedia has these three excellent images of lerping and bezier curves I’ll include below. The values of t are animating from 0 to 1, and lerp/bezier functions are used on input points p0 through p3 to move a point along a bezier curve.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">float</span> <span class="nf">lerp</span><span class="p">(</span><span class="kt">float</span> <span class="n">a</span><span class="p">,</span> <span class="kt">float</span> <span class="n">b</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="p">(</span><span class="n">b</span> <span class="o">-</span> <span class="n">a</span><span class="p">)</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span> <span class="p">}</span>
<span class="n">v2</span> <span class="n">lerp</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="p">(</span><span class="n">b</span> <span class="o">-</span> <span class="n">a</span><span class="p">)</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span> <span class="p">}</span></code></pre></figure>

<p><img src="/assets/bezier1.gif" alt="bezier1.gif" /></p>

<p>A quadratic bezier curve is just lerping between two other lerps.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">bezier</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">v2</span> <span class="n">c</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">d</span> <span class="o">=</span> <span class="n">lerp</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="n">v2</span> <span class="n">e</span> <span class="o">=</span> <span class="n">lerp</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">lerp</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p><img src="/assets/bezier2.gif" alt="bezier2.gif" /></p>

<p>And similarly a cubic bezier curve is just lerping between two quadratic bezier curves.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">bezier</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">v2</span> <span class="n">c</span><span class="p">,</span> <span class="n">v2</span> <span class="n">d</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">e</span> <span class="o">=</span> <span class="n">bezier</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="n">v2</span> <span class="n">f</span> <span class="o">=</span> <span class="n">bezier</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">lerp</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">f</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p><img src="/assets/bezier3.gif" alt="bezier3.gif" /></p>

<p>These are useful for animating all kinds of effects in your game, such as roller coasters, transitions from here to there, missiles, grass blowing in the wind, wires hanging from telephone poles.</p>

<p>As an optimization these functions can be refactored into forms where redundant calulcations are done up-front and then reused as much as possible through a bunch of fairly gnarly algebra. Let’s do it.</p>

<p>The first step is to unwind the lerps into their raw form.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">bezier</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">v2</span> <span class="n">c</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">d</span> <span class="o">=</span> <span class="n">lerp</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="n">v2</span> <span class="n">e</span> <span class="o">=</span> <span class="n">lerp</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">lerp</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// --&gt;</span>

<span class="n">v2</span> <span class="n">bezier</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">v2</span> <span class="n">c</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">d</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="p">(</span><span class="n">b</span> <span class="o">-</span> <span class="n">a</span><span class="p">)</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">e</span> <span class="o">=</span> <span class="n">b</span> <span class="o">+</span> <span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="n">b</span><span class="p">)</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">d</span> <span class="o">+</span> <span class="p">(</span><span class="n">e</span> <span class="o">-</span> <span class="n">d</span><span class="p">)</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>Then take the algebraic pain of reducing common terms.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>d = a + bt - at
e = b + ct - bt
    d + et - dt

a - at = a(1-t)
=&gt;

d = a(1-t) + bt
e = b(1-t) + ct
    d(1-t) + et

Combine into a big formula by substituting in terms over and over
=&gt;

   d(1-t) + et
= (a(1-t) + bt)(1-t) + (b(1-t) + ct)t

Notice that 1-t is used a lot, combine all the terms possible
=&gt;

u = 1-t
= (au + bt)u + (bu + ct)t
= auu + but + but + ctt
= auu + but2 + ctt
</code></pre></div></div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">bezier</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">v2</span> <span class="n">c</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">u</span> <span class="o">=</span> <span class="mf">1.0</span><span class="n">f</span> <span class="o">-</span> <span class="n">t</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">ut</span> <span class="o">=</span> <span class="n">u</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">auu</span> <span class="o">=</span> <span class="n">a</span> <span class="o">*</span> <span class="n">u</span> <span class="o">*</span> <span class="n">u</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">but2</span> <span class="o">=</span> <span class="n">b</span> <span class="o">*</span> <span class="n">ut</span> <span class="o">*</span> <span class="mf">2.0</span><span class="n">f</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">ctt</span> <span class="o">=</span> <span class="n">c</span> <span class="o">*</span> <span class="n">t</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">auu</span> <span class="o">+</span> <span class="n">but2</span> <span class="o">+</span> <span class="n">ctt</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>And here’s a demonstration program to draw a quadratic bezier curve, and also animate a box over moving over it back and forth.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;math.h&gt;</span><span class="cp">
#include</span> <span class="cpf">"tigr.h"</span><span class="cp">
#include</span> <span class="cpf">"math_101.h"</span><span class="cp">
#include</span> <span class="cpf">"draw.h"</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">screen</span> <span class="o">=</span> <span class="n">tigrWindow</span><span class="p">(</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">,</span> <span class="s">"Math 101"</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="kt">float</span> <span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">tigrClosed</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">tigrKeyDown</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">TK_ESCAPE</span><span class="p">))</span> <span class="p">{</span>
		<span class="kt">float</span> <span class="n">dt</span> <span class="o">=</span> <span class="n">tigrTime</span><span class="p">();</span>
		<span class="n">t</span> <span class="o">+=</span> <span class="n">dt</span><span class="p">;</span>
		<span class="n">tigrClear</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">color_black</span><span class="p">());</span>

		<span class="n">v2</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
		<span class="n">v2</span> <span class="n">b</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
		<span class="n">v2</span> <span class="n">c</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">50</span><span class="p">);</span>

		<span class="kt">float</span> <span class="n">t0</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
		<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="mi">30</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
			<span class="kt">float</span> <span class="n">t1</span> <span class="o">=</span> <span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="n">i</span> <span class="o">/</span> <span class="mf">30.0</span><span class="n">f</span><span class="p">;</span>
			<span class="n">v2</span> <span class="n">p0</span> <span class="o">=</span> <span class="n">bezier</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">t0</span><span class="p">);</span>
			<span class="n">v2</span> <span class="n">p1</span> <span class="o">=</span> <span class="n">bezier</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">t1</span><span class="p">);</span>
			<span class="n">draw_line</span><span class="p">(</span><span class="n">p0</span><span class="p">,</span> <span class="n">p1</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>
			<span class="n">t0</span> <span class="o">=</span> <span class="n">t1</span><span class="p">;</span>
		<span class="p">}</span>

		<span class="kt">float</span> <span class="n">pt</span> <span class="o">=</span> <span class="p">(</span><span class="n">cosf</span><span class="p">(</span><span class="n">t</span><span class="p">)</span> <span class="o">+</span> <span class="mf">1.0</span><span class="n">f</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span><span class="p">;</span>
		<span class="n">v2</span> <span class="n">box_center</span> <span class="o">=</span> <span class="n">bezier</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">pt</span><span class="p">);</span>
		<span class="n">draw_box</span><span class="p">(</span><span class="n">aabb</span><span class="p">(</span><span class="n">box_center</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span> <span class="n">box_center</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">)),</span> <span class="n">color_white</span><span class="p">());</span>

		<span class="n">tigrUpdate</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">tigrFree</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p><img src="/assets/quadratic_bezier.gif" alt="quadratic_bezier.gif" /></p>

<p>We can also do this for the cubic bezier function. I personally do this by unwinding the calls to get all the lerps.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">bezier</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">v2</span> <span class="n">c</span><span class="p">,</span> <span class="n">v2</span> <span class="n">d</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">e</span> <span class="o">=</span> <span class="n">bezier</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="n">v2</span> <span class="n">f</span> <span class="o">=</span> <span class="n">bezier</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">lerp</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">f</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// --&gt;</span>

<span class="n">v2</span> <span class="n">bezier</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">v2</span> <span class="n">c</span><span class="p">,</span> <span class="n">v2</span> <span class="n">d</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">e</span> <span class="o">=</span> <span class="n">lerp</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="n">v2</span> <span class="n">f</span> <span class="o">=</span> <span class="n">lerp</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="n">v2</span> <span class="n">g</span> <span class="o">=</span> <span class="n">lerp</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="n">v2</span> <span class="n">h</span> <span class="o">=</span> <span class="n">lerp</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">f</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="n">v2</span> <span class="n">i</span> <span class="o">=</span> <span class="n">lerp</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">lerp</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>The next step is to unwind the lerps into their raw form.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">bezier</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">v2</span> <span class="n">c</span><span class="p">,</span> <span class="n">v2</span> <span class="n">d</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">e</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="p">(</span><span class="n">b</span> <span class="o">-</span> <span class="n">a</span><span class="p">)</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">f</span> <span class="o">=</span> <span class="n">b</span> <span class="o">+</span> <span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="n">b</span><span class="p">)</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">g</span> <span class="o">=</span> <span class="n">c</span> <span class="o">+</span> <span class="p">(</span><span class="n">d</span> <span class="o">-</span> <span class="n">c</span><span class="p">)</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">h</span> <span class="o">=</span> <span class="n">e</span> <span class="o">+</span> <span class="p">(</span><span class="n">f</span> <span class="o">-</span> <span class="n">e</span><span class="p">)</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">i</span> <span class="o">=</span> <span class="n">f</span> <span class="o">+</span> <span class="p">(</span><span class="n">g</span> <span class="o">-</span> <span class="n">f</span><span class="p">)</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">h</span> <span class="o">+</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="n">h</span><span class="p">)</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>Then take the algebraic pain of reducing common terms.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>e = a + bt - at
f = b + ct - bt
g = c + dt - ct
h = e + ft - et
i = f + gt - ft
    h + it - ht

a - at = a(1-t)
=&gt;

e = a(1-t) + bt
f = b(1-t) + ct
g = c(1-t) + dt
h = e(1-t) + ft
i = f(1-t) + gt
    h(1-t) + it

Combine into a big formula by substituting in terms over and over
=&gt;

  h(1-t) + it
= (e(1-t) + ft)(1-t) + (f(1-t) + gt)t
= ((a(1-t) + bt)(1-t) + (b(1-t) + ct)t)(1-t) + ((b(1-t) + ct)(1-t) + (c(1-t) + dt)t)t

Notice that 1-t is used a lot, combine all the terms possible
=&gt;

u = 1-t
= ((au + bt)u + (bu + ct)t)u + ((bu + ct)u + (cu + dt)t)t
= auuu + buut + buut + cutt + buut + cutt + cutt + dttt
= auuu + buut3 + cutt3 + dttt
</code></pre></div></div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">bezier</span><span class="p">(</span><span class="n">v2</span> <span class="n">a</span><span class="p">,</span> <span class="n">v2</span> <span class="n">b</span><span class="p">,</span> <span class="n">v2</span> <span class="n">c</span><span class="p">,</span> <span class="n">v2</span> <span class="n">d</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">u</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">-</span> <span class="n">t</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">tt</span> <span class="o">=</span> <span class="n">t</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">uu</span> <span class="o">=</span> <span class="n">u</span> <span class="o">*</span> <span class="n">u</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">auuu</span> <span class="o">=</span> <span class="n">a</span> <span class="o">*</span> <span class="n">uu</span> <span class="o">*</span> <span class="n">u</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">buut3</span> <span class="o">=</span> <span class="n">b</span> <span class="o">*</span> <span class="n">uu</span> <span class="o">*</span> <span class="n">t</span> <span class="o">*</span> <span class="mf">3.0</span><span class="n">f</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">cutt3</span> <span class="o">=</span> <span class="n">c</span> <span class="o">*</span> <span class="n">u</span> <span class="o">*</span> <span class="n">tt</span> <span class="o">*</span> <span class="mf">3.0</span><span class="n">f</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">dttt</span> <span class="o">=</span> <span class="n">d</span> <span class="o">*</span> <span class="n">tt</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">auuu</span> <span class="o">+</span> <span class="n">buut3</span> <span class="o">+</span> <span class="n">cutt3</span> <span class="o">+</span> <span class="n">dttt</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;math.h&gt;</span><span class="cp">
#include</span> <span class="cpf">"tigr.h"</span><span class="cp">
#include</span> <span class="cpf">"math_101.h"</span><span class="cp">
#include</span> <span class="cpf">"draw.h"</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">screen</span> <span class="o">=</span> <span class="n">tigrWindow</span><span class="p">(</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">,</span> <span class="s">"Math 101"</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="kt">float</span> <span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">tigrClosed</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">tigrKeyDown</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">TK_ESCAPE</span><span class="p">))</span> <span class="p">{</span>
		<span class="kt">float</span> <span class="n">dt</span> <span class="o">=</span> <span class="n">tigrTime</span><span class="p">();</span>
		<span class="n">t</span> <span class="o">+=</span> <span class="n">dt</span><span class="p">;</span>
		<span class="n">tigrClear</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">color_black</span><span class="p">());</span>

		<span class="n">v2</span> <span class="n">a</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
		<span class="n">v2</span> <span class="n">b</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
		<span class="n">v2</span> <span class="n">c</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">50</span><span class="p">);</span>
		<span class="n">v2</span> <span class="n">d</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">);</span>

		<span class="kt">float</span> <span class="n">t0</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
		<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="mi">30</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
			<span class="kt">float</span> <span class="n">t1</span> <span class="o">=</span> <span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="n">i</span> <span class="o">/</span> <span class="mf">30.0</span><span class="n">f</span><span class="p">;</span>
			<span class="n">v2</span> <span class="n">p0</span> <span class="o">=</span> <span class="n">bezier</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">t0</span><span class="p">);</span>
			<span class="n">v2</span> <span class="n">p1</span> <span class="o">=</span> <span class="n">bezier</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">t1</span><span class="p">);</span>
			<span class="n">draw_line</span><span class="p">(</span><span class="n">p0</span><span class="p">,</span> <span class="n">p1</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>
			<span class="n">t0</span> <span class="o">=</span> <span class="n">t1</span><span class="p">;</span>
		<span class="p">}</span>

		<span class="kt">float</span> <span class="n">pt</span> <span class="o">=</span> <span class="p">(</span><span class="n">cosf</span><span class="p">(</span><span class="n">t</span><span class="p">)</span> <span class="o">+</span> <span class="mf">1.0</span><span class="n">f</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span><span class="p">;</span>
		<span class="n">v2</span> <span class="n">box_center</span> <span class="o">=</span> <span class="n">bezier</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">pt</span><span class="p">);</span>
		<span class="n">draw_box</span><span class="p">(</span><span class="n">aabb</span><span class="p">(</span><span class="n">box_center</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span> <span class="n">box_center</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">)),</span> <span class="n">color_white</span><span class="p">());</span>

		<span class="n">tigrUpdate</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">tigrFree</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p><img src="/assets/cubic_bezier.gif" alt="cubic_bezier.gif" /></p>

<p>Just be careful with these optimized versions, because small values of u or t create numeric problems when multiplied together over and over. If the numbers get too small you can end up with <a href="https://en.wikipedia.org/wiki/Subnormal_number">denormalized numbers</a> or just numerically innaccurate results. The previous version using successive lerps or more numerically stable.</p>

<h2 id="matrices">Matrices</h2>

<p>In game development matrices are mostly useful for representing transformations, namely scales, rotations and translations. In 3D graphics there’s also some projection matrices, but we’re sticking to 2D here. A matrix stores the information needed to perform a transformation upon vectors, such as placing an object into the world, or defining a relative position to another object.</p>

<h3 id="rotation-matrices">Rotation Matrices</h3>

<p>We will be using 2x2 matrices to represent rotations and scales, and later attach a position vector to create a 3x2 matrix to represent a full transform. A convenient way to look at a 2x2 matrix is like a collection of two vectors. Take a look at the matrix m.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>u = (ux, uy)
v = (vx, vy)
m = [ux, vx]
    [uy, vy]
</code></pre></div></div>

<p>Each column of m is a vector u or v. If this matrix is a rotation matrix, then u and v would be the basis vectors. u is the x-axis and v is the y-axis. When u and v are unit vectors, <em>and orthogonal</em> (at 90 degree angles from each other), we call m a rotation matrix (or an <em>orthonormal basis</em>). We’ve actually already been using rotation matrices without knowing, back in the rotation section of this article. Let’s define our matrix struct type and a function to build a rotation matrix.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">m2</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">x</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">y</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">m2</span> <span class="n">m2_rotation</span><span class="p">(</span><span class="kt">float</span> <span class="n">angle</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">c</span> <span class="o">=</span> <span class="n">cosf</span><span class="p">(</span><span class="n">angle</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">s</span> <span class="o">=</span> <span class="n">sinf</span><span class="p">(</span><span class="n">angle</span><span class="p">);</span>
	<span class="n">m2</span> <span class="n">m</span><span class="p">;</span>
	<span class="n">m</span><span class="p">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="o">-</span><span class="n">s</span><span class="p">);</span>
	<span class="n">m</span><span class="p">.</span><span class="n">y</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">c</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">m</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">v2</span> <span class="n">mul</span><span class="p">(</span><span class="n">m2</span> <span class="n">m</span><span class="p">,</span> <span class="n">v2</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">m</span><span class="p">.</span><span class="n">x</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">m</span><span class="p">.</span><span class="n">y</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">m</span><span class="p">.</span><span class="n">x</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">m</span><span class="p">.</span><span class="n">y</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span></code></pre></figure>

<p>The mul function is defined by <a href="https://en.wikipedia.org/wiki/Matrix_multiplication">matrix multiplication rules</a>.</p>

<p>If you write down the operations by hand of multiplying a rotation matrix with a vector you’ll find it to be identical to our mul function for rotations (sin + cos pair) and vectors.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>               x-axis
                 v
rotation(a) = [cos(a), -sin(a)]
              [sin(a),  cos(a)]
                          ^
                        y-axis
</code></pre></div></div>

<p>The above matrix performs a <em>clockwise rotation</em>.</p>

<p>Matrix multiplication with vectors simply encodes a <a href="https://en.wikipedia.org/wiki/Linear_combination">linear combination</a>. Within that combination is our transformation (a rotation, scale, or mixture of both).</p>

<p>An extremely useful property of matrices is we can multiply two matrices together to concatenate their operations. If we rotate clockwise a little, then rotate counter-clockwise a lot, then multiply these together we’d be left overall with a lesser counter-clockwise rotation. We can write down the matrix mul function with our matrix to vector mul function.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">m2</span> <span class="nf">mul</span><span class="p">(</span><span class="n">m2</span> <span class="n">a</span><span class="p">,</span> <span class="n">m2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="n">m2</span> <span class="n">c</span><span class="p">;</span> <span class="n">c</span><span class="p">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">.</span><span class="n">x</span><span class="p">);</span> <span class="n">c</span><span class="p">.</span><span class="n">y</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">.</span><span class="n">y</span><span class="p">);</span> <span class="k">return</span> <span class="n">c</span><span class="p">;</span> <span class="p">}</span></code></pre></figure>

<p>The transformation of a rotation matrix can be inverted. There actually exists an inversion operation for matrices in general, but for dimensions larger than 2x2 matrices it gets fairly expensive. A bigger problem about generic inversion functions on matrices is they encourage us to black-box matrices without knowing what the various pieces actually do or represent. For example, we know we can construct a rotation matrix out of two orthogonal unit vectors by simply placing them in the first and second columns. We already have some insight about the internals here.</p>

<p>We can realize quite intuitively how to invert a 2D rotation matrix without learning or bothering with a generic inversion function. We know that a 90 degree counter-clockwise rotation matrix looks like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[cos(a), -sin(a)]
[sin(a),  cos(a)]
</code></pre></div></div>

<p>If we compute the sin and cos of 90 degrees, we get these values:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[0, -1]
[1,  0]
</code></pre></div></div>

<p>When we multiply this matrix with a vector we can see the overall effect:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[0, -1][x]   [-y]
[1,  0][y] = [ x]
</code></pre></div></div>

<p>This is actually the same effect as our earlier learnings about the skew function. If we look just at the first column of our rotation matrix we can see exactly what it’s encoding when we do a multiplication with a vector. Let’s look step by step.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1.  v---------------- x * 0, The input x component will contribute 0 to the final x component.
   [0,  ][x] = [x * 0]
   [ ,  ][ ] = [  ]

2.      v------------ -1 * y, The input y component will contribute -1 to the final x component.
   [ , -1][ ] = [x * 0 + -1 * y]
   [ ,   ][y] = [  ]

   [ ,   ][x] = [x * 0 + -1 * y]
   [1,   ][ ] = [x * 1]
3.  ^---------------- 1 * x, The input x component will contribute 1 to the final y component.

   [ ,   ][x] = [x * 0 + -1 * y]
   [ ,  0][ ] = [x * 1 +  0 * y]
4.      ^----------- 0 * y, The input y component will contribute 0 to the final x component.
</code></pre></div></div>

<p>In steps 1-2 the linear combination for the output x-component is created. The first column in the rotatio matrix, the x-axis, decides where the new x-axis will go. A 1 in the first element means the x-axis will not change. If we move the 1 to the y-component, it means the x-axis is rotated to the y-axis. In fact, we can place any combination of -1 to 1 in the elements of the rotation matrice’s first column, so long as the columns length is 1 and the y column is orthogonal – it will be a valid rotation.</p>

<p>How can we perform the inverted rotation? The inverted rotation of moving the x-axis to the y-axis, would be moving the x-axis back from the y-axis.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1.
[0,  ]
[1,  ]

2.
[1,  ]
[0,  ]

3.
[ 0,  ]
[-1,  ]

4.
[-1,  ]
[ 0,  ]
</code></pre></div></div>

<p>Which option from 1-4 do you think might be the correct answer? Option 1 is what we already did earlier – it moved the x-axis to the y-axis, a 90 degree rotation counter-clockwise as was promised. Option 1 definitely does not invert itself. What about option 2? If we perform the math we find this means leave the x-axis unchanged. It does no operation at all. We call this an <em>identity</em> transform. What about options 4? This simply flips the x-axis to point backwards. That leaves option 3. It will rotate the x-axis to the y-axis <em>but also flip it</em>, performing a clockwise rotation. This is our 90 degree counter-clockwise rotation inverted.</p>

<p>Intuitively that means we can invert the y column of our rotation matrix with a negation operator as well. The full inversion of our 90-degree rotation matrix is simply to negate each element.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[ 0, 1]^-1   [0, -1]
[-1, 0]    = [1,  0]
</code></pre></div></div>

<p>Great! Will this work for all rotation matrices, even non-90 degree rotations? Sadly no, simple negation won’t work. However, transpose does work. Transpose simply means to make all the columns become rows, and all the rows become columns (by rotating the matrix clockwise). For any rotation it’s inverse is the transpose operation (which, for 90 degree 2D rotations is equivalent to negation).</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Rotation matrix A and it's inversion B:
A^-1 = A^T = B
</code></pre></div></div>

<p>Here are some notable properties of rotation matrices:</p>

<ol>
  <li>Multiplication is non-commutative. That means A * B != B * A. If you switch around the order of operations <em>you will get a different effect</em>. This goes back to our old rule, listed next as number 2.</li>
  <li>Rotations are always performed about the origin. Period. It’s possible to encode a larger dimensioned matrix than a mere 2x2 matrix that concatenate many rotations, translations and scales together - but each individual rotation encoded within will still have been performed about the origin. Even if the transform encodes first a translation, then a rotation, then an inverse translation (rotating about a point), the rotation itself was still done about the origin (despite it being temporarily shifted).</li>
  <li>The inverse of a rotation matrix is the transposition of the rotation matrix.</li>
</ol>

<p>Going back to m2 struct we can retrive the x-axis or y-axis of a rotation matrix any time by simply getting the x column or y column.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">m2</span> <span class="o">=</span> <span class="n">m2_rotation</span><span class="p">(</span><span class="n">angle</span><span class="p">);</span>
<span class="n">v2</span> <span class="n">x_axis</span> <span class="o">=</span> <span class="n">m2</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
<span class="n">v2</span> <span class="n">y_axis</span> <span class="o">=</span> <span class="n">m2</span><span class="p">.</span><span class="n">y</span><span class="p">;</span></code></pre></figure>

<h3 id="scale-matrices">Scale Matrices</h3>

<p>Our 2x2 matrix, m2, can also encode a scaling factor along the x-axis or y-axis. A quick note on some properties of scale matrices.</p>

<ol>
  <li>They are commutative. Since a scale matrix does not rotate any axes, they act like scalar multiples. A * B = B * A.</li>
  <li>The inverse of a scale operation is to divide by the same magnitude (fancy word for length/value).</li>
</ol>

<p>The scale of our 2x2 matrices will be encoded as the length of the x-column or the y-column, representing scaling along the x-axes and y-axes respectively.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[xx, yx]
[xy, yy]

x-column/x-axis = (xx, xy)
y-column/y-axis = (yx, yy)

Scale along x-axis = |(xx, xy)|
Scale along y-axis = |(yx, yy)|
</code></pre></div></div>

<p>Going back to our m2 struct, we can add functionality for creating a scale matrix.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">m2</span> <span class="nf">m2_identity</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">m2</span> <span class="n">m</span><span class="p">;</span>
	<span class="n">m</span><span class="p">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
	<span class="n">m</span><span class="p">.</span><span class="n">y</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">m</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">m2</span> <span class="n">m2_scale</span><span class="p">(</span><span class="kt">float</span> <span class="n">x_scale</span><span class="p">,</span> <span class="kt">float</span> <span class="n">y_scale</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">m2</span> <span class="n">m</span> <span class="o">=</span> <span class="n">m2_identity</span><span class="p">();</span>
	<span class="n">m</span><span class="p">.</span><span class="n">x</span> <span class="o">*=</span> <span class="n">x_scale</span><span class="p">;</span>
	<span class="n">m</span><span class="p">.</span><span class="n">y</span> <span class="o">*=</span> <span class="n">y_scale</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">m</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>As hinted in the previous section on Rotation Matrices, the identity matrix is composed of a series of 1’s along the diagonal. This simply leaves each respective component unchanged during multiplication. As promised, scaling is just scaling individual axes of the matrix.</p>

<h3 id="translations">Translations</h3>

<p>Our 2x2 m2 matrix is not designed to handle translations. However, we can augment our m2 struct by defining a wrapping struct that encompasses one more vector to store translation information. This would be a 3x2 matrix; we can call it m3x2.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">m3x2</span>
<span class="p">{</span>
	<span class="n">m2</span> <span class="n">m</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">p</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<p>Translations don’t require too much explanation here – you’re already familiar with them! The key thing to note here is order of operations. When representing a full m3x2 matrix you can encode translations, rotations and scales all together. However, when mixing these operations you lose commutativity. Here comes another nice rule to sear into brain. Ssss…</p>

<ul>
  <li>To undo a series of transform operations, you must not only invert each operation, but also <em>reverse the order of operations</em>. Example: (A * B * C)^-1 = C^-1 * B^-1 * A^-1</li>
</ul>

<p>And finally, a function to build a translation matrix.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">m3x2</span> <span class="nf">make_translation</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">m3x2</span> <span class="n">m</span><span class="p">;</span>
	<span class="n">m</span><span class="p">.</span><span class="n">m</span> <span class="o">=</span> <span class="n">m2_identity</span><span class="p">();</span>
	<span class="n">m</span><span class="p">.</span><span class="n">p</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">m</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<h2 id="transforms">Transforms</h2>

<p>With the nice m3x2 struct we defined in the previous section we can represent almost any kind of 2D transformation we might need, especially when we’re thinking about the three most common ones: scaling, rotating and translating.</p>

<p>First up, let’s list down a series of <code class="language-plaintext highlighter-rouge">make_*</code> functions for building our m3x2 transformation matrices, including <code class="language-plaintext highlighter-rouge">make_translation</code> from the previous section.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">m3x2</span> <span class="nf">make_identity</span><span class="p">()</span> <span class="p">{</span> <span class="n">m3x2</span> <span class="n">m</span><span class="p">;</span> <span class="n">m</span><span class="p">.</span><span class="n">m</span> <span class="o">=</span> <span class="n">m2_identity</span><span class="p">;</span> <span class="n">m</span><span class="p">.</span><span class="n">p</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="k">return</span> <span class="n">m</span><span class="p">;</span> <span class="p">}</span>
<span class="n">m3x2</span> <span class="n">make_translation</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">)</span> <span class="p">{</span> <span class="n">m3x2</span> <span class="n">m</span><span class="p">;</span> <span class="n">m</span><span class="p">.</span><span class="n">m</span> <span class="o">=</span> <span class="n">m2_identity</span><span class="p">();</span> <span class="n">m</span><span class="p">.</span><span class="n">p</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span> <span class="k">return</span> <span class="n">m</span><span class="p">;</span> <span class="p">};</span>
<span class="n">m3x2</span> <span class="n">make_translation</span><span class="p">(</span><span class="kt">float</span> <span class="n">x</span><span class="p">,</span> <span class="kt">float</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">make_translation</span><span class="p">(</span><span class="n">v2</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">));</span> <span class="p">}</span>
<span class="n">m3x2</span> <span class="n">make_scale</span><span class="p">(</span><span class="n">v2</span> <span class="n">scale</span><span class="p">)</span> <span class="p">{</span> <span class="n">m3x2</span> <span class="n">m</span> <span class="o">=</span> <span class="n">make_identity</span><span class="p">();</span> <span class="n">m</span><span class="p">.</span><span class="n">x</span> <span class="o">*=</span> <span class="n">scale</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="n">m</span><span class="p">.</span><span class="n">y</span> <span class="o">*=</span> <span class="n">scale</span><span class="p">.</span><span class="n">y</span><span class="p">;</span> <span class="k">return</span> <span class="n">m</span><span class="p">;</span> <span class="p">}</span>
<span class="n">m3x2</span> <span class="n">make_scale</span><span class="p">(</span><span class="kt">float</span> <span class="n">scale_x</span><span class="p">,</span> <span class="kt">float</span> <span class="n">scale_y</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">make_scale</span><span class="p">(</span><span class="n">v2</span><span class="p">(</span><span class="n">scale_x</span><span class="p">,</span> <span class="n">scale_y</span><span class="p">));</span> <span class="p">}</span>
<span class="n">m3x2</span> <span class="n">make_rotation</span><span class="p">(</span><span class="kt">float</span> <span class="n">radians</span><span class="p">)</span> <span class="p">{</span> <span class="n">m3x2</span> <span class="n">m</span><span class="p">;</span> <span class="n">m</span><span class="p">.</span><span class="n">m</span> <span class="o">=</span> <span class="n">m2_rotation</span><span class="p">(</span><span class="n">radians</span><span class="p">);</span> <span class="n">m</span><span class="p">.</span><span class="n">p</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="k">return</span> <span class="n">m</span><span class="p">;</span> <span class="p">}</span>
<span class="n">m3x2</span> <span class="n">make_TSR</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">v2</span> <span class="n">s</span><span class="p">,</span> <span class="kt">float</span> <span class="n">radians</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">rotation</span> <span class="n">r</span> <span class="o">=</span> <span class="n">sincos</span><span class="p">(</span><span class="n">radians</span><span class="p">);</span>
	<span class="n">m3x2</span> <span class="n">m</span><span class="p">;</span>
	<span class="n">m</span><span class="p">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">c</span><span class="p">,</span> <span class="o">-</span><span class="n">r</span><span class="p">.</span><span class="n">s</span><span class="p">)</span> <span class="o">*</span> <span class="n">s</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
	<span class="n">m</span><span class="p">.</span><span class="n">y</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">s</span><span class="p">,</span> <span class="n">r</span><span class="p">.</span><span class="n">c</span><span class="p">)</span> <span class="o">*</span> <span class="n">s</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>
	<span class="n">m</span><span class="p">.</span><span class="n">p</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">m</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>The really interesting function is <code class="language-plaintext highlighter-rouge">make_TSR</code>, it stands for rotate, then scale, then translate, in that order. It’s a composition of all three kinds of transformations. Whenever we multiply it with a vector, the vector will be first rotated <em>about the origin</em>, then scaled <em>about the origin</em>, then translated. Here’s the mul function for another vector.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">v2</span> <span class="nf">mul</span><span class="p">(</span><span class="n">m3x2</span> <span class="n">m</span><span class="p">,</span> <span class="n">v2</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">mul</span><span class="p">(</span><span class="n">m</span><span class="p">.</span><span class="n">m</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="o">+</span> <span class="n">m</span><span class="p">.</span><span class="n">p</span><span class="p">;</span> <span class="p">}</span></code></pre></figure>

<p>Similarly we can follow the rules of matrix multiplication and write down how to concatenate two m3x2 matrices with a mul function.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="c1">// Transform b by a.</span>
<span class="n">m3x2</span> <span class="nf">mul</span><span class="p">(</span><span class="n">m3x2</span> <span class="n">a</span><span class="p">,</span> <span class="n">m3x2</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="n">m3x2</span> <span class="n">c</span><span class="p">;</span> <span class="n">c</span><span class="p">.</span><span class="n">m</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">m</span><span class="p">,</span> <span class="n">b</span><span class="p">.</span><span class="n">m</span><span class="p">);</span> <span class="n">c</span><span class="p">.</span><span class="n">p</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">m</span><span class="p">,</span> <span class="n">b</span><span class="p">.</span><span class="n">p</span><span class="p">)</span> <span class="o">+</span> <span class="n">a</span><span class="p">.</span><span class="n">p</span><span class="p">;</span> <span class="k">return</span> <span class="n">c</span><span class="p">;</span> <span class="p">}</span></code></pre></figure>

<p>The order of operations on the translation is quite important here. We want to transform b by a, which means we want to rotate a, then scale a, then translate a. The mul with a.m does the scale/rotation together in a single m2, and the translation happens afterwards.</p>

<h3 id="transforming-objects">Transforming Objects</h3>

<p>Usually in games you have two kinds of objects in the world: implicitly defined shapes and meshes. When I say it merely means an array of vertices. Sometimes these vertices are stored as triangle triplets, and somethings they are accompanied by an array of triangle indices. For 2D we can just stick the former: merely an array of vertices (regardless of whether they are individual points, line segments, or triangles). Think of a mesh as an array of v2’s, like the vertices of a polygon.</p>

<p>An implicitly defined shape reduces the amount of information needed to represent a shape down to a convenient minimum, like our aabb shape. Other common shapes include circles, capsules, and rays.</p>

<p>Say we have a mesh definition like so:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">mesh</span>
<span class="p">{</span>
	<span class="n">array</span><span class="o">&lt;</span><span class="n">v2</span><span class="o">&gt;</span> <span class="n">vertices</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<p>Transforming this mesh with an m3x2 is an extremely common operation; simply loop over all vertices and mul them with the m3x2. This can rotate, then scale, then translate all the vertices. This is such a common thing to do that we usually attach a dedicated m3x2 onto our objects with a mesh.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">game_object</span>
<span class="p">{</span>
	<span class="n">m3x2</span> <span class="n">transform</span><span class="p">;</span>
	<span class="n">array</span><span class="o">&lt;</span><span class="n">v2</span><span class="o">&gt;</span> <span class="n">mesh</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<p>As a memory optimization it’s common to store a single copy of a mesh in memory, and have different objects keep a pointer to the mesh and a transform. The mesh vertices themselves, as they sit in memory, are usually stoerd in what’s called <em>model space</em>. This just means the vertices are likely very close to the origin and haven’t been rotated/scaled/translated into the world yet.</p>

<p>To draw one of the meshes usually the vertices are copied over to the GPU (graphics processing unit). In tigr we just set pixels onto the screen directly. Whenever we want to draw a mesh we can loop over the vertices, mul them in the loop and use temporary v2 variables to represent the transformed verts. Then we draw with those temporary variables. The original source mesh vertices are as if they are in “read-only mode”.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">game_object</span>
<span class="p">{</span>
	<span class="n">m3x2</span> <span class="n">transform</span><span class="p">;</span>
	<span class="n">array</span><span class="o">&lt;</span><span class="n">v2</span><span class="o">&gt;*</span> <span class="n">mesh</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// This is just example code -- with tigr we aren't sending meshes to the GPU. But, for most games</span>
<span class="c1">// this is an extremely common operation. We just use tigr for a nice and simple learning environment.</span>
<span class="kt">void</span> <span class="n">send_triangle_mesh_to_gpu</span><span class="p">(</span><span class="n">game_object</span><span class="o">*</span> <span class="n">o</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span><span class="o">*</span> <span class="n">vertices</span> <span class="o">=</span> <span class="n">o</span><span class="o">-&gt;</span><span class="n">mesh</span><span class="p">.</span><span class="n">data</span><span class="p">();</span>
	<span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="n">o</span><span class="o">-&gt;</span><span class="n">mesh</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
	<span class="n">m3x2</span> <span class="n">m</span> <span class="o">=</span> <span class="n">o</span><span class="o">-&gt;</span><span class="n">m</span><span class="p">;</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">I</span> <span class="o">+=</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">v2</span> <span class="n">a</span> <span class="o">=</span> <span class="n">vertices</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
		<span class="n">v2</span> <span class="n">b</span> <span class="o">=</span> <span class="n">vertices</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">];</span>
		<span class="n">v2</span> <span class="n">c</span> <span class="o">=</span> <span class="n">vertices</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">];</span>
		<span class="n">a</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">a</span><span class="p">);</span>
		<span class="n">b</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>
		<span class="n">c</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">c</span><span class="p">);</span>
		<span class="n">gpu_context</span><span class="o">-&gt;</span><span class="n">add_triangle</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">);</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></figure>

<p>For an implicitly defined shape we can do the same, but scaling might be a bit difficult. For example how can we scale a circle along the x-axis but not the y-axis? It’s a bit of a condundrum on what to do here. Nonetheless we can make a decision.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">circle</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">p</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">r</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">circle</span> <span class="n">mul</span><span class="p">(</span><span class="n">m3x2</span> <span class="n">m</span><span class="p">,</span> <span class="n">circle</span> <span class="n">c</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">c</span><span class="p">.</span><span class="n">r</span> <span class="o">*=</span> <span class="n">len</span><span class="p">(</span><span class="n">m</span><span class="p">.</span><span class="n">x</span><span class="p">);</span>
	<span class="n">c</span><span class="p">.</span><span class="n">p</span> <span class="o">=</span> <span class="n">mul</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">c</span><span class="p">.</span><span class="n">p</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">c</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>In the above example we chose to use the x-axis for scaling circles. How you decide to handle this case in your game is up to you. You could use the y-axis, you could use the min or max of both axes, or even the average of both axes.</p>

<h3 id="object-heirarchies">Object Heirarchies</h3>

<p>It’s quite common to give your game_object (or equivalence) a transform <em>and a parent</em>. The parent would be a reference, pointer or id to a parenting game object. The parent has it’s own transform, while the game_object would have it’s transform be defined relative to the parent’s transform. If a game object has no parent, it’s transform is absolute, and not relative.</p>

<p>This can be useful to compose more complicated looking game objects. A great example would be 2D games that use skeletal animation for the animations. Each “bone” in a skeleton is merely a transformation matrix (like an m3x2). An image or mesh is placed into each bone, which each bone transformed relative to it’s parent. A good way to learn about what skeletal animations look like is to check out these cool live demos by <a href="http://esotericsoftware.com/spine-demos">Spine software</a>. Some examples of games that use skeletal animation would be:</p>

<ul>
  <li><a href="https://play.google.com/store/apps/details?id=com.ea.game.pvzfree_row">Plants vs Zombies</a></li>
  <li><a href="https://store.steampowered.com/app/646570/Slay_the_Spire/">Slay the Spire</a></li>
</ul>

<h2 id="raycasting-basics">Raycasting Basics</h2>

<p>A ray is a like a line. It starts at a point and goes on infinitely in a direction. However for games actual rays aren’t super useful because they usually cause a performance concern. When we test to see if a ray hits anything, if the ray goes on infinitely it will often query against shapes in the world very far away that aren’t relevant. Instead it’s good design to define a ray for our games as a line-segment with a finite length.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">ray</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">p</span><span class="p">;</span>    <span class="c1">// Start position.</span>
	<span class="n">v2</span> <span class="n">d</span><span class="p">;</span>    <span class="c1">// Direction of the ray (normalized)</span>
	<span class="kt">float</span> <span class="n">t</span><span class="p">;</span> <span class="c1">// Distance along d the ray travels.</span>
	<span class="n">v2</span> <span class="n">endpoint</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">p</span> <span class="o">+</span> <span class="n">d</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span> <span class="p">}</span>
<span class="p">};</span></code></pre></figure>

<p>It’s quite important to keep the ray direction normalized for numeric stability during ray test operations. <a href="https://github.com/RandyGaul/cute_headers/issues/30">Here’s a thread</a> talking about this sort of thing in detail.</p>

<p>The equation for a ray is merely the parametric form of a line with a condition attached.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>p is the start point of the ray
d is the ray direction vector (normalized)
x is an input scalar

p' = p + d * x
x &gt;= 0
</code></pre></div></div>

<p>In our code we apply an extra condition, namely that the ray goes from t = 0 to t = N. So we can rewrite the definition more like this.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>p' = p + d * x
x &gt;= 0
x &lt;= t // t comes from our ray struct, defining the endpoint of the ray's line segment
</code></pre></div></div>

<p>We can cast rays and hit-test all kinds of shapes. We will cover some shapes here:</p>

<ol>
  <li>Ray to circle</li>
  <li>Ray to polygon</li>
</ol>

<h3 id="ray-to-circle">Ray to Circle</h3>

<p>Deriving the ray to circle routine is much like our other exercises: write down some equations and plug them into each other.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>q : input point
c : center of circle
t : distance along the ray that might hit the circle

sqrt((q - c)(q - c)) = r
p + d * t

rewrite circle equation
=&gt;
|q - c|^2 = r^2

substitute ray into q
=&gt;
|p + d * t - c|^2 = r^2

solve for t (time of impact)
(p + d * t - c)(p + d * t - c) - r^2 = 0
((p - c) + t * d)((p - c) + t * d) - r^2 = 0
e = p - c
(e + t * d)(e + t * d) - r^2 = 0
dot(e, e) + t * dot(e, d) + t * dot(e, d) + t^2 * dot(d, d) - r^2 = 0
t^2 * dot(d, d) + 2t * dot(e, d) + dot(e, e) - r^2 = 0

quadratic equation in t
t = (-b ± sqrt(b * b - 4ac))/(2a)
a = dot(d, d)
b = 2 * dot(d, e)
c = dot(e, e) - r^2

The discriminant (part in the sqrt) tells information based on the sign.
If it's positive we have an intersection.
</code></pre></div></div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">bool</span> <span class="nf">raycast_circle</span><span class="p">(</span><span class="n">ray</span> <span class="n">r</span><span class="p">,</span> <span class="n">circle</span> <span class="n">c</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">c</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="n">c</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">p</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">e</span> <span class="o">=</span> <span class="n">p</span> <span class="o">-</span> <span class="n">c</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">d</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">d</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">a</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">d</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">b</span> <span class="o">=</span> <span class="mf">2.0</span><span class="n">f</span> <span class="o">*</span> <span class="n">dot</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">d</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">c</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">e</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">t</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">t</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">rr</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="n">r</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">r</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">discriminant</span> <span class="o">=</span> <span class="n">b</span> <span class="o">*</span> <span class="n">b</span> <span class="o">-</span> <span class="mf">4.0</span><span class="n">f</span> <span class="o">*</span> <span class="n">a</span> <span class="o">*</span> <span class="n">c</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">discriminant</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>The first obvious optimization is that we know d to be of unit length, so dot(d, d) is 1.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">bool</span> <span class="nf">raycast_circle</span><span class="p">(</span><span class="n">ray</span> <span class="n">r</span><span class="p">,</span> <span class="n">circle</span> <span class="n">c</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">p</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">e</span> <span class="o">=</span> <span class="n">p</span> <span class="o">-</span> <span class="n">c</span><span class="p">.</span><span class="n">p</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">d</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">d</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">rr</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="n">r</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">r</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">b</span> <span class="o">=</span> <span class="mf">2.0</span><span class="n">f</span> <span class="o">*</span> <span class="n">dot</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">d</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">c</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> <span class="o">-</span> <span class="n">rr</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">discriminant</span> <span class="o">=</span> <span class="n">b</span> <span class="o">*</span> <span class="n">b</span> <span class="o">-</span> <span class="mf">4.0</span><span class="n">f</span> <span class="o">*</span> <span class="n">c</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">discriminant</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>Another thing is to use a different form of the quadratic equation where b is doubled. This can remove the extra constant multiply by four and by two. This also slightly increases numeric stability by keeping the numbers a little lower.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>t^2 * dot(d, d) + 2t * dot(e, d) + dot(e, e) - r^2 = 0
t = (-b ± sqrt(b * b - ac))/a
a = 1
b = dot(d, e)
c = dot(e, e) - r^2
</code></pre></div></div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">bool</span> <span class="nf">raycast_circle</span><span class="p">(</span><span class="n">ray</span> <span class="n">r</span><span class="p">,</span> <span class="n">circle</span> <span class="n">c</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">p</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">e</span> <span class="o">=</span> <span class="n">p</span> <span class="o">-</span> <span class="n">c</span><span class="p">.</span><span class="n">p</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">d</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">d</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">rr</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="n">r</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">r</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">b</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">d</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">c</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> <span class="o">-</span> <span class="n">rr</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">discriminant</span> <span class="o">=</span> <span class="n">b</span> <span class="o">*</span> <span class="n">b</span> <span class="o">-</span> <span class="n">c</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">discriminant</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>Lastly, it’s generally useful to add the hit point and normal to the output of any raycast function. The normal describes the direction the surface is facing where the ray hit. This can be used to inform where bullets should bounce, or how players are standing on top of objects. Simply solving for t and plugging it into the ray equation p + d * t will give us the hit location. But first, we must make sure t is within the bounds of the line segment. If t is negative it means the ray started inside the sphere. Additionally, we ignore the ± and only consider the earliest hit time, which would be the - case in our quadratic solution <code class="language-plaintext highlighter-rouge">t = -b - sqrt(b * b - c)</code>.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">raycast_output</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">t</span><span class="p">;</span> <span class="c1">// Time of impact.</span>
	<span class="n">v2</span> <span class="n">n</span><span class="p">;</span>    <span class="c1">// Normal of the surface at impact (unit length).</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">ray</span>
<span class="p">{</span>
	<span class="n">ray</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">ray</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">v2</span> <span class="n">d</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">p</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">d</span> <span class="o">=</span> <span class="n">d</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">t</span> <span class="o">=</span> <span class="n">t</span><span class="p">;</span> <span class="p">}</span>
	<span class="n">v2</span> <span class="n">p</span><span class="p">;</span>    <span class="c1">// Start position.</span>
	<span class="n">v2</span> <span class="n">d</span><span class="p">;</span>    <span class="c1">// Direction of the ray (normalized)</span>
	<span class="kt">float</span> <span class="n">t</span><span class="p">;</span> <span class="c1">// Distance along d the ray travels.</span>
	<span class="n">v2</span> <span class="n">endpoint</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">p</span> <span class="o">+</span> <span class="n">d</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span> <span class="p">}</span>
	<span class="n">v2</span> <span class="n">impact</span><span class="p">(</span><span class="n">raycast_output</span> <span class="n">hit_data</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">p</span> <span class="o">+</span> <span class="n">d</span> <span class="o">*</span> <span class="n">hit_data</span><span class="p">.</span><span class="n">t</span><span class="p">;</span> <span class="p">}</span>
<span class="p">};</span>

<span class="c1">// Reflect vector d across vector n. See: http://paulbourke.net/geometry/reflected/</span>
<span class="n">v2</span> <span class="n">reflect</span><span class="p">(</span><span class="n">v2</span> <span class="n">d</span><span class="p">,</span> <span class="n">v2</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">d</span> <span class="o">-</span> <span class="n">n</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">dot</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span> <span class="p">}</span>

<span class="kt">bool</span> <span class="n">raycast_circle</span><span class="p">(</span><span class="n">ray</span> <span class="n">r</span><span class="p">,</span> <span class="n">circle</span> <span class="n">c</span><span class="p">,</span> <span class="n">raycast</span><span class="o">*</span> <span class="n">out</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">e</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">p</span> <span class="o">-</span> <span class="n">c</span><span class="p">.</span><span class="n">p</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">rr</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="n">r</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">r</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">b</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">d</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">c</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> <span class="o">-</span> <span class="n">rr</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">discriminant</span> <span class="o">=</span> <span class="n">b</span> <span class="o">*</span> <span class="n">b</span> <span class="o">-</span> <span class="n">c</span><span class="p">;</span>
	<span class="kt">bool</span> <span class="n">missed_circle</span> <span class="o">=</span> <span class="n">discriminant</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">;</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">missed_circle</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
	<span class="n">t</span> <span class="o">=</span> <span class="o">-</span><span class="n">b</span> <span class="o">-</span> <span class="n">sqrtf</span><span class="p">(</span><span class="n">discriminant</span><span class="p">);</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">t</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">t</span> <span class="o">&lt;=</span> <span class="n">r</span><span class="p">.</span><span class="n">t</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">out</span><span class="o">-&gt;</span><span class="n">t</span> <span class="o">=</span> <span class="n">t</span><span class="p">;</span>
		<span class="n">v2</span> <span class="n">impact</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">p</span> <span class="o">+</span> <span class="n">r</span><span class="p">.</span><span class="n">d</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span>
		<span class="n">out</span><span class="o">-&gt;</span><span class="n">n</span> <span class="o">=</span> <span class="n">norm</span><span class="p">(</span><span class="n">impact</span> <span class="o">-</span> <span class="n">c</span><span class="p">.</span><span class="n">p</span><span class="p">);</span>
	<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
		<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></figure>

<p><img src="/assets/ray_circle.gif" alt="ray_circle.gif" /></p>

<p>Here’s main.cpp for the above demo.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">"tigr.h"</span><span class="cp">
#include</span> <span class="cpf">"math_101.h"</span><span class="cp">
#include</span> <span class="cpf">"draw.h"</span><span class="cp">
</span>
<span class="n">circle</span> <span class="n">circles</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
	<span class="n">circle</span><span class="p">(</span><span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">20</span><span class="p">),</span>
	<span class="n">circle</span><span class="p">(</span><span class="o">-</span><span class="mi">200</span><span class="p">,</span> <span class="mi">50</span><span class="p">,</span> <span class="mi">30</span><span class="p">),</span>
	<span class="n">circle</span><span class="p">(</span><span class="o">-</span><span class="mi">150</span><span class="p">,</span> <span class="mi">150</span><span class="p">,</span> <span class="mi">70</span><span class="p">),</span>
	<span class="n">circle</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span> <span class="mi">200</span><span class="p">,</span> <span class="mi">100</span><span class="p">),</span>
	<span class="n">circle</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="o">-</span><span class="mi">150</span><span class="p">,</span> <span class="mi">70</span><span class="p">),</span>
	<span class="n">circle</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="mi">20</span><span class="p">),</span>
	<span class="n">circle</span><span class="p">(</span><span class="o">-</span><span class="mi">150</span><span class="p">,</span> <span class="o">-</span><span class="mi">200</span><span class="p">,</span> <span class="mi">100</span><span class="p">),</span>
<span class="p">};</span>

<span class="kt">void</span> <span class="n">cast_ray</span><span class="p">(</span><span class="n">ray</span> <span class="n">r</span><span class="p">,</span> <span class="kt">int</span> <span class="n">depth</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="kt">int</span> <span class="n">depth_max</span> <span class="o">=</span> <span class="mi">100</span><span class="p">)</span>
<span class="p">{</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">depth</span> <span class="o">==</span> <span class="n">depth_max</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">draw_vector</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">p</span><span class="p">,</span> <span class="n">r</span><span class="p">.</span><span class="n">endpoint</span><span class="p">()</span> <span class="o">-</span> <span class="n">r</span><span class="p">.</span><span class="n">p</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>
	<span class="p">}</span>
	<span class="kt">float</span> <span class="n">min_t</span> <span class="o">=</span> <span class="n">FLT_MAX</span><span class="p">;</span>
	<span class="n">raycast_output</span> <span class="n">best_hit</span><span class="p">;</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">circles</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="o">*</span><span class="n">circles</span><span class="p">);</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">raycast_output</span> <span class="n">hit_data</span><span class="p">;</span>
		<span class="kt">bool</span> <span class="n">hit</span> <span class="o">=</span> <span class="n">raycast</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">circles</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="o">&amp;</span><span class="n">hit_data</span><span class="p">);</span>
		<span class="k">if</span> <span class="p">(</span><span class="n">hit</span> <span class="o">&amp;&amp;</span> <span class="n">depth</span> <span class="o">&lt;</span> <span class="n">depth_max</span><span class="p">)</span> <span class="p">{</span>
			<span class="k">if</span> <span class="p">(</span><span class="n">hit_data</span><span class="p">.</span><span class="n">t</span> <span class="o">&lt;</span> <span class="n">min_t</span><span class="p">)</span> <span class="p">{</span>
				<span class="n">min_t</span> <span class="o">=</span> <span class="n">hit_data</span><span class="p">.</span><span class="n">t</span><span class="p">;</span>
				<span class="n">best_hit</span> <span class="o">=</span> <span class="n">hit_data</span><span class="p">;</span>
			<span class="p">}</span>
		<span class="p">}</span>
	<span class="p">}</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">min_t</span> <span class="o">!=</span> <span class="n">FLT_MAX</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">v2</span> <span class="n">hit</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">impact</span><span class="p">(</span><span class="n">best_hit</span><span class="p">);</span>
		<span class="n">draw_line</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">p</span><span class="p">,</span> <span class="n">hit</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>
		<span class="n">r</span><span class="p">.</span><span class="n">d</span> <span class="o">=</span> <span class="n">reflect</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">d</span><span class="p">,</span> <span class="n">best_hit</span><span class="p">.</span><span class="n">n</span><span class="p">);</span>
		<span class="n">r</span><span class="p">.</span><span class="n">p</span> <span class="o">=</span> <span class="n">hit</span><span class="p">;</span>
		<span class="n">r</span><span class="p">.</span><span class="n">t</span> <span class="o">-=</span> <span class="n">best_hit</span><span class="p">.</span><span class="n">t</span><span class="p">;</span>
		<span class="n">cast_ray</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">depth</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">depth_max</span><span class="p">);</span>
	<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
		<span class="n">draw_vector</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">p</span><span class="p">,</span> <span class="n">r</span><span class="p">.</span><span class="n">endpoint</span><span class="p">()</span> <span class="o">-</span> <span class="n">r</span><span class="p">.</span><span class="n">p</span><span class="p">,</span> <span class="n">color_white</span><span class="p">());</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">screen</span> <span class="o">=</span> <span class="n">tigrWindow</span><span class="p">(</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">,</span> <span class="s">"Math 101"</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="kt">float</span> <span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">tigrClosed</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">tigrKeyDown</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">TK_ESCAPE</span><span class="p">))</span> <span class="p">{</span>
		<span class="kt">float</span> <span class="n">dt</span> <span class="o">=</span> <span class="n">tigrTime</span><span class="p">();</span>
		<span class="n">t</span> <span class="o">+=</span> <span class="n">dt</span><span class="p">;</span>
		<span class="n">tigrClear</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="n">color_black</span><span class="p">());</span>

		<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">circles</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="o">*</span><span class="n">circles</span><span class="p">);</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">draw_circle</span><span class="p">(</span><span class="n">circles</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">color_white</span><span class="p">());</span>
		<span class="p">}</span>

		<span class="n">v2</span> <span class="n">m</span> <span class="o">=</span> <span class="n">mouse</span><span class="p">();</span>
		<span class="n">ray</span> <span class="n">r</span> <span class="o">=</span> <span class="n">ray</span><span class="p">(</span><span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">norm</span><span class="p">(</span><span class="n">m</span><span class="p">),</span> <span class="mf">25.0</span><span class="n">f</span> <span class="o">+</span> <span class="p">(</span><span class="n">cosf</span><span class="p">(</span><span class="n">t</span> <span class="o">*</span> <span class="mf">2.0</span><span class="n">f</span><span class="p">)</span> <span class="o">+</span> <span class="mf">1.0</span><span class="n">f</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span> <span class="o">*</span> <span class="mf">500.0</span><span class="n">f</span><span class="p">);</span>
		<span class="n">cast_ray</span><span class="p">(</span><span class="n">r</span><span class="p">);</span>

		<span class="n">tigrUpdate</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">tigrFree</span><span class="p">(</span><span class="n">screen</span><span class="p">);</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<h3 id="ray-to-polygon">Ray to Polygon</h3>

<p>We’ve actually covered this topic already back in the <strong>Distance and Planes</strong> section, at least, mostly covered it by calculating distances of points to planes, and intersection of line segment to plane. From Christer Ericson’s excellent book Real-Time Collision Detection he explains a great algorithm for raycasting against a polygon.</p>

<p>Ericson describes the process as continually slicing a line segment with cutting planes, where each plane is a face of the polygon. If the ray is completely sliced away (length becomes 0 or negative) there is no intersection. Otherwise the final line segment contains the start/endpoints for the ray intersections. Special care must be taken to avoid dividing by zero. The image below shows the step-by-step process of clipping a ling segment against invidual planes of a polygon.</p>

<p><img src="/assets/line_clip_poly.png" alt="line_clip_poly.png" /></p>

<p>The code is rather straightforward. Compute the numerator and denominator in our earlier discussions of line segment to plane, avoid divide by zero issues, and keep track of a lo/hi time of intersection. Just be sure that the polygon is in counter-clockwise vertex order, and is a valid <a href="https://en.wikipedia.org/wiki/Convex_hull">convex hull</a>. We’ll go over an algorithm for building 2D convex hulls later. Note we can of course use this algorithm on aabb’s as well (though it wouldn’t quite be optimal, will definitely get the job done and likely be more than fast enough for most games).</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#define POLYGON_MAX_VERTS 8
</span>
<span class="k">struct</span> <span class="nc">polygon</span>
<span class="p">{</span>
	<span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">verts</span><span class="p">[</span><span class="n">POLYGON_MAX_VERTS</span><span class="p">];</span>
	<span class="n">v2</span> <span class="n">norms</span><span class="p">[</span><span class="n">POLYGON_MAX_VERTS</span><span class="p">];</span>
	<span class="kt">void</span> <span class="n">compute_norms</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">count</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
			<span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;</span> <span class="n">count</span> <span class="o">?</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
			<span class="n">norms</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">norm</span><span class="p">(</span><span class="n">skew</span><span class="p">(</span><span class="n">verts</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="n">verts</span><span class="p">[</span><span class="n">j</span><span class="p">]));</span>
		<span class="p">}</span>
	<span class="p">}</span>
<span class="p">};</span>

<span class="kt">bool</span> <span class="n">raycast</span><span class="p">(</span><span class="n">ray</span> <span class="n">r</span><span class="p">,</span> <span class="n">polygon</span> <span class="n">poly</span><span class="p">,</span> <span class="n">raycast_output</span><span class="o">*</span> <span class="n">out</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">lo</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">hi</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">t</span><span class="p">;</span>
	<span class="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="o">~</span><span class="mi">0</span><span class="p">;</span>

	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">poly</span><span class="p">.</span><span class="n">count</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
		<span class="c1">// Calculate distance of point to plane.</span>
		<span class="c1">// This is a slight variation of dot(n, p) - c, where instead of pre-computing c as scalar,</span>
		<span class="c1">// we form a vector pointing from the ray's start point to a point on the plane. This is</span>
		<span class="c1">// functionally equivalent to dot(n, p) - c, but we don't have to store c inside of our poly.</span>
		<span class="kt">float</span> <span class="n">distance</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">poly</span><span class="p">.</span><span class="n">norms</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">poly</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="n">r</span><span class="p">.</span><span class="n">p</span><span class="p">);</span>
		<span class="kt">float</span> <span class="n">denominator</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">poly</span><span class="p">.</span><span class="n">norms</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">r</span><span class="p">.</span><span class="n">d</span><span class="p">);</span>
		<span class="k">if</span> <span class="p">(</span><span class="n">denominator</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="c1">// Ray direction is parallel to this poly's face plane.</span>
			<span class="c1">// If the ray's start direction is outside the plane we know there's no intersection.</span>
			<span class="k">if</span> <span class="p">(</span><span class="n">distance</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
		<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
			<span class="kt">float</span> <span class="n">t</span> <span class="o">=</span> <span class="n">distance</span> <span class="o">/</span> <span class="n">denominator</span><span class="p">;</span>
			<span class="k">if</span> <span class="p">(</span><span class="n">denominator</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
				<span class="c1">// Ray is entering the plane.</span>
				<span class="n">lo</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">lo</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span>
				<span class="n">index</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
			<span class="p">}</span>
			<span class="k">else</span> <span class="n">hi</span> <span class="o">=</span> <span class="n">min</span><span class="p">(</span><span class="n">hi</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span> <span class="c1">// Ray is exiting the plane.</span>
			<span class="kt">bool</span> <span class="n">ray_clipped_away</span> <span class="o">=</span> <span class="n">lo</span> <span class="o">&gt;</span> <span class="n">hi</span><span class="p">;</span>
			<span class="k">if</span> <span class="p">(</span><span class="n">ray_clipped_away</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">!=</span> <span class="o">~</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">out</span><span class="o">-&gt;</span><span class="n">t</span> <span class="o">=</span> <span class="n">lo</span><span class="p">;</span>
		<span class="n">out</span><span class="o">-&gt;</span><span class="n">n</span> <span class="o">=</span> <span class="n">poly</span><span class="p">.</span><span class="n">norms</span><span class="p">[</span><span class="n">index</span><span class="p">];</span>
		<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
	<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
		<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></figure>

<p>You might be wondering why the polygon is limited to merely 8 vertices with <code class="language-plaintext highlighter-rouge">POLYGON_MAX_VERTS</code>. It’s possible to change this to some other value, such as 16 or 32, but in practice it’s often not a very useful thing to do. In 2D if there are too many vertices the shape starts to look a lot less unique, more like a circle or ellipse. It’s very convenient to keep implementations extremely simple by limiting the number of vertices to a small number. This makes polygons <code class="language-plaintext highlighter-rouge">memcpy</code>-able, and very cache-friendly for running quick and efficient code.</p>

<h2 id="collision-detection-basics">Collision Detection Basics</h2>

<p>Detecting collisions between shapes is quite a difficult challenge. It takes a lot of diligence to learn all the mathematics covered in this article up to this point. We will cover a couple select algorithms to get you started, but a full discussion of collision algorithms is a bit out of scope. Some additional resources are linked at the end of this section.</p>

<h3 id="implicit-shapes">Implicit Shapes</h3>

<p>Implicitly defined shapes are ones we can represent with a small bit of information, as opposed to storing a mesh or array of vertices. Good candidates in 2D include circles, capsules, rays, and axis aligned boxes (aabb). Here’s my recommendation on how to setup your implicit shapes to make writing collision detection routines as easy as possible. Note these definitions were all provided earlier in this document (they’re the same as before).</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">circle</span>
<span class="p">{</span>
	<span class="n">circle</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">circle</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="kt">float</span> <span class="n">r</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">p</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">r</span> <span class="o">=</span> <span class="n">r</span><span class="p">;</span> <span class="p">}</span>
	<span class="n">circle</span><span class="p">(</span><span class="kt">float</span> <span class="n">x</span><span class="p">,</span> <span class="kt">float</span> <span class="n">y</span><span class="p">,</span> <span class="kt">float</span> <span class="n">r</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">p</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">);</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">r</span> <span class="o">=</span> <span class="n">r</span><span class="p">;</span> <span class="p">}</span>
	<span class="n">v2</span> <span class="n">p</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">r</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#define POLYGON_MAX_VERTS 8
</span>
<span class="k">struct</span> <span class="nc">polygon</span>
<span class="p">{</span>
	<span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">verts</span><span class="p">[</span><span class="n">POLYGON_MAX_VERTS</span><span class="p">];</span>
	<span class="n">v2</span> <span class="n">norms</span><span class="p">[</span><span class="n">POLYGON_MAX_VERTS</span><span class="p">];</span>
	<span class="kt">void</span> <span class="n">compute_norms</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">count</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
			<span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;</span> <span class="n">count</span> <span class="o">?</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
			<span class="n">norms</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">norm</span><span class="p">(</span><span class="n">skew</span><span class="p">(</span><span class="n">verts</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="n">verts</span><span class="p">[</span><span class="n">j</span><span class="p">]));</span>
		<span class="p">}</span>
	<span class="p">}</span>
<span class="p">};</span></code></pre></figure>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">aabb</span>
<span class="p">{</span>
	<span class="n">aabb</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">aabb</span><span class="p">(</span><span class="n">v2</span> <span class="n">min</span><span class="p">,</span> <span class="n">v2</span> <span class="n">max</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">min</span> <span class="o">=</span> <span class="n">min</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">max</span> <span class="o">=</span> <span class="n">max</span><span class="p">;</span> <span class="p">}</span>
	<span class="n">v2</span> <span class="n">min</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">max</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">raycast_output</span>
<span class="p">{</span>
	<span class="kt">float</span> <span class="n">t</span><span class="p">;</span> <span class="c1">// Time of impact.</span>
	<span class="n">v2</span> <span class="n">n</span><span class="p">;</span>    <span class="c1">// Normal of the surface at impact (unit length).</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">ray</span>
<span class="p">{</span>
	<span class="n">ray</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
	<span class="n">ray</span><span class="p">(</span><span class="n">v2</span> <span class="n">p</span><span class="p">,</span> <span class="n">v2</span> <span class="n">d</span><span class="p">,</span> <span class="kt">float</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">p</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">d</span> <span class="o">=</span> <span class="n">d</span><span class="p">;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">t</span> <span class="o">=</span> <span class="n">t</span><span class="p">;</span> <span class="p">}</span>
	<span class="n">v2</span> <span class="n">p</span><span class="p">;</span>    <span class="c1">// Start position.</span>
	<span class="n">v2</span> <span class="n">d</span><span class="p">;</span>    <span class="c1">// Direction of the ray (normalized)</span>
	<span class="kt">float</span> <span class="n">t</span><span class="p">;</span> <span class="c1">// Distance along d the ray travels.</span>
	<span class="n">v2</span> <span class="n">endpoint</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">p</span> <span class="o">+</span> <span class="n">d</span> <span class="o">*</span> <span class="n">t</span><span class="p">;</span> <span class="p">}</span>
	<span class="n">v2</span> <span class="n">impact</span><span class="p">(</span><span class="n">raycast_output</span> <span class="n">hit_data</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">p</span> <span class="o">+</span> <span class="n">d</span> <span class="o">*</span> <span class="n">hit_data</span><span class="p">.</span><span class="n">t</span><span class="p">;</span> <span class="p">}</span>
<span class="p">};</span></code></pre></figure>

<h3 id="circle-to-circle">Circle to Circle</h3>

<p>Once we compute the distance between two circle centers, using the <a href="https://en.wikipedia.org/wiki/Pythagorean_theorem">Pythagorean Theorem</a>, we can compare it to the sum of the radii. If the radii are longer than the distance the circles interesect, otherwise they don’t intersect.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">bool</span> <span class="nf">circle_to_circle</span><span class="p">(</span><span class="n">circle</span> <span class="n">circ_a</span><span class="p">,</span> <span class="n">circle</span> <span class="n">circ_b</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">d</span> <span class="o">=</span> <span class="n">circ_b</span><span class="p">.</span><span class="n">p</span> <span class="o">-</span> <span class="n">circ_a</span><span class="p">.</span><span class="n">p</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">d2</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">d</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">r</span> <span class="o">=</span> <span class="n">circ_a</span><span class="p">.</span><span class="n">r</span> <span class="o">+</span> <span class="n">circ_b</span><span class="p">.</span><span class="n">r</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">d2</span> <span class="o">&lt;</span> <span class="n">r</span> <span class="o">*</span> <span class="n">r</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>In order to resolve this collision a bit more information is needed such as the depth of the collision, and a vector to push the shapes away from each other. The best vector would be the axis of minimum penetration. It means the axis with the smallest signed distance to separate the shapes. You can find more information about this special axis by reading online about the Separating Axis Test.</p>

<p>For the case of circles the axis is always going to be the normalized vector from one circle center to another, except when the circles are perfectly on top of each other, where we must choose an arbitrary axis to push along.</p>

<h4 id="collision-manifold">Collision Manifold</h4>

<p>The information gathered from a collision routine on how shapes are touching is often called the collision <a href="https://en.wikipedia.org/wiki/Manifold">manifold</a>. It’s a fancy word that means the topology (surface) of an enclosed shape (convex shapes in our case). Often times this manifold information will be used for one of two major purposes:</p>

<ol>
  <li>Physics engines to resolve collisions semi-realistically.</li>
  <li>Gameplay logic to understand how things hit each other, like what the surface is like when a player walks upon it.</li>
</ol>

<p>The manifold should consist of penetration depth (how deeply shapes are intersecting), a collision normal (the axis of minimum penetration), and optionally points of contact along the collision plane. Here’s an example struct definition:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">collision_data</span>
<span class="p">{</span>
	<span class="kt">int</span> <span class="n">count</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">points</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
	<span class="kt">float</span> <span class="n">depth</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
	<span class="n">v2</span> <span class="n">normal</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<p>For more advanced collision routines a time of impact may also be calculated and represented as a single float <code class="language-plaintext highlighter-rouge">t</code> from 0 to 1.</p>

<p>The reason <code class="language-plaintext highlighter-rouge">points</code> is an array of up to two unique points is that the collision manifold exists within the contact plane. This means the plane orthogonal to the axis of minimum separation. The 2D cross-section of a convex polygon is merely a line segment, so two points suffices. In 3D however, more points are needed. Depending on the physics engine it could be anywhere from 3-8 points in practice, 4-5 being a golden spot. These hit points are mostly needed for phyics engines. If gameplay is the only customer then a single point of contact is likely all that’s necessary, if any at all.</p>

<p>We can augment our circle collision function to generate a manifold in the event a collision is detected. For now I will generate a single contact point for simplicity. By convention we can name each input shape <code class="language-plaintext highlighter-rouge">a</code> and <code class="language-plaintext highlighter-rouge">b</code> respectively, and always generate a <code class="language-plaintext highlighter-rouge">hit_spot</code> on the surface of <code class="language-plaintext highlighter-rouge">b</code>.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">collision_data</span>
<span class="p">{</span>
	<span class="kt">bool</span> <span class="n">hit</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">hit_spot</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">depth</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">normal</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">collision_data</span> <span class="nf">circle_to_circle</span><span class="p">(</span><span class="n">circle</span> <span class="n">circ_a</span><span class="p">,</span> <span class="n">circle</span> <span class="n">circ_b</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">collision_data</span> <span class="n">out</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">d</span> <span class="o">=</span> <span class="n">circ_b</span><span class="p">.</span><span class="n">p</span> <span class="o">-</span> <span class="n">circ_a</span><span class="p">.</span><span class="n">p</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">d2</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">d</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">r</span> <span class="o">=</span> <span class="n">circ_a</span><span class="p">.</span><span class="n">r</span> <span class="o">+</span> <span class="n">circ_b</span><span class="p">.</span><span class="n">r</span><span class="p">;</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">d2</span> <span class="o">&lt;</span> <span class="n">r</span> <span class="o">*</span> <span class="n">r</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">out</span><span class="p">.</span><span class="n">hit</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
		<span class="n">out</span><span class="p">.</span><span class="n">hit_spot</span> <span class="o">=</span> <span class="n">circ_b</span><span class="p">.</span><span class="n">p</span> <span class="o">-</span> <span class="n">norm</span><span class="p">(</span><span class="n">d</span><span class="p">)</span> <span class="o">*</span> <span class="n">circ_b</span><span class="p">.</span><span class="n">r</span><span class="p">;</span>
		<span class="n">out</span><span class="p">.</span><span class="n">depth</span> <span class="o">=</span> <span class="n">r</span> <span class="o">-</span> <span class="n">len</span><span class="p">(</span><span class="n">d</span><span class="p">);</span>
		<span class="n">out</span><span class="p">.</span><span class="n">normal</span> <span class="o">=</span> <span class="n">norm</span><span class="p">(</span><span class="n">d</span><span class="p">);</span>
	<span class="p">}</span>
	<span class="k">return</span> <span class="n">out</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>This function still suffers from numeric robustness problems. If circles <code class="language-plaintext highlighter-rouge">a</code> and <code class="language-plaintext highlighter-rouge">b</code> are right on top of each other the length of <code class="language-plaintext highlighter-rouge">d</code> will be 0 and cause <code class="language-plaintext highlighter-rouge">norm</code> to fail with a division by zero error. In the case of zero distance we can simply choose an arbitrary axis for <code class="language-plaintext highlighter-rouge">n</code>. This also lends itself to a minor optimization where <code class="language-plaintext highlighter-rouge">len</code> is only called once (as we omit the extra calls to <code class="language-plaintext highlighter-rouge">norm</code> that call <code class="language-plaintext highlighter-rouge">len</code> internally).</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">collision_data</span> <span class="nf">circle_to_circle</span><span class="p">(</span><span class="n">circle</span> <span class="n">circ_a</span><span class="p">,</span> <span class="n">circle</span> <span class="n">circ_b</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">collision_data</span> <span class="n">out</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">d</span> <span class="o">=</span> <span class="n">circ_b</span><span class="p">.</span><span class="n">p</span> <span class="o">-</span> <span class="n">circ_a</span><span class="p">.</span><span class="n">p</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">d2</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">d</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">r</span> <span class="o">=</span> <span class="n">circ_a</span><span class="p">.</span><span class="n">r</span> <span class="o">+</span> <span class="n">circ_b</span><span class="p">.</span><span class="n">r</span><span class="p">;</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">d2</span> <span class="o">&lt;</span> <span class="n">r</span> <span class="o">*</span> <span class="n">r</span><span class="p">)</span> <span class="p">{</span>
		<span class="kt">float</span> <span class="n">l</span> <span class="o">=</span> <span class="n">len</span><span class="p">(</span><span class="n">d</span><span class="p">);</span>
		<span class="n">d</span> <span class="o">=</span> <span class="n">l</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">?</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">:</span> <span class="n">d</span> <span class="o">*</span> <span class="p">(</span><span class="mf">1.0</span><span class="n">f</span> <span class="o">/</span> <span class="n">l</span><span class="p">);</span>
		<span class="n">out</span><span class="p">.</span><span class="n">hit</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
		<span class="n">out</span><span class="p">.</span><span class="n">hit_spot</span> <span class="o">=</span> <span class="n">circ_b</span><span class="p">.</span><span class="n">p</span> <span class="o">-</span> <span class="n">d</span> <span class="o">*</span> <span class="n">circ_b</span><span class="p">.</span><span class="n">r</span><span class="p">;</span>
		<span class="n">out</span><span class="p">.</span><span class="n">depth</span> <span class="o">=</span> <span class="n">r</span> <span class="o">-</span> <span class="n">l</span><span class="p">;</span>
		<span class="n">out</span><span class="p">.</span><span class="n">normal</span> <span class="o">=</span> <span class="n">d</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="k">return</span> <span class="n">out</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>As you can see, generating the manifold requires a lot of extra work and implementation! But the information is very valuable for physics and gameplay alike.</p>

<h3 id="aabb-to-aabb">AABB to AABB</h3>

<p>Here’s the typical aabb to aabb test. It simply checks the four face planes by looking directly at the <code class="language-plaintext highlighter-rouge">x</code> and <code class="language-plaintext highlighter-rouge">y</code> components of <code class="language-plaintext highlighter-rouge">min</code> and <code class="language-plaintext highlighter-rouge">max</code> elements of our aabb struct.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">bool</span> <span class="nf">aabb_to_aabb</span><span class="p">(</span><span class="n">aabb</span> <span class="n">a</span><span class="p">,</span> <span class="n">aabb</span> <span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">b</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">a</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">x</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">b</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">x</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">b</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">y</span> <span class="o">&lt;</span> <span class="n">a</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">y</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">y</span> <span class="o">&lt;</span> <span class="n">b</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">y</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
	<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>This function can be optimized to remove excess <a href="https://en.wikipedia.org/wiki/Branch_(computer_science)">branching</a> so the branch predictor cannot fail.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">bool</span> <span class="nf">aabb_to_aabb</span><span class="p">(</span><span class="n">aabb</span> <span class="n">a</span><span class="p">,</span> <span class="n">aabb</span> <span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">bool</span> <span class="n">d0</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">a</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
	<span class="kt">bool</span> <span class="n">d1</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">b</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
	<span class="kt">bool</span> <span class="n">d2</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">y</span> <span class="o">&lt;</span> <span class="n">a</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>
	<span class="kt">bool</span> <span class="n">d3</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">max</span><span class="p">.</span><span class="n">y</span> <span class="o">&lt;</span> <span class="n">b</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>
	<span class="k">return</span> <span class="o">!</span><span class="p">(</span><span class="n">d0</span> <span class="o">|</span> <span class="n">d1</span> <span class="o">|</span> <span class="n">d2</span> <span class="o">|</span> <span class="n">d3</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>You may be wondering why we used bitwise or <code class="language-plaintext highlighter-rouge">|</code> instead of conditional or <code class="language-plaintext highlighter-rouge">||</code>. The conditional operator will often generate branches in assembly structure, as defined by the C standard if the first of a conditional fails the rest need not be checked. By using the bitwise operator we instead perform four bitwise or’s without any branching logic at all. This makes our function run in constant and predictable time with no branching.</p>

<p>As usual, generate a mafifold is way harder than merely detecting a collision. The algorithm works by checking for overlap on first the x-axis and then the y-axis. This is very similar to the previous test, but actually calculates an overlap distance rather than just checking for a sign with the <code class="language-plaintext highlighter-rouge">&lt;</code> operator. If either axis is separating we can immediately return no interesction (due to the Separating Axis Test).</p>

<p>Otherwise we must see if the boxes are intersecting more on the x or y-axis. Once known we can immediately deduce a good contact point and the surface normal.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">collision_data</span> <span class="nf">aabb_to_aabb</span><span class="p">(</span><span class="n">aabb</span> <span class="n">a</span><span class="p">,</span> <span class="n">aabb</span> <span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">collision_data</span> <span class="n">out</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">mid_a</span> <span class="o">=</span> <span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">a</span><span class="p">.</span><span class="n">max</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">mid_b</span> <span class="o">=</span> <span class="p">(</span><span class="n">b</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">max</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">ea</span> <span class="o">=</span> <span class="n">abs</span><span class="p">((</span><span class="n">a</span><span class="p">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">a</span><span class="p">.</span><span class="n">min</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span><span class="p">);</span>
	<span class="n">v2</span> <span class="n">eb</span> <span class="o">=</span> <span class="n">abs</span><span class="p">((</span><span class="n">b</span><span class="p">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">min</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span><span class="p">);</span>
	<span class="n">v2</span> <span class="n">d</span> <span class="o">=</span> <span class="n">mid_b</span> <span class="o">-</span> <span class="n">mid_a</span><span class="p">;</span>

	<span class="c1">// calc overlap on x and y axes</span>
	<span class="kt">float</span> <span class="n">dx</span> <span class="o">=</span> <span class="n">ea</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">eb</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">abs</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">x</span><span class="p">);</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">dx</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="n">out</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">dy</span> <span class="o">=</span> <span class="n">ea</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">eb</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">abs</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">y</span><span class="p">);</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">dy</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="n">out</span><span class="p">;</span>

	<span class="n">v2</span> <span class="n">n</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">depth</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">p</span><span class="p">;</span>

	<span class="k">if</span> <span class="p">(</span><span class="n">dx</span> <span class="o">&lt;</span> <span class="n">dy</span><span class="p">)</span> <span class="p">{</span>
		<span class="c1">// x axis overlap is smaller</span>
		<span class="n">depth</span> <span class="o">=</span> <span class="n">dx</span><span class="p">;</span>
		<span class="k">if</span> <span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">x</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">n</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="o">-</span><span class="mf">1.0</span><span class="n">f</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
			<span class="n">p</span> <span class="o">=</span> <span class="n">mid_a</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="n">ea</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
		<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
			<span class="n">n</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mf">1.0</span><span class="n">f</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
			<span class="n">p</span> <span class="o">=</span> <span class="n">mid_a</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="n">ea</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
		<span class="p">}</span>
	<span class="p">}</span>  <span class="k">else</span> <span class="p">{</span>
		<span class="c1">// y axis overlap is smaller</span>
		<span class="n">depth</span> <span class="o">=</span> <span class="n">dy</span><span class="p">;</span>
		<span class="k">if</span> <span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">y</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">n</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.0</span><span class="n">f</span><span class="p">);</span>
			<span class="n">p</span> <span class="o">=</span> <span class="n">mid_a</span> <span class="o">-</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">ea</span><span class="p">.</span><span class="n">y</span><span class="p">);</span>
		<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
			<span class="n">n</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">1.0</span><span class="n">f</span><span class="p">);</span>
			<span class="n">p</span> <span class="o">=</span> <span class="n">mid_a</span> <span class="o">+</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">ea</span><span class="p">.</span><span class="n">y</span><span class="p">);</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="n">out</span><span class="p">.</span><span class="n">hit</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
	<span class="n">out</span><span class="p">.</span><span class="n">hit_spot</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span>
	<span class="n">out</span><span class="p">.</span><span class="n">depth</span> <span class="o">=</span> <span class="n">depth</span><span class="p">;</span>
	<span class="n">out</span><span class="p">.</span><span class="n">normal</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">out</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<h3 id="circle-to-aabb">Circle to AABB</h3>

<p>The circle to aabb collision detection function is a lot like the circle to circle collision detection function. The trick is to compute the closest point on the aabb to the circle, then perform a circle to circle test with a radius of 0. In older literature the closest point is often called <code class="language-plaintext highlighter-rouge">L</code>, so we copy that old naming convention here for fun. But if I were you I’d probably name it “closest_point”.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">float</span> <span class="nf">clamp</span><span class="p">(</span><span class="kt">float</span> <span class="n">v</span><span class="p">,</span> <span class="kt">float</span> <span class="n">lo</span><span class="p">,</span> <span class="kt">float</span> <span class="n">hi</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">min</span><span class="p">(</span><span class="n">max</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">lo</span><span class="p">),</span> <span class="n">hi</span><span class="p">);</span> <span class="p">}</span>
<span class="n">v2</span> <span class="n">clamp</span><span class="p">(</span><span class="n">v2</span> <span class="n">v</span><span class="p">,</span> <span class="n">v2</span> <span class="n">lo</span><span class="p">,</span> <span class="n">v2</span> <span class="n">hi</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">v2</span><span class="p">(</span><span class="n">clamp</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">lo</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">hi</span><span class="p">.</span><span class="n">x</span><span class="p">),</span> <span class="n">clamp</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">lo</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">hi</span><span class="p">.</span><span class="n">y</span><span class="p">));</span> <span class="p">}</span>

<span class="kt">bool</span> <span class="n">circle_to_aabb</span><span class="p">(</span><span class="n">circle</span> <span class="n">a</span><span class="p">,</span> <span class="n">aabb</span> <span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">v2</span> <span class="n">L</span> <span class="o">=</span> <span class="n">clamp</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">p</span><span class="p">,</span> <span class="n">b</span><span class="p">.</span><span class="n">min</span><span class="p">,</span> <span class="n">b</span><span class="p">.</span><span class="n">max</span><span class="p">);</span>
	<span class="n">v2</span> <span class="n">ab</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">p</span> <span class="o">-</span> <span class="n">L</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">d2</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">ab</span><span class="p">,</span> <span class="n">ab</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">r2</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">r</span> <span class="o">*</span> <span class="n">a</span><span class="p">.</span><span class="n">r</span><span class="p">;</span>
	<span class="k">return</span> <span class="n">d2</span> <span class="o">&lt;</span> <span class="n">r2</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>You guessed it – writing the manifold version is <em>way harder</em>. We start off the same, calculating L the closest point on the box to the circle. There are two cases to look for: shallow and deep intersections. If the circle center intersects the box it’s a deep interesction, shallow otherwise.</p>

<p>For the shallow case we simply treat the problem as two circles, where the circle on L has a radius of 0. For the deep case we snap the sphere’s center to the box’s exterior, immediately giving us all our manifold pieces (the normal, the depth and a collision point on the surface of the aabb).</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">collision_data</span> <span class="nf">circle_to_aabb</span><span class="p">(</span><span class="n">circle</span> <span class="n">a</span><span class="p">,</span> <span class="n">aabb</span> <span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">collision_data</span> <span class="n">out</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">L</span> <span class="o">=</span> <span class="n">clamp</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">p</span><span class="p">,</span> <span class="n">b</span><span class="p">.</span><span class="n">min</span><span class="p">,</span> <span class="n">b</span><span class="p">.</span><span class="n">max</span><span class="p">);</span>
	<span class="n">v2</span> <span class="n">ab</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">p</span> <span class="o">-</span> <span class="n">L</span><span class="p">;</span>
	<span class="kt">float</span> <span class="n">d2</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">ab</span><span class="p">,</span> <span class="n">ab</span><span class="p">);</span>
	<span class="kt">float</span> <span class="n">r2</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">r</span> <span class="o">*</span> <span class="n">a</span><span class="p">.</span><span class="n">r</span><span class="p">;</span>

	<span class="k">if</span> <span class="p">(</span><span class="n">d2</span> <span class="o">&lt;</span> <span class="n">r2</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">if</span> <span class="p">(</span><span class="n">d2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="c1">// shallow (center of circle not inside of AABB)</span>
			<span class="kt">float</span> <span class="n">d</span> <span class="o">=</span> <span class="n">sqrtf</span><span class="p">(</span><span class="n">d2</span><span class="p">);</span>
			<span class="n">v2</span> <span class="n">n</span> <span class="o">=</span> <span class="n">norm</span><span class="p">(</span><span class="n">ab</span><span class="p">);</span>
			<span class="n">out</span><span class="p">.</span><span class="n">hit</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
			<span class="n">out</span><span class="p">.</span><span class="n">depth</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">r</span> <span class="o">-</span> <span class="n">d</span><span class="p">;</span>
			<span class="n">out</span><span class="p">.</span><span class="n">hit_spot</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">p</span> <span class="o">+</span> <span class="n">n</span> <span class="o">*</span> <span class="n">d</span><span class="p">;</span>
			<span class="n">out</span><span class="p">.</span><span class="n">normal</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span>
		<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
			<span class="c1">// deep (center of circle inside of AABB)</span>
			<span class="c1">// clamp circle's center to edge of AABB, then form the manifold</span>
			<span class="n">v2</span> <span class="n">mid</span> <span class="o">=</span> <span class="p">(</span><span class="n">b</span><span class="p">.</span><span class="n">min</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">max</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span><span class="p">;</span>
			<span class="n">v2</span> <span class="n">e</span> <span class="o">=</span> <span class="p">(</span><span class="n">b</span><span class="p">.</span><span class="n">max</span> <span class="o">-</span> <span class="n">b</span><span class="p">.</span><span class="n">min</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span><span class="n">f</span><span class="p">;</span>
			<span class="n">v2</span> <span class="n">d</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">p</span> <span class="o">-</span> <span class="n">mid</span><span class="p">;</span>
			<span class="n">v2</span> <span class="n">abs_d</span> <span class="o">=</span> <span class="n">abs</span><span class="p">(</span><span class="n">d</span><span class="p">);</span>

			<span class="kt">float</span> <span class="n">x_overlap</span> <span class="o">=</span> <span class="n">e</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">abs_d</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
			<span class="kt">float</span> <span class="n">y_overlap</span> <span class="o">=</span> <span class="n">e</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">abs_d</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>

			<span class="kt">float</span> <span class="n">depth</span><span class="p">;</span>
			<span class="n">v2</span> <span class="n">n</span><span class="p">;</span>

			<span class="k">if</span> <span class="p">(</span><span class="n">x_overlap</span> <span class="o">&lt;</span> <span class="n">y_overlap</span><span class="p">)</span> <span class="p">{</span>
				<span class="n">depth</span> <span class="o">=</span> <span class="n">x_overlap</span><span class="p">;</span>
				<span class="n">n</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mf">1.0</span><span class="n">f</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
				<span class="n">n</span> <span class="o">*=</span> <span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">x</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="mf">1.0</span><span class="n">f</span> <span class="o">:</span> <span class="o">-</span><span class="mf">1.0</span><span class="n">f</span><span class="p">);</span>
			<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
				<span class="n">depth</span> <span class="o">=</span> <span class="n">y_overlap</span><span class="p">;</span>
				<span class="n">n</span> <span class="o">=</span> <span class="n">v2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">1.0</span><span class="n">f</span><span class="p">);</span>
				<span class="n">n</span> <span class="o">*=</span> <span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">y</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="mf">1.0</span><span class="n">f</span> <span class="o">:</span> <span class="o">-</span><span class="mf">1.0</span><span class="n">f</span><span class="p">);</span>
			<span class="p">}</span>

			<span class="n">out</span><span class="p">.</span><span class="n">hit</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
			<span class="n">out</span><span class="p">.</span><span class="n">depth</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">r</span> <span class="o">+</span> <span class="n">depth</span><span class="p">;</span>
			<span class="n">out</span><span class="p">.</span><span class="n">hit_spot</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">p</span> <span class="o">-</span> <span class="n">n</span> <span class="o">*</span> <span class="n">depth</span><span class="p">;</span>
			<span class="n">out</span><span class="p">.</span><span class="n">normal</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="n">out</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<h3 id="convex-hull">Convex Hull</h3>

<p>Computing the <a href="https://en.wikipedia.org/wiki/Convex_hull">convex hull</a> from a set of points is a critical operation for collision detection. In 2D usually hulls are defined by a set of counter-clockwise vertices. The convexity of a convex hull allows us to perform a variety of very useful collision detection tests without too much trouble.</p>

<p>This mainly comes from the planes of the convex hull. Each plane of a convex hull corresponds to one of the faces. If we visualize the negative space behind a plane as the half of all space pointing away from the plane’s normal vector, we notice for a convex hull the interior is te negative space. Another way to rephrase this: inside the convex hull is behind all of the face planes.</p>

<h4 id="point-in-polygon-convex">Point in Polygon (Convex)</h4>

<p>A similar observation pops up for the outside of a convex hull – outside of a convex hull is on the positive space of <em>at least one</em> of the planes. This lets us write down a very simple and efficient routine to detect point in convex polygon.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">bool</span> <span class="nf">point_in_poly</span><span class="p">(</span><span class="n">polygon</span> <span class="n">poly</span><span class="p">,</span> <span class="n">v2</span> <span class="n">p</span><span class="p">)</span>
<span class="p">{</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">poly</span><span class="p">.</span><span class="n">count</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
		<span class="kt">float</span> <span class="n">c</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">poly</span><span class="p">.</span><span class="n">norms</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">poly</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
		<span class="kt">float</span> <span class="n">dist</span> <span class="o">=</span> <span class="n">dot</span><span class="p">(</span><span class="n">poly</span><span class="p">.</span><span class="n">norms</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">p</span><span class="p">)</span> <span class="o">-</span> <span class="n">c</span><span class="p">;</span>
		<span class="k">if</span> <span class="p">(</span><span class="n">dist</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<h4 id="other-convex-hull-tests">Other Convex Hull Tests</h4>

<p>Here are some other particularly interesting tests you can consider learning about outside of this article. This article is already too long, so I can’t cram in all these details in one place!</p>

<ul>
  <li>Point in concave polygon (ray odd/even hit test), Ericson Real-Time Collision Detection</li>
  <li><a href="https://www.gdcvault.com/play/1017646/Physics-for-Game-Programmers-The">Polygon to Polygon via SAT</a> (separating axis theorem/test)</li>
  <li><a href="https://box2d.org/files/ErinCatto_DynamicBVH_Full.pdf">Broadphase, or Bounding Volume Heirarchy</a> (BVH) (especially the dynamic aabb tree by E. Catto)</li>
  <li>Time of impact (TOI), swept collision detection, or <a href="https://box2d.org/files/ErinCatto_ContinuousCollision_GDC2013.pdf">continuous collision</a></li>
</ul>

<h4 id="computing-a-convex-hull">Computing a Convex Hull</h4>

<p>From reading Christer Ericson’s orange book Real-Time Collision Detection we can implement the simplest algorithm I know of for computing a 2D convex hull, Andrew’s algorithm. The only predicate used is the <code class="language-plaintext highlighter-rouge">det2</code> function to figure out if a set of vertices are on counter-clockwise or clockwise order. The main step of the algorithm looks at three points and forms two vectors each starting from one point, and pointing to the other two points. This is exactly like our section on the <code class="language-plaintext highlighter-rouge">shortest_arc</code> function using the <code class="language-plaintext highlighter-rouge">det2</code> function. Here is the algorithm:</p>

<ol>
  <li>First sort all the input points from smallest to largest on the x-axis. To break ties, sort from smallest to largest on the y-axis.</li>
  <li>Add the two left-most vertices to the hull. The first <em>will be on the convex hull</em>, while the second is tentative.</li>
  <li>Check the next vertex, going from left to right, and see if it’s on the left (counter-clockwise negative) or right (clockwise positive) using <code class="language-plaintext highlighter-rouge">det2</code>.</li>
  <li>If the vertex is more left than our tentative vertex, pop the tentative vertex off the hull and and replace it with the next vertex.</li>
  <li>Continue steps 3-4 until we reach a tentative vertex that creates a clockwise orientation, or run out of points to pop.</li>
  <li>Complete once we loop over all the points. We have added the top-half or bottom-half of the hull (depending on how you compute the inputs to <code class="language-plaintext highlighter-rouge">det2</code>, in our example below this was the bottom-half).</li>
  <li>Repeat the process for the other half of the hull.</li>
  <li>Remove the extra point at the end of the hull output.</li>
</ol>

<p>Check out this animation of the algorithm from <a href="https://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain">wikibooks on Andrew’s Algorithm</a>.</p>

<p><img src="/assets/andrew_monotone.gif" alt="andrew_monotone" /></p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="c1">// Andrew's Algorithm from Ericson's Real-Time Collision Detection book.</span>
<span class="kt">int</span> <span class="nf">convex_hull</span><span class="p">(</span><span class="n">v2</span><span class="o">*</span> <span class="n">verts</span><span class="p">,</span> <span class="kt">int</span> <span class="n">count</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">count</span> <span class="o">=</span> <span class="n">min</span><span class="p">(</span><span class="n">count</span><span class="p">,</span> <span class="n">POLYGON_MAX_VERTS</span><span class="p">);</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">count</span> <span class="o">&lt;</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="c1">// Sort lexicographically (on x-axis, then y-axis).</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">count</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
		<span class="kt">int</span> <span class="n">lo</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
		<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">count</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span><span class="p">)</span> <span class="p">{</span>
			<span class="k">if</span> <span class="p">(</span><span class="n">verts</span><span class="p">[</span><span class="n">j</span><span class="p">].</span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">verts</span><span class="p">[</span><span class="n">lo</span><span class="p">].</span><span class="n">x</span><span class="p">)</span> <span class="p">{</span>
				<span class="n">lo</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span>
			<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">verts</span><span class="p">[</span><span class="n">j</span><span class="p">].</span><span class="n">x</span> <span class="o">==</span> <span class="n">verts</span><span class="p">[</span><span class="n">lo</span><span class="p">].</span><span class="n">x</span> <span class="o">&amp;&amp;</span> <span class="n">verts</span><span class="p">[</span><span class="n">j</span><span class="p">].</span><span class="n">y</span> <span class="o">&lt;</span> <span class="n">verts</span><span class="p">[</span><span class="n">lo</span><span class="p">].</span><span class="n">y</span><span class="p">)</span> <span class="p">{</span>
				<span class="n">lo</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span>
			<span class="p">}</span>
		<span class="p">}</span>
		<span class="n">v2</span> <span class="n">swap</span> <span class="o">=</span> <span class="n">verts</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
		<span class="n">verts</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">verts</span><span class="p">[</span><span class="n">lo</span><span class="p">];</span>
		<span class="n">verts</span><span class="p">[</span><span class="n">lo</span><span class="p">]</span> <span class="o">=</span> <span class="n">swap</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
	<span class="kt">int</span> <span class="n">hull</span><span class="p">[</span><span class="n">POLYGON_MAX_VERTS</span> <span class="o">+</span> <span class="mi">1</span><span class="p">];</span>
	<span class="n">hull</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="n">hull</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>

	<span class="c1">// Find lower-half of hull.</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">count</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">v2</span> <span class="n">e0</span> <span class="o">=</span> <span class="n">verts</span><span class="p">[</span><span class="n">hull</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]]</span> <span class="o">-</span> <span class="n">verts</span><span class="p">[</span><span class="n">hull</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">]];</span>
			<span class="n">v2</span> <span class="n">e1</span> <span class="o">=</span> <span class="n">verts</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="n">verts</span><span class="p">[</span><span class="n">hull</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">]];</span>
			<span class="k">if</span> <span class="p">(</span><span class="n">det2</span><span class="p">(</span><span class="n">e0</span><span class="p">,</span> <span class="n">e1</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="o">--</span><span class="n">j</span><span class="p">;</span>
			<span class="k">else</span> <span class="k">break</span><span class="p">;</span>
		<span class="p">}</span>
		<span class="n">hull</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="c1">// Find top-half of hull.</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">count</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="n">j</span><span class="o">+</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">;</span> <span class="o">--</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="n">k</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">v2</span> <span class="n">e0</span> <span class="o">=</span> <span class="n">verts</span><span class="p">[</span><span class="n">hull</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]]</span> <span class="o">-</span> <span class="n">verts</span><span class="p">[</span><span class="n">hull</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">]];</span>
			<span class="n">v2</span> <span class="n">e1</span> <span class="o">=</span> <span class="n">verts</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="n">verts</span><span class="p">[</span><span class="n">hull</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">2</span><span class="p">]];</span>
			<span class="k">if</span> <span class="p">(</span><span class="n">det2</span><span class="p">(</span><span class="n">e0</span><span class="p">,</span> <span class="n">e1</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="o">--</span><span class="n">j</span><span class="p">;</span>
			<span class="k">else</span> <span class="k">break</span><span class="p">;</span>
		<span class="p">}</span>
		<span class="n">hull</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="o">--</span><span class="n">j</span><span class="p">;</span> <span class="c1">// Pop the last vert off as it's a duplicate.</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="mi">3</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">hull_verts</span><span class="p">[</span><span class="n">POLYGON_MAX_VERTS</span><span class="p">];</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">j</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="n">hull_verts</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">verts</span><span class="p">[</span><span class="n">hull</span><span class="p">[</span><span class="n">i</span><span class="p">]];</span>
	<span class="n">memcpy</span><span class="p">(</span><span class="n">verts</span><span class="p">,</span> <span class="n">hull_verts</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">v2</span><span class="p">)</span> <span class="o">*</span> <span class="n">j</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">j</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<h4 id="slicing-a-convex-hull">Slicing a Convex Hull</h4>

<p><a href="https://gist.github.com/RandyGaul/8b9c3f3724ea34959586205220be1da3">Sutherland-Hodgman clipping algorithm</a> for <a href="https://gamedevelopment.tutsplus.com/tutorials/how-to-dynamically-slice-a-convex-shape--gamedev-14479">Dynamic Shape Slicing (an article I wrote some time ago)</a> is a great way to make use of convex hulls. Rather than get into all the details I’ll just recommend you check out my other article if you’re interested! Here’s the source code for the function to split a polygon <code class="language-plaintext highlighter-rouge">in</code> into <code class="language-plaintext highlighter-rouge">front</code> and <code class="language-plaintext highlighter-rouge">back</code> polygons along a splitting plane <code class="language-plaintext highlighter-rouge">split</code>.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">sutherland_hodgman_output</span>
<span class="p">{</span>
	<span class="n">polygon</span> <span class="n">front</span><span class="p">;</span>
	<span class="n">polygon</span> <span class="n">back</span><span class="p">;</span>
<span class="p">};</span>

<span class="kt">bool</span> <span class="n">in_front</span><span class="p">(</span><span class="kt">float</span> <span class="n">distance</span><span class="p">,</span> <span class="kt">float</span> <span class="n">epsilon</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">distance</span> <span class="o">&gt;</span> <span class="n">epsilon</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">bool</span> <span class="n">behind</span><span class="p">(</span><span class="kt">float</span> <span class="n">distance</span><span class="p">,</span> <span class="kt">float</span> <span class="n">epsilon</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">distance</span> <span class="o">&lt;</span> <span class="o">-</span><span class="n">epsilon</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">bool</span> <span class="n">on</span><span class="p">(</span><span class="kt">float</span> <span class="n">distance</span><span class="p">,</span> <span class="kt">float</span> <span class="n">epsilon</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="o">!</span><span class="n">in_front</span><span class="p">(</span><span class="n">distance</span><span class="p">,</span> <span class="n">epsilon</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">behind</span><span class="p">(</span><span class="n">distance</span><span class="p">,</span> <span class="n">epsilon</span><span class="p">);</span> <span class="p">}</span>

<span class="c1">// See: https://gamedevelopment.tutsplus.com/tutorials/how-to-dynamically-slice-a-convex-shape--gamedev-14479</span>
<span class="n">sutherland_hodgman_output</span> <span class="n">sutherland_hodgman</span><span class="p">(</span><span class="n">halfspace</span> <span class="n">split</span><span class="p">,</span> <span class="n">polygon</span> <span class="n">in</span><span class="p">,</span> <span class="k">const</span> <span class="kt">float</span> <span class="n">k_epsilon</span> <span class="o">=</span> <span class="mf">1.e-4</span><span class="n">f</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">sutherland_hodgman_output</span> <span class="n">out</span><span class="p">;</span>
	<span class="n">v2</span> <span class="n">a</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">in</span><span class="p">.</span><span class="n">count</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span>
	<span class="kt">float</span> <span class="n">da</span> <span class="o">=</span> <span class="n">distance</span><span class="p">(</span><span class="n">split</span><span class="p">,</span> <span class="n">a</span><span class="p">);</span>

	<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">in</span><span class="p">.</span><span class="n">count</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">v2</span> <span class="n">b</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
		<span class="kt">float</span> <span class="n">db</span> <span class="o">=</span> <span class="n">distance</span><span class="p">(</span><span class="n">split</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>

		<span class="k">if</span><span class="p">(</span><span class="n">in_front</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="n">k_epsilon</span><span class="p">))</span> <span class="p">{</span>
			<span class="k">if</span><span class="p">(</span><span class="n">behind</span><span class="p">(</span><span class="n">da</span><span class="p">,</span> <span class="n">k_epsilon</span><span class="p">))</span> <span class="p">{</span>
				<span class="n">v2</span> <span class="n">i</span> <span class="o">=</span> <span class="n">intersect</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">db</span><span class="p">,</span> <span class="n">da</span><span class="p">);</span>
				<span class="n">out</span><span class="p">.</span><span class="n">front</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">out</span><span class="p">.</span><span class="n">front</span><span class="p">.</span><span class="n">count</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
				<span class="n">out</span><span class="p">.</span><span class="n">back</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">out</span><span class="p">.</span><span class="n">back</span><span class="p">.</span><span class="n">count</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
			<span class="p">}</span>
			<span class="n">out</span><span class="p">.</span><span class="n">front</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">out</span><span class="p">.</span><span class="n">front</span><span class="p">.</span><span class="n">count</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">b</span><span class="p">;</span>
		<span class="p">}</span> <span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">behind</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="n">k_epsilon</span><span class="p">))</span> <span class="p">{</span>
			<span class="k">if</span><span class="p">(</span><span class="n">in_front</span><span class="p">(</span><span class="n">da</span><span class="p">,</span> <span class="n">k_epsilon</span><span class="p">))</span> <span class="p">{</span>
				<span class="n">v2</span> <span class="n">i</span> <span class="o">=</span> <span class="n">intersect</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">da</span><span class="p">,</span> <span class="n">db</span><span class="p">);</span>
				<span class="n">out</span><span class="p">.</span><span class="n">front</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">out</span><span class="p">.</span><span class="n">front</span><span class="p">.</span><span class="n">count</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
				<span class="n">out</span><span class="p">.</span><span class="n">back</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">out</span><span class="p">.</span><span class="n">back</span><span class="p">.</span><span class="n">count</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
			<span class="p">}</span> <span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">on</span><span class="p">(</span><span class="n">da</span><span class="p">,</span> <span class="n">k_epsilon</span><span class="p">))</span> <span class="p">{</span>
				<span class="n">out</span><span class="p">.</span><span class="n">back</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">out</span><span class="p">.</span><span class="n">back</span><span class="p">.</span><span class="n">count</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span>
			<span class="p">}</span>
			<span class="n">out</span><span class="p">.</span><span class="n">back</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">out</span><span class="p">.</span><span class="n">back</span><span class="p">.</span><span class="n">count</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">b</span><span class="p">;</span>
		<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
			<span class="n">out</span><span class="p">.</span><span class="n">front</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">out</span><span class="p">.</span><span class="n">front</span><span class="p">.</span><span class="n">count</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">b</span><span class="p">;</span>
			<span class="k">if</span><span class="p">(</span><span class="n">on</span><span class="p">(</span><span class="n">da</span><span class="p">,</span> <span class="n">k_epsilon</span><span class="p">))</span> <span class="p">{</span>
				<span class="n">out</span><span class="p">.</span><span class="n">back</span><span class="p">.</span><span class="n">verts</span><span class="p">[</span><span class="n">out</span><span class="p">.</span><span class="n">back</span><span class="p">.</span><span class="n">count</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">b</span><span class="p">;</span>
			<span class="p">}</span>
		<span class="p">}</span>

		<span class="n">a</span> <span class="o">=</span> <span class="n">b</span><span class="p">;</span>
		<span class="n">da</span> <span class="o">=</span> <span class="n">db</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="n">out</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<h3 id="advanced-collision-detection">Advanced Collision Detection</h3>

<p>More advanced collision detection routines are out of scope for this article. Things like Capsule and Polygon collisions require quite lot of complicated mathematics and code. That’s all for another time and another blog post! For now you can find a full implementation of correctly implemented and efficient 2D collisions routines at <a href="https://github.com/RandyGaul/cute_framework/blob/master/libraries/cute/cute_c2.h">cute_c2.h</a>, a small single-file C library. It covers circles, capsules, polygons, aabbs, rays, convex hull, shape expansion, closest point pairs, and time of impact (swept) collision detection.</p>]]></content><author><name></name></author><category term="math" /><summary type="html"><![CDATA[Do you want to make a game but don’t know any math? Do you want to skip endless hours of reading arcane math texts and go straight to the useful stuff? Good! Me too. Let’s just skip straight ahead to the useful stuff. Sit back, grab yourself a lunchable, and get ready to become a wizard.]]></summary></entry><entry><title type="html">Datastructure APIs in C++</title><link href="https://randygaul.github.io/algorithm/architecture/data-structures/2020/02/01/Datastructure-APIs-in-C++.html" rel="alternate" type="text/html" title="Datastructure APIs in C++" /><published>2020-02-01T22:28:52+00:00</published><updated>2020-02-01T22:28:52+00:00</updated><id>https://randygaul.github.io/algorithm/architecture/data-structures/2020/02/01/Datastructure-APIs-in-C++</id><content type="html" xml:base="https://randygaul.github.io/algorithm/architecture/data-structures/2020/02/01/Datastructure-APIs-in-C++.html"><![CDATA[<p>Designing a great data structure API is mostly a grey area with lots of room for opinions. Why care about my opinion? Well, take a peek at <a href="https://github.com/RandyGaul/cute_headers">some of my headers on GitHub</a>. If you think they might look useful or interesting upon first glance, then read on, as all those headers were written with the ideas here in mind. Here are my major priorities for a data structure API to tackle, listed with the most important first.</p>

<ol>
  <li>Anticipate common fundamental use-cases and minimize friction for these cases.</li>
  <li>Expose as little as possible to the user.</li>
  <li>Incur as little overhead as possible.</li>
</ol>

<p>Note I placed “overhead” as third, not first! In this case overhead means a few things.</p>

<ul>
  <li>Run-time overhead</li>
  <li>Compile-time overhead</li>
  <li>Abstraction cost</li>
</ul>

<p>We all know what run-time overhead is, it’s the cost of running the code, as in how slow or fast it is.</p>

<p>Compile-time overhead is usually overlooked by C++ developers. It’s completely possible to time compilation and run performance analysis, especially over a long period of time as a project matures. It’s also possible with MSVC to <a href="https://aras-p.info/blog/2017/10/23/Best-unknown-MSVC-flag-d2cgsummary/">diagnose specifically what is incurring long compile times</a>. There’s really no excuse for having awful compilation times, even in really large projects with millions of lines of code. The key is to minimize inter-dependencies between different sections of code, in order to minimize the following equation (just an approximation, but a good approximation).</p>

<p>compile + link time = number of <a href="https://en.wikipedia.org/wiki/Translation_unit_(programming)">translation units</a> * amount of code to process</p>

<p>The actual solution to slow compiling/link times is to put as little code as possible into each translation unit as possible. This means some real thought and planning has to go into each included file. All other strategies, such as inredibuild, precompiled headers, or unity builds are merely band-aids that can be applied to codebases that grow large without a strong underlying architecture. In other words, these alternative strategies can be the cheapest and only option for old codebases, but, with some skill and foresight these problems can simply be avoided in the first place.</p>

<p>Abstraction overhead is not often talked about, and is also not really a quantifiable metric, making it up a candidate for perpetual debate and mysticism. Put as simply as I can, the cost of abstraction for a particular piece of code is how difficult it is to read and understand, especially at-a-glance. The general pattern for any code base is to start out lean and mean. Over time more people are hired to work on the code base, and more code is added. As more code gets added it becomes more and more difficult understand how everything fits together, and abstractions are used ubiquitously as a compromise. Each time an abstraction is added the difficulty in mustering a competent grok of the project becomes greater and greater, and thus nobody has the ability to reason about compile-time overhead any longer. At this point the ship is sinking, and nothing can save it. Large old projects eventually get scrapped in favor of starting over.</p>

<p>Here is a quick list of some things I think incur the most abstraction cost in C++.</p>

<ul>
  <li>Exceptions</li>
  <li>Constructors/destructors</li>
  <li>Move semantics</li>
  <li>Smart pointers (yes, including unique_ptr)</li>
  <li>RAII in general</li>
  <li>Traditional usage of the class keyword (putting too much code into the header)</li>
  <li>Lambdas</li>
  <li>Templates</li>
  <li>constexpr</li>
  <li>Iterators</li>
</ul>

<p>This is my own personal list of costly abstractions. In my experience the code that everyone appreciates the most (in the general sense) is code that solves hard problems without any of the above features. My reasoning is that these features are much more complicated than the potential benefits they might bring to the table, so code that simply omits these features is more likely to produce a more favorable benefit to complexity ratio. Avoid all of these features, especially in you headers and data structure APIs. Your compile times will survive long enough to thank you, and your users will thank you for not <a href="https://web.archive.org/web/20200408025742/https://en.wikipedia.org/wiki/Overengineering">over-engineering</a> your API into oblivion.</p>

<p>A data structure API can minimize all three types of overhead. The first thing is to only templatize the tiniest amount of code as necessary. The next thing is to have as little code in headers as possible. These two steps will encourage people to include your header, since it won’t really affect compile times in a relevant way. The last thing is to reduce your own compile times in the implementation file by simply not including anything unless absolutely necessary.</p>

<p>Take a hash table as an example. First, implement the header with a C API, preferably using the PIMPL idiom or something similar. If done intelligently this C API can be exposed through DLLs trivially, and also exhibit resiliency in terms of <a href="https://web.archive.org/web/20200408025742/https://en.wikipedia.org/wiki/Application_binary_interface">ABI stability</a>. Here is my personal hash table API as an example.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">hashtable_slot_t</span>
<span class="p">{</span>
    <span class="kt">uint64_t</span> <span class="n">key_hash</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">item_index</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">base_count</span><span class="p">;</span>
<span class="p">};</span>
 
<span class="k">struct</span> <span class="nc">hashtable_t</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">count</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">slot_capacity</span><span class="p">;</span>
    <span class="n">hashtable_slot_t</span><span class="o">*</span> <span class="n">slots</span><span class="p">;</span>
 
    <span class="kt">int</span> <span class="n">key_size</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">item_size</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">item_capacity</span><span class="p">;</span>
    <span class="kt">void</span><span class="o">*</span> <span class="n">items_key</span><span class="p">;</span>
    <span class="kt">int</span><span class="o">*</span> <span class="n">items_slot_index</span><span class="p">;</span>
    <span class="kt">void</span><span class="o">*</span> <span class="n">items_data</span><span class="p">;</span>
 
    <span class="kt">void</span><span class="o">*</span> <span class="n">temp_key</span><span class="p">;</span>
    <span class="kt">void</span><span class="o">*</span> <span class="n">temp_item</span><span class="p">;</span>
    <span class="kt">void</span><span class="o">*</span> <span class="n">mem_ctx</span><span class="p">;</span>
<span class="p">};</span>
 
<span class="k">extern</span> <span class="n">CUTE_API</span> <span class="kt">int</span> <span class="n">CUTE_CALL</span> <span class="n">hashtable_init</span><span class="p">(</span><span class="n">hashtable_t</span><span class="o">*</span> <span class="n">table</span><span class="p">,</span> <span class="kt">int</span> <span class="n">key_size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">item_size</span><span class="p">,</span> <span class="kt">int</span> <span class="n">capacity</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span> <span class="n">mem_ctx</span><span class="p">);</span>
<span class="k">extern</span> <span class="n">CUTE_API</span> <span class="kt">void</span> <span class="n">CUTE_CALL</span> <span class="n">hashtable_cleanup</span><span class="p">(</span><span class="n">hashtable_t</span><span class="o">*</span> <span class="n">table</span><span class="p">);</span>
 
<span class="k">extern</span> <span class="n">CUTE_API</span> <span class="kt">void</span><span class="o">*</span> <span class="n">CUTE_CALL</span> <span class="n">hashtable_insert</span><span class="p">(</span><span class="n">hashtable_t</span><span class="o">*</span> <span class="n">table</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">key</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">item</span><span class="p">);</span>
<span class="k">extern</span> <span class="n">CUTE_API</span> <span class="kt">void</span> <span class="n">CUTE_CALL</span> <span class="n">hashtable_remove</span><span class="p">(</span><span class="n">hashtable_t</span><span class="o">*</span> <span class="n">table</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">key</span><span class="p">);</span>
<span class="k">extern</span> <span class="n">CUTE_API</span> <span class="kt">void</span> <span class="n">CUTE_CALL</span> <span class="n">hashtable_clear</span><span class="p">(</span><span class="n">hashtable_t</span><span class="o">*</span> <span class="n">table</span><span class="p">);</span>
<span class="k">extern</span> <span class="n">CUTE_API</span> <span class="kt">void</span><span class="o">*</span> <span class="n">CUTE_CALL</span> <span class="n">hashtable_find</span><span class="p">(</span><span class="k">const</span> <span class="n">hashtable_t</span><span class="o">*</span> <span class="n">table</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">key</span><span class="p">);</span>
<span class="k">extern</span> <span class="n">CUTE_API</span> <span class="kt">int</span> <span class="n">CUTE_CALL</span> <span class="n">hashtable_count</span><span class="p">(</span><span class="k">const</span> <span class="n">hashtable_t</span><span class="o">*</span> <span class="n">table</span><span class="p">);</span>
<span class="k">extern</span> <span class="n">CUTE_API</span> <span class="kt">void</span><span class="o">*</span> <span class="n">CUTE_CALL</span> <span class="n">hashtable_items</span><span class="p">(</span><span class="k">const</span> <span class="n">hashtable_t</span><span class="o">*</span> <span class="n">table</span><span class="p">);</span>
<span class="k">extern</span> <span class="n">CUTE_API</span> <span class="kt">void</span><span class="o">*</span> <span class="n">CUTE_CALL</span> <span class="n">hashtable_keys</span><span class="p">(</span><span class="k">const</span> <span class="n">hashtable_t</span><span class="o">*</span> <span class="n">table</span><span class="p">);</span>
<span class="k">extern</span> <span class="n">CUTE_API</span> <span class="kt">void</span> <span class="n">CUTE_CALL</span> <span class="n">hashtable_swap</span><span class="p">(</span><span class="n">hashtable_t</span><span class="o">*</span> <span class="n">table</span><span class="p">,</span> <span class="kt">int</span> <span class="n">index_a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">index_b</span><span class="p">);</span></code></pre></figure>

<p>It requires stdint.h, a couple of defines, and that’s it. Including this into a translation unit should not increase compile times in a relevant way.</p>

<p>The next step is to add as small of a templated wrapper as possible. Here’s an example API I came up with.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="nc">K</span><span class="p">,</span> <span class="k">typename</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="k">struct</span> <span class="nc">dictionary</span>
<span class="p">{</span>
	<span class="n">dictionary</span><span class="p">();</span>
	<span class="n">dictionary</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">user_allocator_context</span><span class="p">);</span>
	<span class="n">dictionary</span><span class="p">(</span><span class="kt">int</span> <span class="n">capacity</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span> <span class="n">user_allocator_context</span><span class="p">);</span>
	<span class="o">~</span><span class="n">dictionary</span><span class="p">();</span>

	<span class="n">T</span><span class="o">*</span> <span class="n">find</span><span class="p">(</span><span class="k">const</span> <span class="n">K</span><span class="o">&amp;</span> <span class="n">key</span><span class="p">);</span>
	<span class="k">const</span> <span class="n">T</span><span class="o">*</span> <span class="n">find</span><span class="p">(</span><span class="k">const</span> <span class="n">K</span><span class="o">&amp;</span> <span class="n">key</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
	<span class="n">error_t</span> <span class="n">find</span><span class="p">(</span><span class="k">const</span> <span class="n">K</span><span class="o">&amp;</span> <span class="n">key</span><span class="p">,</span> <span class="n">T</span><span class="o">*</span> <span class="n">val_out</span><span class="p">);</span>
	<span class="n">error_t</span> <span class="n">find</span><span class="p">(</span><span class="k">const</span> <span class="n">K</span><span class="o">&amp;</span> <span class="n">key</span><span class="p">,</span> <span class="n">T</span><span class="o">*</span> <span class="n">val_out</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>

	<span class="n">T</span><span class="o">*</span> <span class="n">insert</span><span class="p">(</span><span class="k">const</span> <span class="n">K</span><span class="o">&amp;</span> <span class="n">key</span><span class="p">);</span>
	<span class="n">T</span><span class="o">*</span> <span class="n">insert</span><span class="p">(</span><span class="k">const</span> <span class="n">K</span><span class="o">&amp;</span> <span class="n">key</span><span class="p">,</span> <span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">val</span><span class="p">);</span>
	<span class="kt">void</span> <span class="n">remove</span><span class="p">(</span><span class="k">const</span> <span class="n">K</span><span class="o">&amp;</span> <span class="n">key</span><span class="p">);</span>

	<span class="kt">void</span> <span class="n">clear</span><span class="p">();</span>

	<span class="kt">int</span> <span class="n">count</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
	<span class="n">T</span><span class="o">*</span> <span class="n">items</span><span class="p">();</span>
	<span class="k">const</span> <span class="n">T</span><span class="o">*</span> <span class="n">items</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
	<span class="n">K</span><span class="o">*</span> <span class="n">keys</span><span class="p">();</span>
	<span class="k">const</span> <span class="n">K</span><span class="o">*</span> <span class="n">keys</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>

	<span class="kt">void</span> <span class="n">swap</span><span class="p">(</span><span class="kt">int</span> <span class="n">index_a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">index_b</span><span class="p">);</span>

<span class="nl">private:</span>
	<span class="n">hashtable_t</span> <span class="n">table</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<p>The major observation is this templated wrapper calls into the C api. Each function is just one or a few lines each, and requires no other additional headers or dependencies of any kind. The templates are here merely to provide types over the void pointers. Personally, I like to think of the dictionary as an <a href="https://web.archive.org/web/20200408025742/https://en.wikipedia.org/wiki/Abstract_data_type">abstract data type</a>, as opposed to a “class”. Class in C++ is a really loaded term. I actually use the keyword struct just to try and avoid all the pre-loaded context or baggage that class brings with it, which is sort of silly of me, but whatever :)</p>

<p>Notice how there are no iterators. Iterators are awful for a variety of reasons, but one major reason iterators are horrible is the overhead they incur to compile times when templated. They generate large amounts of code in every single translation unit they touch, and encourage people to write “generic” iterators and “generic” algorithms that operate on iterators. This all leads to slower and slower compile times.</p>

<p>If I compare my own templated dictionary to unordered_map things start to come into perspective. My own dictionary includes stdint.h, and contains about 200 lines of code. unordered_map in VS2017 has 1k lines of code, but also includes tuple and xhash. Delving into those headers reveals cstring, cwchar, list, vector, new, type_traits, xutility, and it keeps going and going and going. I stopped estimating once I hit 20k lines of code. It’s possible to run a test example and look at the preprocessed output, but I digress, and think my point is already proven.</p>]]></content><author><name></name></author><category term="algorithm" /><category term="architecture" /><category term="data-structures" /><summary type="html"><![CDATA[Designing a great data structure API is mostly a grey area with lots of room for opinions. Why care about my opinion? Well, take a peek at some of my headers on GitHub. If you think they might look useful or interesting upon first glance, then read on, as all those headers were written with the ideas here in mind. Here are my major priorities for a data structure API to tackle, listed with the most important first.]]></summary></entry><entry><title type="html">Collision Detection in 2D or 3D – Some Steps for Success</title><link href="https://randygaul.github.io/collision-detection/2019/06/19/Collision-Detection-in-2D-Some-Steps-for-Success.html" rel="alternate" type="text/html" title="Collision Detection in 2D or 3D – Some Steps for Success" /><published>2019-06-19T00:00:00+00:00</published><updated>2019-06-19T00:00:00+00:00</updated><id>https://randygaul.github.io/collision-detection/2019/06/19/Collision-Detection-in-2D-Some-Steps-for-Success</id><content type="html" xml:base="https://randygaul.github.io/collision-detection/2019/06/19/Collision-Detection-in-2D-Some-Steps-for-Success.html"><![CDATA[<p>These are my personal opinions about recommended readings for collision detection in either 2D or 3D. This post is intended to act as a jumpstart in order to avoid endless swaths of outdated, poorly written, or otherwise incorrect information.</p>

<p>Some steps for success when writing your own collision detection.</p>

<ol>
  <li>Use the best resources. Collision detection success comes mostly from selecting the best and most well-known algorithms. A lot of articles and online resources give bad advice in the algorithms they pick, or obfuscate good algorithms with poor explanations. Go to <a href="https://box2d.org/publications/">box2d.org</a> and look at Dirk Gregorius’s talks on the Separating Axis Test (2013) and Contact Creation (2015).</li>
  <li>Collision detection is complicated, and the only way to keep it simple is to stick with very strict limitations, such as only AABBs. The moment rotations are added in even <a href="https://www.randygaul.net/2014/05/22/deriving-obb-to-obb-intersection-sat/">OBB to OBB collision detection</a> spikes in terms of complexity.</li>
  <li>Look at <a href="https://github.com/erincatto/box2d-lite">Box2D Lite</a> (not the full Box2D library, just the old 2006 demo) for a small C++ example for 2D OBBs. This is a good start before doing a 3D port.</li>
  <li>GJK is a great algorithm to compute the closest points between two shapes, or to detect collision between two shapes. However, I personally recommend to <em>not</em> use EPA. Dirk’s 2015 lecture goes into some detail on specifically why EPA might be avoided. Please use <a href="https://box2d.org/publications/">Erin’s lecture from 2010</a> to learn about GJK. He has great sample code that is readily portable to 3D. GJK is best used as a work-horse to implement higher level algorithms, like time of impact functions or Separating Axis Test functions.</li>
  <li>Christer Ericson’s orange book <a href="https://www.amazon.com/Real-Time-Collision-Detection-Interactive-Technology/dp/1558607323">Real-Time Collision Detection</a> is a great resource. It has fairly good example code, however it does contain a few small errors. Christer himself states the example code is not intended to be production ready. However, in practice most game studios I known of simply copy + paste his example code into production and then ship it, and it usually works quite well. A good book for beginners and professionals alike. The only real downside to this book is it doesn’t cover much beyond boolean collision detection, which is what Dirk’s resources are for.</li>
</ol>

<p>I know it’s very tempting to search a bunch of different articles to try and find the resources that are the easiest to understand. However, other resources are going to more or less lead you into pitfalls. How do I know this? I’ve probably read any resource you might find online. I like collision detection and actively search and read things about the topic for fun. I’m sure there are some articles out there I haven’t read and would add to the recommended reading list, but the chances are quite low.</p>

<p>Just to be a little more convincing I will go ahead and list out some popular articles you will find if you go against my recommendation and start randomly searching online. Here are some resources I personally recommend <em>not</em> reading, with some short justifications on why they might be avoided.</p>

<ol>
  <li>wildbunny articles – The wildbunny articles mostly share outdated techniques, and are largely behind a pay wall. Not recommended as reading or as a purchase.</li>
  <li>Game Physics by Ian Millington – This book is an ok resource for collision detection, but uses outdated techniques for collision resolution, and the example code itself uses poor software engineering practice, and the sample code in general is obfuscated. Not recommended as reading or as a purchase.</li>
  <li><a href="https://www.geometrictools.com/">David Eberly’s site and books</a> – David’s resources are quite robust and correct. In all cases where I’ve used his code it has both worked correctly and was very informative. However, David’s resources are very in-depth, often in ways that aren’t actually very relevant to whatever it is you specifically want to do at any given time. I recommend using David’s resources as a reference after some expertise have been built independently. His stuff is not helpful for beginners, and his example code is unnecessarily complicated in most cases, handling generality even when generality is likely unneeded.</li>
  <li><a href="https://www.metanetsoftware.com/technique/tutorialA.html">Metanet N Tutorial</a> – The N tutorial is actually an ok resource in terms of using a good algorithm without obfuscating it. It’s an ok introduction for 2D stuff, but is really inferior compared to the resources I linked above in my personal opinion, but maybe you’ll find it a good resource.</li>
  <li><a href="http://www.dyn4j.org/2010/05/epa-expanding-polytope-algorithm/">dynj4 GJK/EPA</a> – This post actually contains pretty good information, and is a good way to learn about EPA in the 2D case. However, since I recommended not using EPA; In 3D EPA is expensive, very difficult to implement robustly, and usually requires an “incremental manifold” leading to artifacts during simulation.</li>
  <li><a href="https://www.youtube.com/watch?v=Qupqu1xe7Io">Casey Muratori’s video on GJK</a> – This video, although quite interesting, is not a great learning resource compared to Erin’s GJK slides from 2010. Also the underlying strategy Casey is advocating doesn’t actually work in practice. Go ahead and try skipping Voronoi regions in your code, run some basic tests, and it can be easily shown that Voronoi regions which might be logically skippable are not skippable in practice. My conclusion was that due to numeric approximation it is absolutely necessary to retest previously visited Voronoi regions. My best guess is Casey was not using GJK for physics simulation at the time, so he simply didn’t notice any problems (for example, if he was doing occlusion culling with the view frustum).</li>
  <li><a href="https://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-basics-and-impulse-resolution--gamedev-6331">My old tuts+ articles</a> – This stuff is mostly just a rehash of things Erin and Dirk documented in their GDC talks. It can be ok for beginners and some 2D games, but is quite inferior compared to the recommended resources.</li>
</ol>

<p>Stick to the top resources. If you’re confused when reading the top resources, that means you have valuable questions to ask and are not understanding something fundamentally important. Instead of searching around online through an endless sea of misinformation and poor articles, go to a forum like Gamedev.net and ask questions about the information in my list of recommended resources.</p>]]></content><author><name></name></author><category term="collision-detection" /><summary type="html"><![CDATA[These are my personal opinions about recommended readings for collision detection in either 2D or 3D. This post is intended to act as a jumpstart in order to avoid endless swaths of outdated, poorly written, or otherwise incorrect information.]]></summary></entry><entry><title type="html">Base64 Encoding in C</title><link href="https://randygaul.github.io/algorithm/compression/serialization/api-design/2019/05/01/Base64-Encoding.html" rel="alternate" type="text/html" title="Base64 Encoding in C" /><published>2019-05-01T00:00:00+00:00</published><updated>2019-05-01T00:00:00+00:00</updated><id>https://randygaul.github.io/algorithm/compression/serialization/api-design/2019/05/01/Base64-Encoding</id><content type="html" xml:base="https://randygaul.github.io/algorithm/compression/serialization/api-design/2019/05/01/Base64-Encoding.html"><![CDATA[<p>Base64 encoding has this nice feature where the encoded information is safely copy-pasteable and stored as plaintext in files. It uses numbers represented in Base64 with a limited character set. Here’s the table from <a href="https://www.ietf.org/rfc/rfc4648.txt">RFC 4648</a>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>                      Table 1: The Base 64 Alphabet

     Value Encoding  Value Encoding  Value Encoding  Value Encoding
         0 A            17 R            34 i            51 z
         1 B            18 S            35 j            52 0
         2 C            19 T            36 k            53 1
         3 D            20 U            37 l            54 2
         4 E            21 V            38 m            55 3
         5 F            22 W            39 n            56 4
         6 G            23 X            40 o            57 5
         7 H            24 Y            41 p            58 6
         8 I            25 Z            42 q            59 7
         9 J            26 a            43 r            60 8
        10 K            27 b            44 s            61 9
        11 L            28 c            45 t            62 +
        12 M            29 d            46 u            63 /
        13 N            30 e            47 v
        14 O            31 f            48 w         (pad) =
        15 P            32 g            49 x
        16 Q            33 h            50 y
</code></pre></div></div>

<p>We can see all numbers from 0-63 are mapped to characters. To encode binary data into Base64 we simply loop over our data in 7-bit chunks and output the correct character. To decode we can build a table of characters that maps to the correct 7-bit binary data. Encoding and decoding should be one for loop and a table lookup, along with some bit manipulation to pack/unpack 7 bits at a time.</p>

<p>It can be fairly difficult to find a good, copy-pastableable, Base64 encoding implementation in C. After some searching around and mandatory hair-pulling I made one. It’s since been absorbed into Cute Framework and available for anyone to use. The code is under zlib license so feel free to use it basically however you want. It’s just two functions, one for encode and one for decode. They look a lot like <code class="language-plaintext highlighter-rouge">memcpy</code>. Here’s my recommended API if you want to grab the code from Cute Framework or write your own from scratch:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">cf_error_t</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">code</span><span class="p">;</span>
    <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">details</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">cf_error_t</span> <span class="n">cf_base64_encode</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">dst</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">dst_size</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">src</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">src_size</span><span class="p">);</span>
<span class="n">cf_error_t</span> <span class="n">cf_base64_decode</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">dst</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">dst_size</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="n">src</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">src_size</span><span class="p">);</span></code></pre></figure>

<p>Cute Framework reference files:</p>

<ul>
  <li><a href="https://github.com/RandyGaul/cute_framework/blob/master/include/cute_base64.h">Base64 Header File</a></li>
  <li><a href="https://github.com/RandyGaul/cute_framework/blob/master/src/cute_base64.cpp">Base64 CPP File</a></li>
</ul>

<p>A quick note about optimization and SIMD – The encode/decode functions are great candidates for further optimizations. You could use <a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">SIMD instructions</a> to increase performance by 2-3x quite easily. Another way would be to re-shuffle around the order of operations to improve <a href="https://en.wikipedia.org/wiki/Instruction-level_parallelism">instruction level parallelism</a>. These could be great ways to practice optimization, though personally I prefer to keep the code as-is for maximizing simplicity and portability. For games Base64 encoding is probably an infrequent operation and will be unlikely to ever show up in a profiler as a hot-path.</p>]]></content><author><name></name></author><category term="algorithm" /><category term="compression" /><category term="serialization" /><category term="api-design" /><summary type="html"><![CDATA[Base64 encoding has this nice feature where the encoded information is safely copy-pasteable and stored as plaintext in files. It uses numbers represented in Base64 with a limited character set. Here’s the table from RFC 4648.]]></summary></entry><entry><title type="html">Error Codes and Error Handling</title><link href="https://randygaul.github.io/api-design/2019/04/26/Error-Codes-and-Error-Handling.html" rel="alternate" type="text/html" title="Error Codes and Error Handling" /><published>2019-04-26T22:28:52+00:00</published><updated>2019-04-26T22:28:52+00:00</updated><id>https://randygaul.github.io/api-design/2019/04/26/Error-Codes-and-Error-Handling</id><content type="html" xml:base="https://randygaul.github.io/api-design/2019/04/26/Error-Codes-and-Error-Handling.html"><![CDATA[<p>There is a longstanding and ongoing debate in the industry on whether exceptions or error codes are superior when it comes to handling and report errors. I will share my opinion.</p>

<p>Error codes are better.</p>

<p>Here are some reasons to bias against exceptions.</p>

<ul>
  <li>They destroy code flow.</li>
  <li>Users end up try-catching exceptions everywhere, and it devolves to more or less error codes.</li>
  <li>Handling an error in a centralized location is rarely useful, which is often the motivation for exceptions.</li>
</ul>

<p>The simplest way to implement error codes is to return an integer value representing success or failure. Sometimes this integer gets upgraded to an enumeration for a little more descriptive flavor. Sometimes the codes or the enumeration are mapped to “details”. The details are the human readable description of a specific error. Sometimes the details live on a webpage, and sometimes they live in a big switch statement somewhere in the code.</p>

<p>After talking with a friend, they suggested creating an error struct containing both an error code along with a details string. Here’s an example of what I came up with.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#define ERROR_CODE_FAILURE -1
#define ERROR_CODE_SUCCESS 0
</span>
<span class="k">struct</span> <span class="nc">error_t</span>
<span class="p">{</span>
	<span class="kt">int</span> <span class="n">code</span><span class="p">;</span>
	<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">details</span><span class="p">;</span>

	<span class="kr">inline</span> <span class="kt">int</span> <span class="n">is_error</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">code</span> <span class="o">==</span> <span class="n">ERROR_CODE_FAILURE</span><span class="p">;</span> <span class="p">}</span>
<span class="p">};</span>

<span class="kr">inline</span> <span class="n">error_t</span> <span class="n">error_make</span><span class="p">(</span><span class="kt">int</span> <span class="n">code</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">details</span><span class="p">)</span> <span class="p">{</span> <span class="n">error_t</span> <span class="n">error</span><span class="p">;</span> <span class="n">error</span><span class="p">.</span><span class="n">code</span> <span class="o">=</span> <span class="n">code</span><span class="p">;</span> <span class="n">error</span><span class="p">.</span><span class="n">details</span> <span class="o">=</span> <span class="n">details</span><span class="p">;</span> <span class="k">return</span> <span class="n">error</span><span class="p">;</span> <span class="p">}</span>
<span class="kr">inline</span> <span class="n">error_t</span> <span class="n">error_failure</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">details</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">error_make</span><span class="p">(</span><span class="n">ERROR_CODE_FAILURE</span><span class="p">,</span> <span class="n">details</span><span class="p">);</span> <span class="p">}</span>
<span class="kr">inline</span> <span class="n">error_t</span> <span class="n">error_success</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">error_make</span><span class="p">(</span><span class="n">ERROR_CODE_SUCCESS</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span> <span class="p">}</span></code></pre></figure>

<p>Functions can now return an <code class="language-plaintext highlighter-rouge">error_t</code> struct by value whenever reporting errors. Users can choose to respond or ignore to codes as they see fit. There is no need for thread local storage, exceptions, or any other fancy features. The strings themselves should be stored as a string literal, and I would recommend <em>not</em> localizing them for simplicity’s sake.</p>

<p>User code now will look mostly like this excerpt.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">error_t</span> <span class="n">err</span> <span class="o">=</span> <span class="n">do_something</span><span class="p">(</span><span class="n">params</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">err</span><span class="p">.</span><span class="n">is_error</span><span class="p">())</span> <span class="p">{</span>
	<span class="n">handle_error</span><span class="p">(</span><span class="n">err</span><span class="p">.</span><span class="n">details</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>Once error codes like this are setup any kind of long jump logic can be added as a separate feature, but the basic error codes themselves do not need complicated jump functionality built-in.</p>]]></content><author><name></name></author><category term="api-design" /><summary type="html"><![CDATA[There is a longstanding and ongoing debate in the industry on whether exceptions or error codes are superior when it comes to handling and report errors. I will share my opinion.]]></summary></entry><entry><title type="html">Hash Tables, Sorting, and Security</title><link href="https://randygaul.github.io/data-structures/api-design/hash/2019/04/08/Hashtables-Sorting-and-Security.html" rel="alternate" type="text/html" title="Hash Tables, Sorting, and Security" /><published>2019-04-08T22:28:52+00:00</published><updated>2019-04-08T22:28:52+00:00</updated><id>https://randygaul.github.io/data-structures/api-design/hash/2019/04/08/Hashtables-Sorting-and-Security</id><content type="html" xml:base="https://randygaul.github.io/data-structures/api-design/hash/2019/04/08/Hashtables-Sorting-and-Security.html"><![CDATA[<p>I’d like to recommend Mattias Gustavsson’s hash table he has <a href="https://github.com/mattiasgustavsson/libs">open sourced on github</a>. The implementation stores a few arrays, the most interesting one is a layer of indirection between mapping hashes to key/value entries.</p>

<p>Each key/value pair is stored in their own contiguous array of keys, or values, at matching indices. This means the table as an API that allows users to loop over key/value pairs with a trivial for loop:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">key_t</span><span class="o">*</span> <span class="n">keys</span> <span class="o">=</span> <span class="p">(</span><span class="n">key_t</span><span class="o">*</span><span class="p">)</span><span class="n">get_keys</span><span class="p">(</span><span class="n">table</span><span class="p">);</span>
<span class="n">value_t</span><span class="o">*</span> <span class="n">values</span> <span class="o">=</span> <span class="p">(</span><span class="n">value_t</span><span class="o">*</span><span class="p">)</span><span class="n">get_values</span><span class="p">(</span><span class="n">table</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="n">get_count</span><span class="p">(</span><span class="n">table</span><span class="p">);</span>

<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">count</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">key_t</span><span class="o">*</span> <span class="n">key</span> <span class="o">=</span> <span class="n">keys</span> <span class="o">+</span> <span class="n">i</span><span class="p">;</span>
	<span class="n">value_t</span><span class="o">*</span> <span class="n">value</span> <span class="o">=</span> <span class="n">values</span> <span class="o">+</span> <span class="n">i</span><span class="p">;</span>
	<span class="n">do_things</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>This opens up some possibilities.</p>

<p>The table entries can be processed with a tight for loop, without running into “empty entries” which can cause branch mis-prediction performance hits.
Key/value pairs can be deleted from the table and remapped internally in a trivial manner, while looping over elements contiguously.
Key/value pairs can be swapped trivially, so the ordering of the keys and values arrays can be sorted. For example, quicksort can trivially sort key/value pairs using a comparison predicate and the swap function of the table.</p>

<p>Suddenly the hash table now serves many interested purposes. Without additional memory the table can act as a priority queue, a sorted array, or other similar data structures. This utility comes at the cost of an extra layer of indirection: the key value pairs can be moved around, because the table is storing a separate array of data that tracks the index of a particular key/value pair. This means that if the hash table itself is “cold” (none of the data is in a memory cache) twice the number of cache misses can occur. However, if the table is hot, little to no performance hit will be seen in the common case.</p>

<p>Additionally, performance gains when iterating key/value pairs will “win-back” any loss from the extra layer of indirection.</p>

<hr />

<p>Let us cover secure hash tables. If a hash table is used to cache or map data coming in from the network (or any other insecure data), if the attacker can learn or guess what kind of table and hash function is in use, they can craft input to try to degenerate table lookups to a time complexity of O(N) linear time. This is a type of DoS attack. Not too long ago this attack was popularized on applications using popular hash functions such as murmurhash3.</p>

<p><a href="https://libsodium.gitbook.io/doc/hashing/short-input_hashing">libsodium</a> has some functions made specifically for hash tables, where the hash function takes a secret seed. This lets the table mitigate DoS effectiveness on the table itself. The webpage recommends ensuring table sizes are a prime number in order to ensure all bits of the hash function are utilized. In my own code I have modified Mattias’s table to use the libsodium function in the above link, in order to mitigate this style of DoS attack.</p>

<p>This is not necessary for the common use-case, where the code’s internal hash function is very fast, and preferable when data is known to not be malicious.</p>

<hr />

<p>Finally, I have made some small modifications to Mattias’s table to allow arbitrarily sized keys. This modification is quite trivial, and simply changes keys from uint64_t to void* + key_size, where the key_size is constant for the table’s lifetime.</p>

<p>My use case here was to map incoming IP addresses and ports to some encryption state, to efficiently implement a connection handshake process for a protocol I am working on. In this case a 64-bit key is not large enough to store a 16 bit port, and a potentially 18 byte IPv6 address.</p>]]></content><author><name></name></author><category term="data-structures" /><category term="api-design" /><category term="hash" /><summary type="html"><![CDATA[I’d like to recommend Mattias Gustavsson’s hash table he has open sourced on github. The implementation stores a few arrays, the most interesting one is a layer of indirection between mapping hashes to key/value entries.]]></summary></entry><entry><title type="html">Virtual File Systems in Games!</title><link href="https://randygaul.github.io/architecture/2019/03/20/Virtual-File-Systems-in-Games.html" rel="alternate" type="text/html" title="Virtual File Systems in Games!" /><published>2019-03-20T22:28:52+00:00</published><updated>2019-03-20T22:28:52+00:00</updated><id>https://randygaul.github.io/architecture/2019/03/20/Virtual-File-Systems-in-Games</id><content type="html" xml:base="https://randygaul.github.io/architecture/2019/03/20/Virtual-File-Systems-in-Games.html"><![CDATA[<p>After a particularly elucidating conversation with <a href="https://twitter.com/Mattias_G">Mattias Gustavsson on Twitter</a>, I came to the delightful realization that a well utilized virtual path system can be make writing games a lot more fun. This blog post describes some basic, but strong, benefits in favor of using a virtual file system, as opposed to using the OS’s native file system alone.</p>

<hr />

<h3 id="ranting-about-poor-virtual-file-systems">Ranting about (poor) Virtual File Systems</h3>

<p>If readers are at all like myself, they may have tinkered with some larger engines that utilized virtual file paths all over the place. Often at work I would have to use the debugger and enter into this kind of virtual file system to figure out where things are located on disk, or where they are supposed to be located on disk. Typically this was a huge hassle, since the systems I used at the time were: A) not documented at all; B) not understood by anyone currently at the company; and C) over-engineered with incredibly deep and superfluous callstacks.</p>

<p>My initial experience with these systems was quite horrible, so I was very biased against them for a number of years. However, if used and written properly, some important benefits can come about from virtual file systems.</p>

<h3 id="what-is-a-virtual-file-system">What is a Virtual File System?</h3>

<p>Typically the kind of virtual file system I have encountered somehow translate actual file paths on disk to a virtualized file path of some kind. Usually the system will truncate off the disk drive letters on Windows, and pretend the root of paths is located at some directory. Here is an example:</p>

<p>Say your game’s executable is located at C:/Program Files/Game/game.exe, and needs to open two other folders:</p>

<ol>
  <li>C:/Program Files/Game/data</li>
  <li>C:/Users/Bob/Game/save_files</li>
</ol>

<p>The first folder is where all game assets are stored on disk, like the art, animations, music, etc. The second folder is where the game writes out player save information, like their character or level save states.</p>

<p>Hard-coding these paths will not work if the game needs to run on platforms other than Windows. One nice way to gracefully handle multiple platforms is to use a virtual file system that can mount folders under an alias. Look at this code example:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="c1">// vfs - Virtual File System</span>
<span class="c1">// A hypothetical library implementing useful file-related features.</span>
<span class="cp">#include</span> <span class="cpf">&lt;vfs.h&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">vfs_t</span><span class="o">*</span> <span class="n">vfs</span> <span class="o">=</span> <span class="n">vfs_create</span><span class="p">();</span>

	<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">dir_on_disk</span> <span class="o">=</span> <span class="s">"./data"</span><span class="p">;</span>
	<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">new_alias</span> <span class="o">=</span> <span class="s">"/data"</span><span class="p">;</span>
	<span class="n">vfs_mount</span><span class="p">(</span><span class="n">vfs</span><span class="p">,</span> <span class="s">"."</span><span class="p">,</span> <span class="n">new_alias</span><span class="p">);</span>

	<span class="kt">void</span><span class="o">*</span> <span class="n">data</span><span class="p">;</span>
	<span class="kt">int</span> <span class="n">size</span><span class="p">;</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">vfs_read_file_to_memory</span><span class="p">(</span><span class="n">vfs</span><span class="p">,</span> <span class="s">"/data/boat.png"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">data</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">size</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">printf</span><span class="p">(</span><span class="s">"Unable to find boat file."</span><span class="p">);</span>
		<span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="c1">// On windows, for example, can be something like:</span>
	<span class="c1">// C:/Users/Bob/Game/saves</span>
	<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">virtual_save_folder</span> <span class="o">=</span> <span class="n">get_virtual_save_folder</span><span class="p">();</span>
	<span class="n">vfs_mount</span><span class="p">(</span><span class="n">vfs</span><span class="p">,</span> <span class="n">virtual_save_folder</span><span class="p">,</span> <span class="s">"/saves"</span><span class="p">);</span>

	<span class="c1">// Open up save.txt, which resides on disk at C:/Users/Bob/Game/saves/save.txt</span>
	<span class="n">vfs_file_t</span><span class="o">*</span> <span class="n">fp</span> <span class="o">=</span> <span class="n">vfs_open_file</span><span class="p">(</span><span class="n">vfs</span><span class="p">,</span> <span class="s">"/saves/save.txt"</span><span class="p">);</span>
	<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">fp</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">printf</span><span class="p">(</span><span class="s">"Unable to open save file."</span><span class="p">);</span>
		<span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="c1">// Now save the game!</span>
	<span class="n">save_the_game</span><span class="p">(</span><span class="n">vfs</span><span class="p">,</span> <span class="n">fp</span><span class="p">,</span> <span class="n">get_game_data</span><span class="p">());</span>
<span class="p">}</span></code></pre></figure>

<p>The nice benefit here is that now game code can focus on local directories without needing to know specifically where on the disk the local directory resides. This removes the underlying OS characteristics from the game as dependencies, in trade for the virtual file system dependency.</p>

<p>Assuming the virtual file system is well implemented and used properly (which is often not the case in practice!), the tradeoff can be really good.</p>

<h3 id="two-major-benefits">Two Major Benefits</h3>

<p>My #1 favorite benefit of mounting archives as virtual folders. My #2 favorite benefit is outlined by the above section: removing OS file-system characteristics from as much of the game as possible, in an attempt to make the game easier to port to multiple platforms.</p>

<p>I will focus on #1. The above section mounted actual directories under a virtual alias. It is also great if the virtual file system can mount archives under an alias, while still allowing file read operations as-per usual. This can grant the game the ability to read from archives or folders without requiring any changes to code whatsoever.</p>

<p>One huge benefit here is ease of distribution of the game. During development the majority of assets can sit on disk in separate files, making them easy to modify as needed. When ship time comes, the folder can be archived (example: zipped up as a .zip file), and the game will still run seamlessly.</p>

<p>Another benefit here is run-time efficiency. For example, on Windows opening a file is itself a heavy-weight operation. I am not exactly sure why this is the case, but my cursory research says it seems mostly slow due to security checks on file before opening (if any affluent readers could clarify, please post a comment or shoot me an email!). However, if many assets sit in a single archive, going through the initial “open the file handle” phase only has to happen once. This can be a giant time saver, just in terms of opening many individual files.</p>

<h3 id="extensions-patches-or-mods">Extensions, Patches, or Mods</h3>

<p>If the virtual file system can handle duplicate aliases, then some nice benefits pop out for adding on changes or extensions to game assets. A good example is applying patches to a game. One way to patch a game is to modify old archives on-disk, but another strategy is to simply add another archive entirely.</p>

<p>If another archive can be added to the game’s directory, but mounted under the same alias as the original archive, an interesting effect takes place. Say we have two archives, A and B. Say A is the original, and B applies some patch (it has updated contents for only a small section of A). If the game first mounts A, and then mounts B under the same alias, then we can think about the search-path of the virtual file system.</p>

<p>Say we try to read a file from the archive. The virtual file system will search through its internal virtual file path and report the first match it finds. If the path is constructed in a known order, it can be guaranteed that the patch archive B will be considered before the original archive A. No game code needs to change at all, and only a new archive needs to be added (assuming the game looks for patches to mount when booted up).</p>

<p>Once another patch gets rolled out, C, it can be mounted in front of A and B in the virtual path! And so on, and so forth. Adding in new archives can be a very easy way for customers to modify the art assets of your game to their liking, and also be a great way to apply small patches to your game.</p>

<p>Obviously large-scale and numerous patches would probably be best done by modifying the original archive… But for smaller and less frequent changes, dropping in a new archive file is very simple and cheap!</p>

<h3 id="other-benefits">Other Benefits</h3>

<p>I’m sure there are lots of other benefits that require a bit more in-depth knowledge than I have (for example, dealing with game-console oddities), so if anyone has any other ideas please do post them in the comments!</p>

<h3 id="some-recommended-virtual-file-systems">Some Recommended Virtual File Systems</h3>

<p>I have experience with two different virtual file systems, and can recommend them both.</p>

<ul>
  <li><a href="https://web.archive.org/web/20190320091637/https://github.com/mattiasgustavsson/libs">assetsys by Mattias Gustavsson</a></li>
  <li><a href="https://web.archive.org/web/20190320091637/https://icculus.org/physfs/">PhysicsFS by Icculus</a></li>
</ul>

<p>assetsys is the easier of the two to get up and running, but has less features than PhysicsFS. I would recommend trying assetsys if you’re looking for a single-file-header sort of drop-in solution, with a very small and focused API.</p>

<p>PhysicsFS is a more heavy-duty and serious solution that supports lots of platforms, and has a lot more features. This library will be a bit harder to integrate into pre-existing projects, but with cmake isn’t too bad to build from source.</p>

<p>Both libraries are very well written! I’ve used both in my personal code, and more recently am leaning towards PhysicsFS since it has a long history of very active development.</p>]]></content><author><name></name></author><category term="architecture" /><summary type="html"><![CDATA[After a particularly elucidating conversation with Mattias Gustavsson on Twitter, I came to the delightful realization that a well utilized virtual path system can be make writing games a lot more fun. This blog post describes some basic, but strong, benefits in favor of using a virtual file system, as opposed to using the OS’s native file system alone.]]></summary></entry></feed>