GARIN R. K. RICHARDS
  • HOME
  • linkedin

DEV-LOG

Concluding the Semester

12/10/2017

0 Comments

 

On the Purpose of the Assignments

While on an assignment by assignment basis they each taught us a specific implementation, design, or engine process. I think there is a larger lens to look at the semester as a whole.

In previous semesters we've written engines where we were instructed on what to do, but for the most part not HOW. While the difficult part for me wasn't the exact implementation of a given feature, it was often times the design or coming up with the sensible decisions on WHERE to place things. By having an existing code base to work within, I had immediate examples for design centric decisions when it came to writing the various systems that we've done.
​
I also enjoyed the "directedness" of the assignments. Because of this, I was able to spend most of my time on the "HOW" to accomplish a goal. Not "WHERE" that has tripped me more than once in the past. I felt like the learning was that much more effective because I didn't spend too long spinning my wheels wondering on the best practices to go along doing something. Since I could just look elsewhere in a different system and see how it was implemented, and try my best to stick to an existing design. By imposing this arbitrary design consideration on myself, I also got experience on working, and sticking to an existing designs. Which, may be more useful if working on a large team.

What did I get out of the class?

Of course, the exact topics that we covered were at times completely new to me, so it was great to get my first experience with some of these systems and topics. Although, the best insights I got out of the course were directly related to Engine DESIGN and the thought processes / justifications for doing things a certain way.
I do want to comment on the fact that at the beginning of the semester I had thought the codebase was quite huge. But, at the end I believed that I had a decent grasp on the code base as a whole. I may not know every system intimately, but I had gotten to the point that I knew the DIRECTION to look in for specific things and questions.
 

Thoughts on General Software Architecture

After the experiences of this semester, working in this engine while also alongside a "large" engineering team. Time and time again I found myself practicing the design mantra of things should be where you THINK they should be. Meaning, sensible. I used that word far too much this semester... I do believe that there needs to be a period of planning prior to beginning major work on a project, whether that be the raw outlining of systems and where they exist or directly on the code habits of working with these systems. I prefer the upfront planning, even if it be brief and sparse. I have always been a person that prefers a plan of attack versus "winging it".

This semester one of my colleagues made the statement concerning what constitutes good code (paraphrased):
"It needs to be easily iterable, flexible enough that changes can be made to match the needs of the developers and design without too much rework".
To do this, what does it entail? Surely we can't be aware of ALL of our future needs for the entirety of the project. But there are base design considerations that can be made. For example, in my latest project NOT having on screen buttons tired DIRECTLY into the graphics system. This would server better in its own interface system that speaks to graphics. By having multiplatform being a high emphasis this semester we can take steps to ensure that our code is as platform independent as possible by using a multitude of the strategies this semester.

I believe good software architecture should be easily iterable.
​

Bad software design ties systems together, with dependencies going back and forth requiring a single end change, to take numerous changes along the way. Or more succinctly:
 
Bad software architecture is when a "small" end change requires a "large" internal change.
0 Comments

Final - Interface

12/10/2017

0 Comments

 
Picture
Basic UI
Picture
A button is selected!

What and Why?

I return with a new engine feature, basic user interface! User Interface programming and design has been a field that yours truly has had an interest for quite some time. Seeing that we developed very basic on screen sprites, I figured why not try my hand at creating some basic buttons?

My biggest experience with game interface programming has been done via Unity, therefore, many of my design decisions and criticisms of my implementation may compare and contrast directly with Unity's Canvas and UI system. One that I have gotten to know pretty well over the years. Before attacking this, I found it useful to map out the exact capabilities that we'd have to write:

Observations:
  • Lack of any mouse control / integration in the User Input System
  • Lack of a proper on screen image system
    • ​All we've had so far were 2D Sprites that we've created directly within the Graphics System
  • ​Dealing with the fact that our images were in a screen space that uses bounds of [-1,1] for both the horizontal and vertical​

How?!

The Buttons are essentially a different type of Sprite but with the needed extra functionality to process click events. The position of the mouse click is passed into ProcessClick(). Which is polled each update, the reasoning for such will be explained later.

But, the mouse?!

I mentioned before that the existing engine had no support for tracking the mouse whether it be it's state or direct position on screen. To get this done, we had to do some digging in the proper Windows API. This required some brushing up on WindowHandles, and putting these functionalities in an appropriate place. We have an existing UserInput system that until recently, was only detecting simple key presses. There, we can no poll if user has the mouse button clicked or not.
Picture
Testing if the user's mouse is within the game window

Okay, but what about detecting clicks?

The real meat of the challenge was detecting whether or not the user clicked on a given button, in a sensible way. Currently, our process for listening for user input has been to check every frame for user input. Our engine was not event driven. Meaning, the engine wasn't listening for an input event to fire off. For moving our meshes and sprites in prior assignments, we just checked the state of the keyboard every frame. This isn't a bad way, but it is a way to do it, in fact Unity I believe does this. You'd do the following in your Update​ 
Picture
The fastest way to detect if 'A' was pressed in Unity

Finally, how about image bounds?

After we know how and where buttons clicked are performed, how do we figure out if they've been clicked on our button?! I mentioned above that I made note that we declare the position/size of our on screen sprites via bounds of [-1,1] on screen. This is similar to how Unity's canvas system allows the developer to position elements based on variable screen size. (Unity also allows you to specify the direct pixel offset as well).

Because Windows's calls that give us the mouse position give it to us in absolute pixels, we must convert our screen space bounds of [-1,1] to actual pixels within the window.
Picture
Going from [-1,.1] to [0,WindowWidth/WindowHeight]
Above is the lines where we can compute exactly where is the center pivot of the image in relation to the actual size of the window. The window size is passed in at button creation for this to happen. We do the same to determine the left, right, top, and bottom bounds of the image.

These are then used in a ProcessClick() that will fire off the saved callback specified to fire off when a click is detected.

How did this all fit?

With the lack of proper mouse support. a true UI system, to get this system working most of it is shoehorned into graphics. Which, while it does work, I really don't like it. Because this is part of a new Interface system. I would have made a proper Interface system, just like Graphics, UserInput, etc. But with direct interface with Graphics. Since of course, they'll need to talk to one another.
Picture

In Conclusion

This challenge was more of a personal exercise on understanding what needs to go into creating a sensible Interface system. The biggest hurdle was working with a code base that had no regard for the matter, and trying to fit my logic into sensible places that fought with my personal opinions on where things should go while working within a specific time frame.

Try it out!

Below you can find executables that allow you to mouse around and test out the menu for yourself. Unlike prior downloads of the game, movement of the camera, a mesh, transparency, all of that has been taken out. When you click a button, they are specified to log the event to the log file, which you can find in the executable's main directory.
final_garinrk_x64.zip
File Size: 1343 kb
File Type: zip
Download File

final_garinrk_x86.zip
File Size: 1566 kb
File Type: zip
Download File

Thanks to those at Hathos Interactive for allowing me to use some assets from their current project for this example!

NOTE: While the site is quite bare, the team will be releasing an update to their current project sometime this winter / early next year.
0 Comments

Assignment 14 - Going Clearer

12/2/2017

0 Comments

 
Picture
Picture

Being Transparent!

Recall back to when we first implemented three dimensional graphics in our game engine in week 9's post. One of the challenges we hypothesized was that of depth. As in, who is in front of whom? Well, we're fortunate that for those opaque meshes, the GPU is in charge of who is in front of what based on their world position and just overwrites that pixel with the pixel that is in the front. But what about transparent objects? 

Because an object is transparent, we must know what is behind it. This order is very important, and we'll keep in mind the logic of drawing from front to back. Or perhaps more simply, we must first "draw" the pixels that are behind the transparent objects before we draw the transparent objects with their effect. This is crucial as the opaque object's must be on screen in order for the alpha blending to occur properly within the transparent meshes.

Previously in both our application and rendering threads, we had a vector that held the Meshes that would be rendered on screen. But how do we impose order within these structures? We'll have to sort them based on their Z position. We could have approached this by adding the transparent meshes to the same structures that held the rest of the meshes, but for simplicity, we'll just go ahead and make a separate structure that is sorted that only holds transparent meshes. We'll just make sure that these are sorted correctly based on their position's Z value, and that they are the ones drawn last.

Specifically, we do the following:
  • Calculate the Z position of the objects, in camera space
    • This is so we know where the objects are in relation to the camera to draw them in the appropriate order
  • Draw our opaque meshes first
    • The GPU will handle who goes in front of what then.
  • Sort our submitted transparent meshes based on their position in the world
  • Draw our transparent meshes in this sorted order.

In the screenshots above you can see two cube meshes that use our transparent fragment shader, placed in front of one another to be able to see their transparencies with an opaque mesh in the background.

​Controls

​The Camera: [Key : Action]​​​

[W : Move Forwards]
[A : Move to the Left]
[S : Move to the Right]
[D: Move Backwards]
[Space: Move UP]
[Left / Right Ctrl: Move DOWN]

The Brain: [Key : Action]

​[Arrow UP : Move Forwards]
[Arrow LEFT: Move to the Left]
[Arrow RIGHT : Move to the Right]
[Arrow DOWN: Move Backwards]
[Page UP: Move UP]
[Page DOWN: Move DOWN]

Downloads

You can try out these games via the below links. The only difference is that Direct3D will be used in the x64 version, with OpenGL in the other. They have been built and verified to work on Windows.
assign14_garinrk_x64.zip
File Size: 863 kb
File Type: zip
Download File

assign14_garinrk_x86.zip
File Size: 855 kb
File Type: zip
Download File

0 Comments

Assignment 13 - Build Simplification

11/28/2017

0 Comments

 
Picture

How to Simplify the Build Process

Prior to this week, in order to build our game assets using the appropriate build tools, this required the use of a lengthy .lua file that contained instructions on how, and when, to build each and every game asset. This file stretched to almost 500 lines of code! It was a direct offender of programming paradigm of being DRY or Don’t Repeat Yourself. It contained dozens of repeated routines that did similar tasks. These tasks included determining if a directory should be created to house our final compiled assets, and error reporting when appropriate.
To mitigate this, we now have our new Asset Build System! The only difference between our game assets are their names / paths and file type. We can contain this data in a more central location, formatted nicely within another .lua file, as shown below:
Picture
We contain our meshes into our “meshes” group, shaders into “shaders”, and so on. We can then pass these arguments to functions that determine what type they are, and can feed them to the appropriate executable. In the end, we now have a more versatile asset building system with minimal repeat routines. Also, it can be easily extended to include assets of different types that may be useful in the future if the engine is ever expanded upon.
Another thing to mention, is that the above .lua file containing assets relevant to the game is now contained directly within the game’s source directory. No longer having to be included as a real part of the game engine. This is a forward step in making the clear distinction between game and engine code.

​Controls

​​The Camera: [Key : Action]​​​

[W : Move Forwards]
[A : Move to the Left]
[S : Move to the Right]
[D: Move Backwards]
[Space: Move UP]
[Left / Right Ctrl: Move DOWN]

The Brain: [Key : Action]

​[Arrow UP : Move Forwards]
[Arrow LEFT: Move to the Left]
[Arrow RIGHT : Move to the Right]
[Arrow DOWN: Move Backwards]
[Page UP: Move UP]
[Page DOWN: Move DOWN]

Downloads

You can try out these games via the below links. The only difference is that Direct3D will be used in the x64 version, with OpenGL in the other. They have been built and verified to work on Windows.
assign13_garinrk_x64.zip
File Size: 784 kb
File Type: zip
Download File

assign13_garinrk_x86.zip
File Size: 776 kb
File Type: zip
Download File

0 Comments

Assignment 12 - Binary Files!

11/23/2017

0 Comments

 
Picture

Binary Files!

Last time on the dev blog, we implemented the use of .lua writing and parsing for our game engine. This week, we turned to binary files on our quest for a more efficient system. Specifically, we added support for reading and writing binary files. Those being files of bytes that we can parse in at runtime in order to generate the meshes in our game, like the brain that you see above!
Picture
A simple floor mesh in our binary file format

The Data

The data that comprises one of our meshes are the following:

Index Data
​Vertex Data

In the above example, this file describes the "floor" in our game scene. At the moment, it has a picture of a dog and is composed of four Vertexes of which each describes the position, color, and UV data of each vertex. Then, six indexes that refer to the drawing order of the vertex to create the two triangles that make up the simple floor plane. 

Why Binary Files?

After seeing the work we went through to make our mesh data as easily readable by the human eye in the previous post, you're probably wondering as to why would we go through the hassle to move this new format? There are two immediately discernible advantages, file size and process speed. 

Because binary files are just a sequence of bytes, no alphabetical characters, the data is exactly as the computer reads it. Meaning, because we don't have to "transcribe" or "translate" into the more readable english .lua format that you saw previously, we can now write code that directly reads the values of the bytes contained within the file. This time, we don't need to write the visual representation of the letter / coordinate axis "z" along with it's value but rather, we can read a set of x bytes at a given position directly as the z value itself.

Continuing on the point that binary files are the exact representations of the data that they are, it makes processing and parsing much easier as well. For example, instead of having to search for the letter "x" and the corresponding value to the key (as lua represents our arrays as key-value pairs) we know directly that the first bytes in the vertex data sequence will correspond to the x value. Thus, we can interpret it exactly so in our read code. You'll see the direct evidence for this proposition later when we get to the timing of the process functions of this blog entry.

But don't worry! Human-readable formats like .lua still have their place here in the engine. When writing the data or storing the data, we will continue to use .lua. This still is the case because we're emphasizing readability and versatility when it comes to manipulating game data, like our meshes for example. However, at runtime, we're going to emphasize speed as we'd like our game to get up and running as soon as possible! To do this, we just have to make sure that we build our .lua readable data into their appropriate binary counterparts.

How about them Platform Specifics?

We can't forget the arbitrary platform specifics that we have imposed on ourselves throughout the engine though. And I'm speaking specificaly about the use of OpenGL for x86 builds, and Direct3D for x64. 

Recall from the previous section that we saved the direct position, UV, and color data of a given vertex. Because our exporter for Maya outputs in OpenGL we must remember to build our binary files into say, the correct Direct3D requirements. To do that we:
  • Negate the Z value of our position
  • Define our V value as 1 - V
  • Flip the winding order from OpenGL's Right Handedness to Direct3D's Left Handedness

We do these steps in our MeshBuilder code, where .lua is compiled into their binary representation.

Extracting Binary Data

Picture
Extracting the data from the raw loaded chunk of bytes is fairly straight forward if you're decently versed in pointer manipulation. The key to this process is understanding how the data is written to file. Knowing this we know the exact format, eliminating guesswork. We know the format is as follows:

Amount of Indexes | The Actual Index Data | The Amount of Vertexes | The Actual Vertex Data

With that in mind, as well as the exact data types that are used to write these to disk, it is fairly simple to do the arithmetic to get to the appropriate addresses in the loaded data to store into our Mesh representation

Data Proof!

Earlier I mentioned how we'd now prove our assumption that reading binary data is faster than .lua script. The following are the results of timing the exact functions that do these tasks. The difference is easily seen!

This was done with the same mesh that you see in my first screenshot, the brain:

Lua Load Time: 0.016053 Seconds
Binary Load Time: 0.000545 Seconds

Loading via binary files are tens of times faster than that of Lua! But, it doesn't stop there. If we also compare file size we get the following:

Lua File Size: 434KB
Binary File Size: 91KB

The advantages are to speak for themselves.
​

Controls

​The Camera: [Key : Action]​​​

[W : Move Forwards]
[A : Move to the Left]
[S : Move to the Right]
[D: Move Backwards]
[Space: Move UP]
[Left / Right Ctrl: Move DOWN]

The Brain: [Key : Action]

[Arrow UP : Move Forwards]
[Arrow LEFT: Move to the Left]
[Arrow RIGHT : Move to the Right]
[Arrow DOWN: Move Backwards]
[Page UP: Move UP]
[Page DOWN: Move DOWN]

Downloads

You can try out these games via the below links. The only difference is that Direct3D will be used in the x64 version, with OpenGL in the other. They have been built and verified to work on Windows.
assign12_garinrk_x64.zip
File Size: 784 kb
File Type: zip
Download File

assign12_garinrk_x86.zip
File Size: 775 kb
File Type: zip
Download File

0 Comments
<<Previous

    Categories

    All
    Engines
    Programming

    RSS Feed

Powered by Create your own unique website with customizable templates.
  • HOME
  • linkedin