I can haz rotation in 3D?

Ladies and gentlemen, prepare to be amazed and astounded. I have written code, from scratch (yes that means I did not copy from any book), to rotate vectors in 3D around arbitrary axes. Behold: http://axefrog.com/jswireframe/1.rotation/

Image

Because it’s all JavaScript and (almost no) HTML, you can view and steal the source code if you want, though I made no real attempt to make the code pretty, so… yeah, sorry about that.

It’s good to feel like I’m actually progressing with my understanding of the fundamentals of 3D math, but of course I still have a very long way to go. This demo was put together using JavaScript and the HTML5 canvas element. I’m using a simple orthographic projection because it’s super easy to plot and I’m not fancy enough to do a proper camera perspective projection just yet.

To make this demo, I had to make sure I understood the following:

  1. Drawing lines on a canvas with JavaScript
  2. Vector dot products
  3. Vector cross products
  4. Vector normalization
  5. Basic vector math (addition, subtraction, multiplication)
  6. … and of course, rotation in 3D space.

Why did I use JavaScript and HTML instead of Direct3D, you might be asking? The point of this exercise was to understand what I was doing, which meant learning the mathematics. HTML5 canvas is very easy to draw on, so it served as a useful platform on which to prove to myself that I understood the material.

Ye olde mathematics

One of the reasons I’ve elected to learn Direct3D (and later, OpenGL) rather than just, say, downloading Unity and learning that, is that I’ve often been quite frustrated in the past using a tool and having no idea what goes on under the hood. That lack of understanding meant that I could always reach a certain point of mediocrity but had no power to really bend the system to my will. My reasoning here is that if I know exactly what I’m doing at a very fundamental level, then developing games, rendering beautiful graphics and building interesting subsystems becomes a case of logic, creativity and problem-solving, and these are the things I enjoy most when developing software. What I find most frustrating and most damaging to my motivation is when I hit brick walls that exist only due to my lack of understanding of what I’m doing.

After I finished adapting my spinning rainbow cubes into my “Grasshopper” game engine, I then attempted to follow the next part of my book (Direct3D Rendering Cookbook) and implement texturing and lighting, but because I’d already been adapting things to my own engine, things didn’t work quite right; the lighting was “prepainted” onto the cubes, which would then spin in different directions and ruin the effect. Fine, so fix it, I hear you say! I attempted to do that and in doing so I realised I didn’t understand the underlying algebra and matrix math well enough to figure out what I was doing wrong. So… back to basics.

I’ve discovered that most books I’ve read seem to be really good in some areas and then explain certain other things in ways I don’t quite get, or they gloss over aspects of an important topic, leaving me floundering in the material that follows. Take two or three different books on the same topic though, and areas where one book falls short seem to be well covered by another book. On top of that we have the universal helper; the internet!

So, here’s what I’ve got now (mostly on Kindle, as it’s just so damn convenient):

For Direct3D

For game-specific mathematics:

For foundational mathematics:

Note that I bought all of these on Kindle, other than Mathematics for 3D Game Programming and Computer Graphics, which doesn’t seem to have a Kindle version available. Having all of these on Kindle is super convenient, as textbooks are usually big, thick and heavy and I seriously can’t be bothered carrying those around with me. Last year I got a Kindle Fire for my birthday, so I’ve been mostly using that to read these books while on the bus and train to and from work. There’s also the Kindle Cloud Reader, which lets you read Kindle books in your browser, and editions for most other platforms, including iOS, Android, Windows 8, etc. I usually open the cloud reader on my second monitor and refer to it while coding. I’ve noticed there seems to be two varieties of Kindle reader software. The first, and most common, dynamically reflows text according to your device screen size and settings. The e-Ink kindle reader uses this same software internally. Then there is the “advanced” version of the Kindle reader, which does everything the others do, but can also display Kindle books of the “PDF” variety; that is, books that have been released to Kindle pre-published with specific layouts and not adapted to be able to reflow like other Kindle books. Unfortunately only the downloadable Kindle for PC and the Kindle Fire can read books of this type, which means a basic Kindle, or any of the normal Kindle reader software on Android or iOS is not an option when stuck with one of those types of Kindle books and unfortunately for me, the book 3D Math Primer for Graphics and Game Development is just such a title.

Nevertheless, I’m getting through all of these slowly. Dot products, cross products, basic matrix math and so forth are slowly becoming a part of my brain, and being able to switch back and forth between different texts and have that knowledge reinforced through repetition, practice and alternate explanations is really helpful.

The return of the cubes

After a lot of stuffing around trying to get my matrices, vectors and other stuff worked out, not to mention completing enough of my “Grasshopper” 3D engine to make the cubes demo even possible in the first place, I have finally got my cubes demo working with the new engine. Behold:

2014-03-09_2226

Note the fancy debug panel indicating some of what’s going on. Here’s the source code, should you wish to have a look around and try to run the demo yourself.

Some issues:

  • The debug panel tightly couples the list of debug values to the rendering code, which is bad, because it means I can’t cleanly share the panel with my core game logic, which is supposed to be operating without any knowledge of the renderer. I’ll have to fix this.
  • I was experiencing an issue where all of the cubes were being rendered with their back faces showing and the front faces hidden, which looked very strange. I “fixed” it by setting CullMode to Front, which is backwards because that’s supposed to cause the problem I was experiencing, not fix it. Going to have to get some help on that.
  • I have input handling for forward and backward (using the keys W and S) but when I went to implement camera rotation it occurred to me that the maths for this hasn’t sunk in yet (or even been properly understood to begin with actually), so I’m going to have to focus on that a little bit more.

Here’s a terribly-overcompressed video of the demo on YouTube. It’s slightly better if you set it to 720p quality when playing the video. One of these days I’m going to figure out how to actually record high quality game footage and how to have it also look decent on YouTube.

So, I guess next steps are to solve these issues and include mouse movement to allow for full freedom of movement of the camera. After I’ve done that I’ll be looking at texturing and lighting.

Got my debug information panel running

Just a quick post; I got the code for my debug output panel working. It dynamically sizes according to its contents and is very easy to turn on and off and add/remove items to/from, and I know it will be invaluable in helping my see the inner workings of my engine while testing. Here’s the code. The next step is to get my cubes (see previous posts) to use the engine.

Back from the dead

Oh, hai there. I’ve had a big 2-3 month gap in my game development learning but over the last week or so I’ve found the time to continue where I left off late last year, which means this blog can return from the dead! Praise the flying spaghetti monster!

rainbow-cubes-in-space-framelessNow, I wanted to continue on with my cubes project, but when I sat down where I left off with my Direct3D book I was having trouble getting back into it particularly because of the disconnect between the C++ in the book and the SharpDX-based C# code in my own project, but also because I wasn’t happy with how my “framework”, if you can call it that, felt from a separation-of-concerns perspective.

7101OT_Direct3D Rendering Cookbook

And that’s when I discovered the Direct3D Rendering Cookbook, which was also available for Kindle, which allowed me to feed my instant gratification monster and get back into it straight away! The reason this book is working so well for me is that all of its code is written with SharpDX and C#, which is exactly what I’m using already, so not only is the code in the book easier to follow, but I’m getting a better insight into areas of SharpDX that I’m not familiar with, how to properly use the SharpDX APIs, and more ideas on how to structure my code properly.

In the second chapter the book introduces a basic framework on which it builds the samples in the rest of the book. My first reaction to this was apprehensive, as I wanted to be introduced to any code I write piece by piece and not have it dumped on me with instructions to “just use this”. My concerns were unjustified though because the book explained all of the code in great detail (and it was fully commented as well) and as a bonus, after reviewing all of the code myself, I realised I had a much better idea how to structure my own code, and this has led to the beginning of my very first 3D engine: Grasshopper. I’ve named it this because I recognise that I have “much to learn, grasshopper”, and I am very aware that it will be thrown away, rewritten and refactored many times as I continue to learn. Nevertheless, as I have been coding for many years, hopefully I’ll make good decisions with my code and avoid a significant number of rewrites that might be necessary if I was also learning to code through the medium of game programming as is so often the case with many of the developers asking questions on the gamedev.net forums.

Right now I’m in the process of recreating the cubes demo using Grasshopper, and I’m also creating a nice 2D text panel for displaying debug values. I expect this will all be finished within a couple of days, at which point I’ll write another blog post complete with screenshots, and I’ll post the code in my Github project, in case you want to take a look.

9781568817231Oh, I almost forgot to mention that on my train rides to and from work, I’ve also been reading a math book I bought also. You may remember (if you have ready my other blog posts) that I already bought a book on mathematics for games, but one thing I found difficult is that it glossed over some of the foundations I needed explained properly and made it hard for me to follow along in subsequent sections. So, last weekend when I bought the other book I mentioned above, I also stumbled across the site gamemath.com which was offering a book 3D Math Primer for Graphics and Game Development, available through Amazon, and on Kindle too! The absolutely fantastic thing about this book is that it not only does it not assume anything more than a rudimentary level of high school mathematics education, but it has been written in a very friendly, easy-to-read style, unlike many other math textbooks, which can be quite dry. Definitely recommended, based on the 60-70 pages I’ve gone through so far.

Quick Update

I’m not dead. And my motivation is as strong as ever. Unfortunately sometimes you have to prioritise, and I’m behind on a commercial side project I’m trying to finish up, hence the silence on the game development front. As soon as that’s on track, posts will pick up here again.

For now, here’s something to look at. The latest version of the NVidia drivers come with a handy tool for capturing video and sound output directly to video, thus eliminating my need to pick up a copy of DXtory (or similar). I’ve captured my spinning cubes with the tool and posted them to YouTube. Make sure you set to HD (720 or 1080) or it looks overcompressed.

rainbow-cubes-in-space-frameless

#6 Houston, we have instancing and animation

It is satisfying to feel my understanding growing, little by little. Each new task forces me into situations where I hit bugs, errors and crashes and, while trying to pull out as little hair as possible, I gradually figure out where I’m going wrong and what the individual API methods, parameters, enums and so forth mean, and how they are supposed to be used.

This time around I wanted to figure out how to render the same cube in multiple locations and give each instance its own unique positional data and animation parameters, which meant I had to figure out how to draw my triangles instanced, and how to pass individual parameters for each instance to the vertex shader so that the cubes could each be rendered with their own rotations. And as before, I have tidied the code up even more. It’s nice to see a very simple beginner’s 3D engine taking shape, little by little.

Some things I learned:

  • Quarternions – not specifically the maths behind them, but their usefulness in representing a 3D rotational state. I also found handy methods to create matrices from a quaternions, which is what you need if you want to actually make use of the quaternion in terms of representing the vertex’s rotation based on the quaternion in question. It is because of these that my cubes now rotate in 3D space.
  • Drawing instanced triangles – I pulled bits of information from around the place for this one, as it wasn’t particularly clear in any of my usual sources, or perhaps I was just impatient and if I’d done things in the order that the chapters are laid out, I’d have figured it out quicker. In any case, I learned how to use an instance buffer, and how it relates to the vertices it represents.
  • Passing per-instance data to the vertex shader – This was a real pain, as it requires a deeper understanding of how input layouts work, and how their parameters represent the vertex shader’s function signature. Given that I lack (or lacked) the understanding, it took a bunch of trial and error and a lot of back-and-forth on a couple of different forum threads, both on gamedev.net and gamedev stackexchange, to finally understand what I was doing wrong, Now, I’m still by no means an expert, but I feel like it’s a little bit clearer now, so that if I want to pass more data into a shader, I’ll be able to with a bit more ease next time.
  • DirectX debugging – You know, if I’d learned this one first, I’d have suffered a lot less during this task. I had to set my project to allow native debugging, and I had to initialize my device to enable the debugging flag. Once I did this, the debugger output window magically started telling me, very precisely, what I was doing wrong whenever my initialization code crashed! Very cool.

Oh, if you read my previous post, I also worked out why DrawIndexed was forcing me to specify three times the number of triangles as I actually had. Turns out the index buffer refers to the indices of each vertex, not the indices of each triangle. Who knew?

So here we go, a screen capture of my instanced cubes. To see them move, you’ll have to grab the source code and run it! Note that I’ve hosted the code on Github now, which is better for me, because source control is better than zip files.

rainbow-cubes-in-space