TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

The DDA Algorithm, explained interactively

108 点作者 ibobev大约 2 个月前

7 条评论

amjoshuamichael大约 2 个月前
Original author here. I&#x27;ve been reading this website for years. Imagine my shock when I saw my own article on the front page! I&#x27;m glad people are enjoying it.<p>Quick fact about the way the interactivity is done, all of the code for it is in this blogpost.js file: <a href="https:&#x2F;&#x2F;aaaa.sh&#x2F;creatures&#x2F;blogpost.js" rel="nofollow">https:&#x2F;&#x2F;aaaa.sh&#x2F;creatures&#x2F;blogpost.js</a>, which is only about 100 lines long. Each block has a list of scripts that it pulls from like so:<p>&lt;div class=&quot;code-example&quot; scripts=&quot;grid-sm 2d-vector-gfx-lib draw-grid full-algo-intro feather-canvas-edges&quot;&gt;&lt;&#x2F;div&gt;<p>and then there&#x27;s a set of script tags with those ids. I figured it was a nice solution!
评论 #43591925 未加载
评论 #43595576 未加载
评论 #43592294 未加载
评论 #43593812 未加载
a_e_k大约 2 个月前
Having implemented DDA code a bunch of times, I find it easiest to think about it in lazy functional terms: it&#x27;s like a takeWhile on a merge (or union) of infinite ordered streams of ray t-values.<p>In other words, decompose the problem into one of finding where the ray crosses the X grid lines and the Y grid lines, and the mental image is:<p><pre><code> +-------+-------+-------+ | | | | ------------------------- | | | ^ | | | | ^ | ^ | | | &#x2F; | | | | &#x2F; | &#x2F; | | | &#x2F; | | | | &#x2F; | &#x2F; +-------+-------+-*-----+ | | | &#x2F; | ------------------*------ | | |&#x2F; | | | |&#x2F; | &#x2F; | | * | | | * | &#x2F; | | &#x2F;| | | | &#x2F;| | &#x2F; +-------+-----*-+-------+ = | | &#x2F; | | U --------------*---------- | | &#x2F; | | | | &#x2F; | | &#x2F; | | &#x2F; | | | | &#x2F; | | &#x2F; | | &#x2F; | | | | &#x2F; | | &#x2F; +-------+-*-----+-------+ | | &#x2F; | | ----------*-------------- | |&#x2F; | | | |&#x2F; | | &#x2F; | * | | | * | | &#x2F; | o| | | | o| | | o +-------+-------+-------+ | | | | ------------------------- </code></pre> Now, if our ray has origin o, and direction d, the position of any point along the ray for a t-value is:<p><pre><code> x&#x27; = o.x + t * d.x y&#x27; = o.y + t * d.y. </code></pre> Where&#x27;s the first grid intersection in X? Assuming d.x is positive, it&#x27;ll be at ceil(o.x). So solve for t:<p><pre><code> ceil(o.x) = x&#x27; = o.x + t * d.x t = (ceil(o.x) - o.x) &#x2F; d.x. </code></pre> Then, since the grid lines are spaced 1 unit apart, every subsequent intersection will be 1&#x2F;d.x further along in t. In other words, the ray t-values of all the grid crossing in X are stream generated by a simple linear function:<p><pre><code> ((ceil(o.x) - o.x)&#x2F;d.x) + step * 1&#x2F;d.x. </code></pre> And exactly the same thing applies in Y for the Y grid crossings.<p>So let&#x27;s say that we have a ray with origin (0.8, 0.2) and a direction of (0.5, 0.25). Then we get:<p><pre><code> X-crossings = [0.4, 2.4, 4.4, 6.4, 8.4, 10.4, ...] Y-crossings = [3.2, 7.2, 11.2, 15.2, ...] </code></pre> Then we merge those two infinite ordered streams:<p><pre><code> [0.4, 2.4, 3.2, 4.4, 6.4, 7.2, 8.4, 10.4, 11.2, ...] X X Y X X Y X X Y ... </code></pre> and those are the t-values where we walk from one cell to another. Keeping track of which value came from which stream tells us whether the step is in X or in Y (it&#x27;s always one or the other - a DDA never takes a diagonal step). Continue lazily generating and merging the stream this way until you run into something, run out of bounds, or just decide you&#x27;ve gone far enough to stop.<p>Obviously, there&#x27;s some fiddliness when the direction has negative components or worse, zero, but it&#x27;s not to hard to work out the adjustments for those cases. Likewise, you also want to be very careful about handling the case where the ray origin is <i>exactly</i> on a cell boundary. But again, focusing on just one dimension at a time helps when reasoning all that out.<p>Generalizing the concept to a DDA in 3D on a voxel grid isn&#x27;t much harder, either: now you find the stream of Z-crossings as well and do a 3-way merge.<p>(If you ever want to vectorize grid traversal across multiple rays, there are some tricks to that in a 2006 SIGGRAPH paper that I worked on: <a href="https:&#x2F;&#x2F;www.sci.utah.edu&#x2F;~wald&#x2F;Publications&#x2F;2006&#x2F;CGT&#x2F;grid.pdf" rel="nofollow">https:&#x2F;&#x2F;www.sci.utah.edu&#x2F;~wald&#x2F;Publications&#x2F;2006&#x2F;CGT&#x2F;grid.pd...</a>)
评论 #43600592 未加载
jrdres大约 2 个月前
Oh, this is DDA, not Bresenham, for lines.<p>An interesting point about Bresenham&#x27;s algorithm is made by David Schmenk (dschmenk) on his &quot;Bresen-Span&quot; page:<p>&quot;Take note that the algorithm can be viewed as the long division of delta-major&#x2F;delta-minor. The error term is really the running remainder, and every step results in a pixel along the major axis until the division completes with a remainder. The division restarts by moving along the minor axis and adding the dividend back in to the running remainder (error term). This is a bit of a simplification, but the concept is that the long division will only result in two integral spans of pixels, depending on the value of the running remainder (error term). We will take this in to account to write a routine that outputs spans based on the two span lengths: a short-span and a long-span.&quot;<p>In other code, dschmenk does use DDA for anti-aliased lines.<p><a href="https:&#x2F;&#x2F;github.com&#x2F;dschmenk&#x2F;Bresen-Span">https:&#x2F;&#x2F;github.com&#x2F;dschmenk&#x2F;Bresen-Span</a>
grg0大约 2 个月前
Good website&#x2F;visualization, but I think the implementation can be improved. If I remember correctly, one of the strengths of DDA is that it works out entirely with integer math. I think you get there by multiplying out the denominators. Seeing that this implementation involves sqrt(), it probably has room for improvement.
purple-leafy大约 2 个月前
I used this algorithm to build my ray caster blocky world in C, now try doing it in a third dimension (height) :)<p><a href="https:&#x2F;&#x2F;github.com&#x2F;con-dog&#x2F;chunked-z-level-raycaster">https:&#x2F;&#x2F;github.com&#x2F;con-dog&#x2F;chunked-z-level-raycaster</a>
tmdo大约 2 个月前
That&#x27;s incredible timing, I just spent 2 days trying to implement DDA from first principles for my wolfenstein-like game in C.<p>Can&#x27;t wait to see how you explain it.
Surac大约 2 个月前
What language is the sample written in? It is really hard to read for a C guy like me
评论 #43592268 未加载
评论 #43592595 未加载