Jump to content

  • Log In with Google      Sign In   
  • Create Account

SpeedRun's Journal

Screen To World Coordinates

Posted by , in Tutorial, Snippet 06 December 2012 - - - - - - · 1,017 views

This snippet shows how to convert a point on screen to a corresponding point in the world. It borrows heavily from the concept of ray-tracing.

Let x and y be the point on the screen which we want to convert to the world space.
We need to create a ray which passes through the camera and the point(x, y) in worldSpace
This ray needs to satisfy the line equation (1)
where Pl = point along the line.
C = Point on the line. In this case the camera position
D = the Direction of the ray
t = some float

Now we need to get the direction of the ray.

First we transform the point to our View space coordinates. View space ranges from -1 to 1 on the x and y axis and 0 to 1 on the z axis with (0,0) being the center of the screen. We can set viewSpaceZ to 1 since the ray goes into the screen

We just reverse the following formula which is used to scale the the position in the world to fit the viewport size.
x = (ViewSpaceX + 1) * Viewport.Width * 0.5 + Viewport.TopLeftX
y = (1 - ViewSpaceY) * Viewport.Height * 0.5 + Viewport.TopLeftY
z = Viewport.MinDepth + ViewSpaceZ * (Viewport.MaxDepth - Viewport.MinDepth)

Spoiler


Next we adjust the points using the projection matrix to account for the aspect ratio of the viewport.
Spoiler


To get our world matrix we just need to invert our view matrix.
Once we have our world matrix we can get the direction of our ray by transforming the viewspace point with the world matrix and then normalize the resultant vector.
Spoiler


At this stage, we have an infinite number of positions in the world which will fall on this ray(depending on the value of t)

To get the exact point in the world we need the intersection of this ray with the viewing plane.
The viewing plane be defined by the plane equation
where N = (A, B, C) = the plane normal vector
k = Distance from the origin
Alternatively, the plane equation can be written as (2)
where Pp is the point on plane

To get the normal of our viewing plane in world space, we need the combination matrix of our view and projection matrix

Once we have our matrix M, the viewing plane normal is simply the normalized vector of (M._13, M._23, M._33)

When the plane and line intersect ,
Substituting (1) in 2, we get

Using distribution, we get

Solving for t, we get


Once we have t, we can plug it back in equation (1) to get the point in our world.

This ends this mini tutorial of converting our screen coordinates to world coordinates


Timing and FPS

Posted by , in Tutorial 07 May 2012 - - - - - - · 812 views

In this tutorial, we will learn how to create a timer to be used in our projects. We can use our timer for Creating a constant experience over multiple configurations, Calculating the FPS(Frames per second) etc.
The timer class will keep track of the Total Running Time, the time elapsed between 2 frames i.e between consecutive calls to Update and the FPS

ITimer Interface : Timer.hxx


Spoiler


cTimer Class : Timer.h


The cTimer class handles the creation of the timer
Spoiler


Implementation : Timer.cpp


Constructor: In the constructor, we check how many times per second the system counter fires by making a call to QueryPerformanceFrequency. We also set the FPS update interval to half a second because if we updated the FPS every frame, it would change too fast for us to see.
Spoiler

Destructor:
Spoiler

Create: This function Create and Returns an object of this class.
Spoiler

VStartTimer: This function starts the timer if it has not already been started by getting the current value of the high-resolution performance counter.
Spoiler

VStopTimer: This function stops the timer if it has not already been stopped and update the running time
Spoiler

VOnUpdate: This function Calculates the time elapsed since the last update call and updates the FPS and total running time.To calculate the FPS, we divide the frame counter by the time passed since the last time the FPS was calculated. Once the FPS is calculated, we reset the frame counter to 0.
Spoiler

VIsStopped: Returns true if the timer is stopped
Spoiler

VGetFPS: Returns the FPS
Spoiler

VGetRunningTime: Returns the running time
Spoiler

VGetRunningTicks: Returns the running ticks
Spoiler

VGetDeltaTime: Returns the elapsed time between frames
Spoiler

CreateTimer: Creates and returns a pointer to an object of this class
Spoiler


Using the timer


Spoiler



Initializing DirectX

Posted by , in Tutorial 17 April 2012 - - - - - - · 1,101 views

Now that we have created our window, we need to give it DirectX Capabilities, Again, since we will want to create only one instance of this class for each application we will create it as singleton. Even though on running the application we will just see a background color (TAN), we will have our DirectX device initialized and up for running. We will be able to Alt-Tab out of our full screen app or toggle between full screen and windowed mode

Setting Up the Project


The DXSDK installation defines the DXSDK_DIR environment variable which can be used to include all the directX files into our project.
for all configurations
In the Project Properties -> C/C++ -> Additional Include Directories add $(DXSDK_DIR)\Include (apart from all the include files) (for all configurations)
In the Project Properties -> Linker -> Additional Library Directories add ..\..\bin\;"$(DXSDK_DIR)\Lib\x86"
Debug Mode
In the Project Properties -> Linker -> Input-> Additional Dependencies add d3dx9d.lib DxErr.lib d3d9.lib winmm.lib dinput8.lib dxguid.lib
Release Mode
In the Project Properties -> Linker -> Input-> Additional Dependencies add d3dx9.lib DxErr.lib d3d9.lib dinput8.lib dxguid.lib winmm.lib

IDXBase Interface : DxBase.hxx


Since we dont need to expose all the functions to the rest of the world, we will just include a small subset in the interface. We will come to the purpose of each function in just a bit.
Spoiler


cDxBase Class : DxBase.h


The cDxBase class handles the creation of the directX device
Spoiler


Implementation : DxBase.cpp


Constructor
Spoiler

Destructor - Make sure the directX object and device are released
Spoiler

method Create - Creates an object of this class and returns it
Spoiler

method VOnInitialization - This is the first function that needs to be called since it is responsible for creating the directX object and device
Spoiler

method VOnResetDevice - Resets the device
Spoiler

method VBeginRender- This function clears the surface with the specified color and prepares it for rendering. This function must always be called before we render any geometry.
Spoiler

method VEndRender- This function displays what we just rendered to the screen .This function must always be called after we are done rendering
Spoiler

method VGetDevice
Spoiler

method VIsAvailable - This function checks whether the device is available for rendering or not. We need to call this function before we begin rendering
Spoiler

method VOnDestroy- Releases the DirectX object and deletes the singleton object
Spoiler

method VToggleFullScreen - Toggles between full screen and windowed mode
Spoiler

method DirectxInit- This function creates the Direct3D object. After creating the object, we get the system’s current display mode by calling GetAdapterDisplayMode which will be used when we create a fullscreen device. Then we check what the video card is capable of by calling GetDeviceCaps.
Spoiler

method CreateDirectxDevice - This function check if the hardware supports transformation and lighting and whether it supports a pure device. In the end, we create the directX device based on the parameters that we have filled and the hardware capabilities.
Spoiler

method SetParameters - This function fills out the D3DPRESENT_PARAMETERS structures depending on whether it is a full screen or windowed application. We also check which depth stencil format is supported by calling CheckDeviceFormat
Spoiler

method Cleanup - This function releases the directx device and object. SafeRelease is a special macro which releases the object if it not released
Spoiler


Running the code


The code needs to be added in the following functions
MainWindow.cpp
Spoiler


WinMain
Spoiler



Creating a Window

Posted by , in Tutorial 05 April 2012 - - - - - - · 808 views

Before we create our game, we first need to know how to create a window. Thanks to OOP's the code just needs to be written just once. Since we will want to create only one instance of this class for each application we will create it as singleton.

IMainWindow Interface : MainWindow.hxx


Since we dont need to expose all the functions to the rest of the world, we will just include a small subset in the interface. We will come to the purpose of each function in just a bit.
Spoiler

cMainWindow Class : MainWindow.h


The cMainWindow class is the main class that handles the window creation and controls the message loop.
Spoiler

Implementation : MainWindow.cpp


Constructor
Spoiler

method VOnInitialization
Spoiler

method VOnDestroy
Spoiler

method VToggleFullScreen - This method is used to toggle between windowed and full screen mode. We just need to set the appropriate style in the GWL_STYLE attribute of the window by calling SetWindowLongPtr.
Spoiler

method Create
Spoiler

method RegisterWin - Here, we need to define the window class by filling out a WNDCLASSEX structure. This structure tells Windows all the properties of the window that we want to create. The lpfnWndProc member is set to a function pointer that we will write later on. that has a specific function declaration:
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
When the program is compiled, another parameter is added to all non-static member functions, a this pointer, which changes the function declaration so it is incompatible with what is required for the lpfnWndProc member. Static functions on the other hand, do not receive this extra parameter, which is why we set the lpfnWndProc member to StaticWndProc. We register the window class for subsequent window class by calling RegisterClassEx
Spoiler

method CreateMyWindow - This function is responsible for creating the window. In the CreateWindow function, we can store any type of pointer we want in the last parameter(lpParam), such as a this pointer. Since our static window procedure does not have access to the "this" pointer, the "this" pointer which will be accessible during a WM_CREATE message, could be used to send messages meant for our application to a non-static window procedure, which would allow us to access the non-static data of our class. One of the attributes of all windows is a user-defined attribute, where we can store our this pointer in the user-defined attribute using the SetWindowLongPtr function with the GWLP_USERDATA offset flag
Spoiler

method StaticWndProc - With the this pointer stored with our window, we can access it in all subsequent messages with the GetWindowLongPtr. Once the pointer is retreived, we can cast the pointer to a cMainWindow pointer and access all the non-static functions of the class, such as the non-static window procedure. Using this, we route all messages to their corresponding non-static window procedure.
Spoiler

method OnWindowCreated - This function will be called after the window is created. All our resources will be created here
Spoiler

method WndProc - This function is used to process all our messages
Spoiler

method OnWindowDestroyed - This function will be called after the window is destroyed. All our resources will be released here
Spoiler

method SetDisplayResolution - This function sets the display settings of the monitor to the fullscreen width and height that has already been specified by filling the DEVMODE structure. ChangeDisplaySettings(NULL, 0) resets the display to the registry stored values
Spoiler

method GetInstance _ this function will create a cMainWindow object if it is not yet created and return a pointer to it
Spoiler

Running the code


The WinMain function is the entry point of all Windows programs. Here we initialize the window and on quit destroy the window
Spoiler

Updates


Edit 14 Apr 2012 : Added a fix in VToggleFullScreen so that other windows can come in front when we lose focus in windowed mode.


NonCopyable objects

Posted by , in Tutorial 22 December 2011 - - - - - - · 536 views

Sometimes, you don't want to encounter a situation where something made a copy of the object. In C++, a copy of an object can be made in a number of situations. The most obvious is direct assignment. Less obvious, but equally valid, is a function call using pass-by-value.

Copying in C++ is handled in two ways
  • the copy assignment operator; and
  • the copy constructor
Unfortunately, if the class definition does not explicitly declare a copy constructor or a a copy assignment operator, the compiler provides an implicit version which is a public member function.
Now, if we want to make a class noncopyable, we can simply define its copy constructor and copy assignment operator as private members. But, it makes more sense to have a noncopyable base class. If a class derives from the noncopyable base class, it too will be noncopyable, since the copy of an object of a derived class must necessarily invoke the copy constructor or copy assignment operator of the corresponding base class.
namespace Base
{   	
	class cNonCopyable
	{
	protected:
		cNonCopyable(){}
	private:
		cNonCopyable(const cNonCopyable&);
		cNonCopyable operator =(const cNonCopyable&);
	}
}

By making the copy constructor or copy assignment operator private, we ensure that the derived class is noncoyable as well. By just providing the declaration and not implementing them, we ensure that the compiler does not provide its own versions and a linking error is generated if they are used anywhere in the program.


Some Basic concepts

Posted by , in Tutorial 17 December 2011 - - - - - - · 440 views

DLL Basics


Since, we are going to be using dll's to have 1 single copy of our engine code, lets understand the basics of DLL's. For those of you, who are on the fence of whether to use a dll or not. Here are some of the advantages of using a dll as per MSDN

We will be using __declspec(dllexport) and__declspec(dllimport) to export and import functions, data and objects to and from a dll. We will mainly be using it to export/import functions or interface declarations and not member variables.

I prefer to have a header file which can encapsulate the above function calls. I will explain it with an example
#ifdef project_EXPORTS
#define project_API __declspec(dllexport)
#else
#define project_API __declspec(dllimport)
#endif
For the project from which we want to export functions, project_EXPORTS macro will be defined so that project_API automatically map to __declspec(dllexport). For all other projects project_API will map to __declspec(dllimport)

Now for whichever interface, we need to export all/the functions all we need to do is include the above header and add the following code
class project_API className
{
};
This takes care of exporting/importing all the functions, member variables in the class className.


Memory Leak Woes

Posted by , in Tutorial 16 December 2011 - - - - - - · 1,288 views

Finding Memory Leaks


If you are not a big company, chances are you cannot afford the commercial programs to check for memory leaks in your program.. This tutorial will give you a free alternative which you can add to your projects.

The 1st thing that we need to do is to include <crtdbg.h>. One thing to note is that crtdbg.h should be added after all the other header files

To make debugging easier, it would be nice if we could get the file and the line no which is causing the leak. Luckily, this can easily be done with some macro trickery
#ifdef _DEBUG
#define DEBUG_NEW   new( _NORMAL_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_NEW new
#endif
The _DEBUG macro is defined only for release builds so by encasing the code in #ifdef/#endif quotes, we can ensure that we dont get sub-par code with Release Builds.
_NORMAL_BLOCK is the ordinary memory allocated by our program. Alternatively, we can use _CLIENT_BLOCK which is a special type of memory block (typically used by MFC programs) for objects that require a destructor.
__FILE__ and __LINE___ are predefined ANSI C macros which return The name of the current source file and the line number the current source file respectively.
Now all of our new operator calls three parameter new calls with the __FILE__ and __LINE__ automatically inserted by the pre-compiler.

We can override the new and delete functions to add our own custom tracking methods. We just need to make sure they atleast do what the old new/delete operator functions did.

The only thing remaining is to set the debug flags to enable memory leak detection. Make sure you call this function at the start of your program
Spoiler


The _CrtSetDbgFlag function allows the application to control how the debug heap manager tracks memory allocations by modifying the bit fields of the _crtDbgFlag flag.OR'ing the current _crtDbgFlag flag with _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF and setting it, the program automatically calls _CrtDumpMemoryLeaks when the program exits.

The _CrtDumpMemoryLeaks function determines whether a memory leak has occurred since the start of program execution. When a leak is found, the debug header information for all the objects in the heap is dumped in a user-readable form.

If you do not set _CRTDBG_LEAK_CHECK_DF, you will need to call _CrtDumpMemoryLeaks yourself.

Additional Reading


You can read more about the different flags here

Coming Up


In the next tutorial, we will look at creating a window


Setting Up the Project - Part II (Project Properties)

Posted by , in Tutorial 15 December 2011 - - - - - - · 512 views

Now that we have decided the basic directory structure and dependencies that each project will have, we will now set the project properties. I prefer to do this at the project level so that the properties are persistent and I don't have to set them every time I download the project. The steps are based on Visual 2008 Professional, but you can adapt them to a different IDE as well

Setup the Main Exe Project

  • Create an Win 32 Project and delete all the files except for stdafx.h, stdafx.cpp (I named the project as Main)
    • Create a new folder called src and move the above files in there (I prefer all my source files in one main directory Posted Image)
  • In the property settings for the project perform the following steps
    • For Both Release and Debug Modes
      • In the tab C/C++ -> General -> Additional Include Directories add
        • "$(SolutionDir)Common\src"
        • "$(SolutionDir)Base\Includes"
        • "$(SolutionDir)Utilities\Includes"
        • "$(SolutionDir)GameBase\Includes"
        • "$(SolutionDir)Game\src"
    • For Debug Mode
        • In the tab Debugging -> Working Directory add
        • ..\..\Debug\
      • In the tab Linker -> General -> Output Directory add
        • ..\..\Debug\
      • In the tab Linker -> General -> Output File add
        • $(OutDir)/$(ProjectName)_D.exe
      • In the tab Linker -> General -> Additional Library Directories add
        • ..\..\Debug\
      • In the tab Linker -> Input -> Additional Dependencies add
        • Utilities_D.lib
        • Base_D.lib
        • Game_D.lib
  • For Release Mode
    • In the tab Debugging -> Working Directory add
      • ..\..\bin\
    • In the tab Linker -> General -> Output Directory add
      • ..\..\bin\
    • In the tab Linker -> General -> Output File add
      • $(OutDir)/$(ProjectName).exe
    • In the tab Linker -> General -> Additional Library Directories add
      • ..\..\bin\
    • In the tab Linker -> Input -> Additional Dependencies add
      • Utilities.lib
      • Base.lib
      • Game.lib

Setting up the DLL's

I will explain how to setup one of the lib projects which links to an extern library. Properties for all the other projects can be set in the same way by looking at the dependencies from the previous tutorial

  • Create an Win 32 Project but change the Application Type to DLL and delete all the files except for stdafx.h, stdafx.cpp (For tutorial purposes we will be setting up the Utilities project)
    • Create a new folder called src and move the above files in there
  • In the property settings for the project perform the following steps
    • For Both Release and Debug Modes
      • In the tab C/C++ -> General -> Additional Include Directories add
        • "Includes"
        • "..\Common\src"
        • "..\Base\Includes"
        • "..\..\extern\Include""
    • For Debug Mode
        • In the tab Linker -> General -> Output Directory add
        • ..\..\Debug\
      • In the tab Linker -> General -> Output File add
        • $(OutDir)/$(ProjectName)_D.dll
      • In the tab Linker -> General -> Additional Library Directories add
        • ..\..\Debug\
        • ..\..\extern\Lib\Zlib
        • ..\..\extern\Lib\TinyXml
      • In the tab Linker -> Input -> Additional Dependencies add
        • Winmm.lib
        • tinyxmld.lib
        • Base_D.lib
        • zlibwapi.lib
  • For Release Mode
    • In the tab Linker -> General -> Output Directory add
      • ..\..\bin\
    • In the tab Linker -> General -> Output File add
      • $(OutDir)/$(ProjectName).dll
    • In the tab Linker -> General -> Additional Library Directories add
      • ..\..\bin\
      • ..\..\extern\Lib\Zlib
      • ..\..\extern\Lib\TinyXml
    • In the tab Linker -> Input -> Additional Dependencies add
      • tinyxml.lib
      • Winmm.lib
      • Base.lib
      • zlibwapi.lib

Notes:

  • To point to the directx dir we can use the visual studio macro $(DXSDK_DIR)\Include
  • I use the suffix _D to distinguish between debug and release builds
  • For the most part, only the Include folder should be added in the additional include directories. Exceptions Being GameBase and Game

Final Thoughts

This finishes the initial setup. Since I am not sure, how much detail I should get into of why I setup my projects this way, I will be happy to answer any questions in the comments.

The next tutorial will deal with the common includes, macros and how to make the debugger check for Memory LeaksPosted Image




Setting Up the Project - Part I (Directory Structures)

Posted by , in Tutorial 14 December 2011 - - - - - - · 630 views

In this post I am going to cover the third party libraries, project breakup, and current directory structure that I follow. Even though its not perfect, its served me well so far

Third Party Tools

  • FMod - Sound
  • TinyXML - XML
  • Zlib - zip

Projects in the Solution

  • Common
    • Common includes, macros etc that should be included in every project
    • Dependencies - None
    • Project Includes - None
    • Additional Includes - None
    • Third Party Libraries - None
  • Base
    • common datastructures/classes such as wrappers for string
    • Dependencies - None
    • Project Includes - Common
    • Additional Includes - None
    • Third Party Libraries - None
  • Utilities
    • All Utility Functions such as Logger
    • Dependencies - Base
    • Project Includes - Common, Base
    • Additional Includes - Third Party includes (see extern below)
    • Additional Libraries - Winmm.lib tinyxml.lib zlibwapi.lib
  • AI
    • AI related Functionality
    • Dependencies - Base, Utilities
    • Project Includes - Common, Base
    • Additional Includes - None
    • Additional Libraries - None
  • GraphicsEngine
    • All Graphic related stuff
    • Dependencies - Base, Utilities
    • Project Includes - Common, Base, Utilities
    • Additional Includes - DirectX Includes
    • Additional Libraries - d3dx9.lib DxErr.lib d3d9.lib winmm.lib dinput8.lib dxguid.lib
  • Sound
    • Wrappers for playing sound (might move to Graphics Engine later)
    • Dependencies - Base, Utilities
    • Includes - Common, Base, Utilities
    • Additional Includes - Third Party includes (see extern below)
    • Additional Libraries - fmodex_vc.lib
  • GameBase
    • Functionality that needs to be setup every game
    • Dependencies - Base, Utilities, GraphicsEngine
    • Includes - Common, Base, Utilities, GraphicsEngine
    • Additional Includes - DirectX Includes
    • Additional Libraries - None
  • Game
    • GamePlay Logic (This project will be swapped for different games)
    • Dependencies - Base, Utilities, GraphicsEngine, GameBase, Sound
    • Includes - Common, Base, Utilities, GraphicsEngine, GameBase, Sound, AI
    • Additional Includes - DirectX includes
    • Additional Libraries - None
  • Main
    • The exe file
    • Dependencies - Base, Utilities, Game
    • Project Includes - Common, Base, Utilities, Gamebase, Game
    • Additional Includes - None
    • Additional Libraries - None

Directory Structure


For each Project I mantain 2 folders
  • Include
    • This folder contains all the interfaces for the respective project. This folder will be included in the all projects that are dependent on it. This way, the underlying implementations need not be released. It also reduces the compile time, if i change the implementation
  • Src
    • This folder contains all files for the actual implementation. Most of the classes would be inheriting from one of the interfaces in the Include folder

Final Thoughts

Now that we have the basic directory structure mapped out, the next tutorial will deal with actually setting up the project for the Visual 2008 environment.

Till Next TimePosted Image





December 2016 »

S M T W T F S
    123
456 7 8910
11121314151617
18192021222324
25262728293031

Recent Entries

Recent Comments

Latest Visitors