[video member=cmuratori stream_platform=twitch stream_username=handmade_hero project=chat title="Drawing a Circle on a 286" vod_platform=youtube id=kVtDEy1ndYg annotator=Miblo] [2:11][Upgrade ~remedybg to 0.2.4.2][:admin] [3:12][@egnadh][Q: I remember you were asked what's the best way to draw a circle at a Microsoft job interview. What's the answer?] [5:40][The "free" aspects of drawing a circle on a 286: the centre and cardinal radius points][:blackboard :geometry] [8:10][Our target requirements: no floating point, wide instructions or threading; but branching is fine][:blackboard :geometry] [11:10][Efficiently computing the circle's arc][:blackboard :geometry] [26:13][Storing the error value, x and y][:blackboard :geometry] [31:55][Plotting a mere eighth of the circle][:blackboard :geometry] [37:11][Create bcircle.cpp (from "Bresenham Circle") and create a pixel grid to contain our circle][:blackboard :geometry :programming] [40:10][Build and :run bcircle to see our pixel grid][:geometry :programming] [40:49][Reduce the size of our pixel grid to 32×32 characters][:geometry :programming] [41:04][Check out our smaller pixel grid][:geometry :run] [41:19][Implement our error-based circle drawing routine][:geometry :programming] [48:44][Check out our circle, to find that it is positioned incorrectly][:geometry :run] [48:51][Fix our routine to plot the circle around its centre][:geometry :programming] [48:57][Check out our circle, one eighth of it][:geometry :run] [49:32][Make our routine plot our eighth of the circle around the entire circumference][:geometry :programming] [50:05][Check out our fuller circle][:geometry :run] [50:11][Prevent our routine from plotting the pixel grid's centre point][:geometry :programming] [50:16][Check out our fuller circle][:geometry :run] [50:24][Plot the initial pixel][:geometry :programming] [50:32][Check out our perfect circle][:geometry :run] [50:39][Optimise our routine, using one pointer initialised at the circle's centre in lieu of two stored Cx and Cy values][:geometry :optimisation :programming] [54:31][Check out our same circle][:geometry :run] [54:41][Consider how to remove the eight integer multiplies by the WIDTH][:geometry :optimisation] [58:25][Temporarily make our routine test abs(E0) < abs(E1)][:geometry :mathematics :programming] [58:46][Check out our identical circle][:geometry :run] [58:55][Revert that -E0 < E1 test][:geometry :mathematics :programming] [59:07][See that all remains identical][:geometry :run] [59:10][Continue to consider how to remove the eight integer multiplies by the WIDTH][:geometry :optimisation] [1:00:15][@Rounin][@cmuratori: X<<5?] [1:00:20][Sully the WIDTH and HEIGHT so that they are not a power of two][:geometry :programming] [1:00:51][@ggn2][@handmade_hero Calculate the initial X/Y into a pointer and increment that?][:geometry] [1:01:26][@said6289][@handmade_hero Store XWidth and YWidth pointers that you increment accordingly every run][:geometry] [1:02:12][Ruminate on our circle drawing routine][:geometry] [1:02:50][@ggn2][@handmade_hero Well, I'm thinking on 68000 terms where there were a bit more registers than x86][:hardware] [1:03:22][Consider the WIDTH multiply to have potential for improvement][:geometry :optimisation] [1:04:00][Try to remove the Ep += 1 from the equation][:geometry :optimisation :programming] [1:04:43][Check out our (different) circle][:geometry :run] [1:04:50][Reinstate the Ep += 1][:geometry :optimisation :programming] [1:06:29][@x13pixels][Q: Can you get rid of the "Ep += 1" line?][:geometry :optimisation] [1:07:09][Try to negate X the whole way through][:geometry :optimisation :programming] [1:08:17][Check out our same circle][:geometry :run] [1:08:37][Assess our options, with X negated, and try plotting X and Y pixels from different eights of the circle][:geometry :optimisation :programming] [1:13:31][Check out our barely-plotted circle][:geometry :run] [1:13:35][Try looping while X <= (R / 2)][:geometry :optimisation :programming] [1:14:02][Check out our big X][:geometry :run] [1:14:06][Continue to try plotting X and Y pixels from different eights of the circle][:geometry :optimisation :programming] [1:17:16][Plotting X and Y pixels from different eights of the circle][:blackboard :geometry :optimisation] [1:18:41][Understanding why our X / Y plotting on different eighths doesn't work][:geometry :optimisation] [1:20:55][@filiadelski][Q: I'm sorry we decided to go with another candidate because he went to Harvard] [1:21:20][Midpoint[ref site=Wikipedia page="Midpoint circle algorithm" url=https://en.wikipedia.org/wiki/Midpoint_circle_algorithm] and Bresenham's circle drawing algorithm[ref site=GeeksforGeeks page="Bresenham’s circle drawing algorithm" url=https://www.geeksforgeeks.org/bresenhams-circle-drawing-algorithm/]][:geometry :research] [1:23:22][Temporarily make our routine always increment the Y][:geometry :programming] [1:23:48][Check out our circle with the Y always incrementing][:geometry :run] [1:24:36][Revert our routine to not always increment the Y][:geometry :programming] [1:24:39][Compare our circle][:geometry :run] [1:24:41][Increase the radius of our circle][:geometry :programming] [1:24:50][Check out our larger circle][:geometry :run] [1:25:17][Leave further :optimisation as an exercise for the reader] [1:26:40][Check out the register count of the Intel 386[ref site=Wikipedia page="Intel 80386" url=https://en.wikipedia.org/wiki/Intel_80386] and 286[ref site=Wikipedia page="Intel 80286" url=https://en.wikipedia.org/wiki/Intel_80286][ref site=WikiChip page="80286 - Microarchitectures - Intel" url=https://en.wikichip.org/wiki/intel/microarchitectures/80286][ref site=Wikipedia page="x86" url=https://en.wikipedia.org/wiki/X86] and suggest writing this routine in x86 assembly targeted at DOSBox's :emulation of a 286[ref site=DOSBox url=https://www.dosbox.com/]][:research] [1:31:41][@alex_deak][Q: Hi Casey! (Sorry, it's pretty long, and has nothing to do with circles) I'm a mathematician, trying to be a graphics / engine programmer. I made some pet projects using OpenGL and Vulkan, in which I was able to make the things I wanted, but since my lack of enough experience, I had a hard time figuring out what "professional programming" is. I started watching [~hero Handmade Hero] in December from day 1, and I almost caught up (currently I'm at day 520). Thanks for this amazing series, it has been inc… \[sic\]] [1:32:29][Wonder who is responsible for the message truncation] [1:33:43][@alex_deak][Q: Do you have any advice about starting a career in graphics / engine programming for someone, who has a very strong background in mathematics, physics, can do research, perhaps can come up with creative ideas, wants to learn ab… \[sic\][ref site=YouTube page="HandmadeCon 2016 - Technical Direction at Blizzard" url=https://www.youtube.com/watch?v=jyA0csH4KNE][ref site=Milton url=https://www.miltonpaint.com/]] [1:43:01][@ggn2][@handmade_hero For what it's worth, PCem[ref site=PCem url=https://pcem-emulator.co.uk] has cycle exact CPU cores if you want to be more accurate][:emulation] [1:43:46][@tshugako][Q: On one of the first [~hero Handmade Hero] streams you said that it was faster to work (bitwise operations) on a uint32 than a uint8. Why?][:performance] [1:50:08][@toideng][Q: Any opinion of Linux's way to define integer types with one letter (like u8, i16, i64)?][:language] [1:51:21][@flightlesshippo][Q: Pug with a gun needs to be an enemy in the game] [1:51:32][@printf_armin][Q: For a program for Windows only is DX the better or OpenGL?][:api] [1:51:55][@saidwho12][@handmade_hero What do you think of getting a college degree in information technology? Should you instead be working on hobby projects? My dad has been wanting me to get into a post-secondary school for a long time] [1:55:37][@centhusiast][Q: I have done lots of tools in C like a string utility, JSON parser, data visualization on Linux using X11, vector library and some other tools. Do you think these can be valuable for the CV?] [1:59:32][@alex_deak][Q: Great, thank you! Do you think it's maybe enough to have a YouTube channel, instead of a webpage? Since I have no idea how to do a webpage... Or is it very basic knowledge that I should know?] [2:00:31][Recommend The ryg blog[ref site="The ryg blog" url=https://fgiesen.wordpress.com/]][:research] [2:01:55][@joeyiswatching][Q: Why were you suggesting to look at how to do it under 286? I just joined as you were talking about that] [2:02:56][@boonetbe][Q: I've been using a :language with function polymorphism similar, I think, to what [@naysayer88 Jon] is doing in JAI, i.e. "multiple dispatch" / dispatch on input types. I recently tried out some different languages and found this is not at all very common. How come not more languages have this? Is it hard to implement, other issues?] [2:04:40][@flightlesshippo][Q: I heard JAI is close to beta release? Will you be playing about with that or leaving it until it's matured more?][:language] [2:05:10][@centhusiast][Q: Have you met the Amiga programmer like Bruce Dawson? It seems like they were the great programmers] [2:06:33][@toideng][Q: Would you use sine / cosine now?][:mathematics] [2:07:18][@victorn][Q: Are you going to push the circle solution to GitHub?] [2:07:28][@unxx][Q: Do you ever use any scripting :language?] [2:07:37][@toideng][Q: Is there any computer world outside US?] [2:19:59][@centhusiast][Q: I saw some codes that use the array of function pointers and enums to avoid branching. enums like action type move_right, move_left and then function pointers associated with them. Do you think it is a good idea to do that?][:language] [2:22:52][Understanding a Skylake core[ref site=WikiChip page="Skylake (client) - Microarchitectures - Intel" url=https://en.wikichip.org/wiki/intel/microarchitectures/skylake]][:hardware :performance :research] [2:33:51][Branch-prediction in the context of a Skylake core[ref site=WikiChip page="Skylake (client) - Microarchitectures - Intel" url=https://en.wikichip.org/wiki/intel/microarchitectures/skylake]][:hardware :performance :research] [2:38:48][Understanding the Skylake CALL instruction[ref site=Intel page="Intel® 64 and IA-32 Architectures Software Developer Manuals" url=https://software.intel.com/en-us/articles/intel-sdm]][:isa :research] [2:45:23][@boonetbe][Q: I saw [@naysayer88 Jon] implement a compare and swap intrinsic recently for lock-free multithreading. Except for incrementing counters and stuff, what is it useful for? Do I understand it correctly that it's only useful when the thread-unsafe code / task is small?[ref author="Maurice Herlihy" title="Wait-Free Synchronization" publisher="Digital Equipment Corporation" url=https://cs.brown.edu/~mph/Herlihy91/p124-herlihy.pdf]][:threading] [2:48:16][@boonetbe][Q: Why aren't we using analog computing, i.e. instead of bits use frequencies. Noise?][:hardware] [2:49:17][@florian3321][Q: I am 50k lines into a C++ Android engine development (tried to stay away from inheritance and stuff. Note that I am still learning). Should I rewrite it the "C" way? How can I change my thinking? You at some point said that one should come to the point where OOP fails and then use non-OOP, but I think I am not really there yet. Hope this is not a dumb question][:language] [2:50:24][@garryjohanson][Q: He did do a video on branch predictions, though I don't know if it's germane to what we're talking about[ref site=YouTube page="Rambling talk about CPU uArch stuff" url=https://www.youtube.com/watch?v=oDrorJar0kM]][:hardware] [2:52:22][Recommend [@rygorous Fabian]'s entire YouTube channel[ref site=YouTube page="Fabian Giesen" url=https://www.youtube.com/channel/UCcRaa0AcYX32c0m8wJJHNWg/videos]][:research] [2:53:01][Wind down] [/video]