Saturday, March 17, 2012

finally for c++



//finally for c++

//endofscope.h

#ifndef       __ENDOFSCOPE_H_
#define       __ENDOFSCOPE_H_

template<typename T>
struct __EndOfScope
{
       T func;

       __EndOfScope(T f):func(f){}

       ~__EndOfScope()
       {
              func();
       }
};

#define __EndOfScopeCONCATE(a,b) a##b
#define __EndOfScopeEOS(a,b) __EndOfScopeCONCATE(a,b)

/*
Call something when the scope ends.
*/
#define EndOfScope(function) auto __EndOfScopeEOS(eos,__LINE__) = function; __EndOfScope<decltype(__EndOfScopeEOS(eos,__LINE__))> __EndOfScopeEOS(eosCaller,__LINE__) (__EndOfScopeEOS(eos,__LINE__) );

#endif //__ENDOFSCOPE_H_



//main.cpp

#include <iostream>

void endOfScopeFunction()
{
       std::cout << "End of scope function" << std::endl;
}

int main(int argc, char* argv[])
{
       //call a lambda at the end of the scope.
       EndOfScope([&](){std::cout << "End of scope lambda" << std::endl;});

       //call a lambda at the end of the scope.
       auto a2 = [&](){std::cout << "End of scope lambda 2" << std::endl;};
       EndOfScope(a2);


       //call a functor at the end of the scope.
       struct endOfScopeFunctor
       {
              void operator()()
              {     
                     std::cout << "End of scope obj" << std::endl;
              }
       };
       EndOfScope(endOfScopeFunctor());


       //call a function at the end of the scope.
       EndOfScope(endOfScopeFunction);


       //This will be executed first.
       std::cout << "The rest of the main !" << std::endl;


       return 0;
}



Output :

The rest of the main !
End of scope function
End of scope obj
End of scope lambda 2
End of scope lambda

Monday, December 6, 2010

DDS from file on XNA 4.0

In XNA 4.0 the Texture.FromFile() and Texture.Save() methods where removed letting us with no option on directly loading or saving dds files in our applications, we can load dds files trough the content pipeline but for an editor or for any application/game where you can create or even add content dynamically this is simply not an option.
For this reason I created a small dds manipulation library for XNA 4.0, it can load almost any Directx9 dds type that containes a 2d texture a volume texture or a cube-map and it can save Texture2D,Texture3D and TextureCube with all the available XNA surface formats except for HdrBlendable.
It will load mip-maps only if the data contains a complete chain, this is for consistency with the rest of the XNA 4.0 framework, if an incomplete mip-map chain is discovered only the main surface will be loaded.


Save a Texture2D or a TextureCube as a dds to a file: 
DDSLib.DDSToFile("texture.dds", true, texture, false); 

Save a Texture2D or a TextureCube as a dds to a stream: 
DDSLib.DDSToStream(stream,0, true, texture); 

Load a dds from a file:
DDSLib.DDSFromFile("texture.dds", GraphicsDevice,true, out texture); 

Load a dds from a stream:
DDSLib.DDSFromStream(stream,0, GraphicsDevice,true, out texture); 

Get the size in bytes for a mip-map level: 
DDSLib.GetDataByteSize(texture, level)

DDS Formats it can read :
Dxt1,Dxt2,Dxt3,Dxt4,Dxt5,A8R8G8B8/Color,X8R8G8B8,R8G8B8,A4R4G4B4,
A1R5G5B5,R5G6B5,A8,FP32/Single,FP16/HalfSingle,FP32x4/Vector4,
FP16x4/HalfVector4,CxV8U8/NormalizedByte2/CxVU,
Q8VW8V8U8/NormalizedByte4/8888QWVU,HalfVector2/G16R16F/16.16fGR,
Vector2/G32R32F,G16R16/RG32/1616GB,B8G8R8,X8B8G8R8,A8B8G8R8/Color,L8,
A2B10G10R10/Rgba1010102,A16B16G16R16/Rgba64

DDS Formats it can write:
Dxt1,Dxt3,Dxt5,A8R8G8B8/Color,A4R4G4B4,A1R5G5B5,R5G6B5,A8,
FP32/Single,FP16/HalfSingle,FP32x4/Vector4,FP16x4/HalfVector4,
CxV8U8/NormalizedByte2/CxVU,
Q8VW8V8U8/NormalizedByte4/8888QWVU,HalfVector2/G16R16F/16.16fGR,
Vector2/G32R32F,G16R16/RG32/1616GB,A8B8G8R8,
A2B10G10R10/Rgba1010102,A16B16G16R16/Rgba64

It has support for cube-maps.
It has support for volume textures.

It is released under the MIT/X11 license as a result you can do whatever you want with it, you just have to mention me on the credits. 
If you download it you agree with the terms of the license. 

License :
You can download it from here : 
https://skydrive.live.com/redir.aspx?cid=58baf3506093b62a&resid=58BAF3506093B62A!192&parid=58BAF3506093B62A!156

Notes :
-For the A2B10G10R10 known in XNA as Rgba1010102 there is a problem the RED and BLUE masks are backwards from the actual data ordering, this is for consistency with XNA and Directx, if you try to open such files in an editor the red and blue channel might get changed with each other, but if you open them with the Directx Texture Tool or trough the XNA Content Pipeline they will look as they should.
-At some point I will release  a standalone c# dds reader for the gdi+.

If you have something to say live a comment here or send me an email on kiki_karon@yahoo.com
I hope the gods of coding watch over you :)

Saturday, December 4, 2010

Animation library for XNA 4.0



This is a simple animation library it offers animation blending, when changing animation or animation blending from multiple animations on the same set of bones.
It has a quaternion based implementation and a matrix based implementation, the matrix based implementation doesn't offer multiple animations on the same set of bones but unlike the quaternion implementation it has scale support;When used in code there should be no big difference.
It is time-based so it doesn't count if your game is playing at 60 frames/second or at 5000.

It is licensed under the MIT/X11 license so you can do what you feel with it you just have to mention my name on your credits.
If you download it you agree with the terms of the license.

It is on Microsoft SkyDrive :

Reference :
http://cid-58baf3506093b62a.office.live.com/self.aspx/.Documents/SkinningLib/v15/CommunistSkinning.rtf
 License:
http://cid-58baf3506093b62a.office.live.com/self.aspx/.Documents/SkinningLib/v15/LICENSE.txt
You can download it from here:
http://cid-58baf3506093b62a.office.live.com/self.aspx/.Documents/SkinningLib/v15/CommunistSkinning^_15d.zip

If you have something to say live a comment here or send me an email on kiki_karon@yahoo.com
I hope the gods of coding watch over you :)

Saturday, November 20, 2010

I decided to make a game(yay for me)

I started working on an engine on and off so this is not by far a from scratch experience.
I think it will be a Descent like game with a few mini-games for flavor and some rpg elements because in the end I'm a geek.
I know every game should start with a design document,because I worked in this industry for a long time, but as for the moment I haven't recruited anyone and I'm still coding the nonspecific stuff so I don't see the point of that, but when it will be made it will be published on this blog so you can show me how floded my ideas are.
I will base my work on xna 4.0 because I love C# and I have a lot of experience with directx.
I live in Romania that means I wont be able to sell my game on xbox live arcade indi(that makes me angry), so I'm going to make a PC game.
I will post my progress as this experiment continues.
Here is the first screen-shot from the my world/game-play editor:

Tuesday, November 9, 2010

The Depth Buffer(Z-Buffer) and it's precision problems

Introduction to the problem :

-The first thing that any graphics programmer will start cursing is the depth buffer, and this is because of it's precision and the leak of understanding on how it works.
-Setting the bit depth is a straight forward process,select the biggest depth buffer available that feats in your video memory plane.
-Creating the projection matrix,specifically setting the near and far planes is a little more challenging,because the leak of math education + some leek of knowledge on how computer works makes a noob programmer to set the near planes at 0.000001f and far planes at 9999999,this is a bad thing,because the z-buffer advertises as something that it is not; when you are setting the near and far plane you are not just setting your convenient frustum but also it's compression, I will talk more about this later.
-The other element that is hard for beginners to understand is that in computer programming like in any real application made in this universe the real number is a pipe dream,floats and double look like they have a place in continues mathematics but they are just convinces over discreet mathematics.
  
The core of the problem :

-First let's look at the bit depth and it's meaning, depth buffer come in many flavors, in recent video cards the selection was reduced but we steal have a few :
                      +15bit, that's 32768 discrete values(as in the 16bit depth buffer with 1 bit stencil).
                      +16bit, that's 65536 discrete values(as in the standard 16bit depth buffer and the 24bit depth buffer with 8bit stencil).
                      +24bit, that's 16777216 discrete values(as in the standard 24bit depth buffer and the 32bit depth buffer with 8bit stencil).
                      +32bit, that's 4294967296 discrete values.
When you see this values you will probably say yawn that's a lot of discreet values,but there is another catch, the depth buffer DOES NOT HAVE A LINEAR DISTRIBUTION, almost all the values are in the first 10% of the interval, it has almost a hyperbolic distribution.
Lets see some examples :
-For a 32 bit depth with the z-near at 0.1f and the z-far at 100 we will have
               at                             z-buffer value                 error
              0.25                         2579559936    0.00000000014537363
              0.2505                     2582992440    0.000000000145955692
              0.26                         2645702437    0.000000000157236113
              1.00                         3869339904    2.325978E-9
              4.00                         4191784896    0.00000003721565
              10.00                       4256273894    0.000000232597813
              20.00                       4277770227    0.0000009303912
              80.00                       4293892476    0.0000148862573
              90.00                       4294489597    0.00001884042
              99.00                       4294923866    0.0000227969067
              99.0005                   4294923888    0.0000227971377
              100.00                     4294967293    0.0000232597758

Here is a graph representing the error as it grows (at the bottom of the page there is a link for a depth error calculator that I made):











Can you spot the problem, the difference between 0.25 and 0.2505 is of 0.0005 units in the 3d world but the difference in the depth buffer is of 3432504 units, now let's see
between 99 and 99.0005 in 3d space logic dictates that it will also be 0.0005 units but in the z-buffer the difference is only of 22.

-For a 16 bit depth buffer the situation is a lot more tragic :
               at                             z-buffer value                 error
             0.25                              39360                  0.000009526843
             0.2505                          39413                  0.00000956498752
             99                                65535                  1.47180724
             99.0005                        65535                  1.471822










-For 15 bits I won't even show you the numbers(but you can calculate them yourself with the calculator that you can download at the bottom of this page):










As you can see near the z-far we can't even distinguish values.
And I hope you noticed that at 0.25 we stored 39360 and our full precision is 65563 more then half of our precision is in the first 0.25 units of our depth !!!!
  
Why we have the problem 


-After the projection matrix transforms the coordinates, the XYZ-vertex values are divided by their clip coordinate W value, which results in normalized device coordinates. This step is known as the perspective divide. The clip coordinate W value represents the distance from the eye. As the distance from the eye
increases, 1/W approaches 0. Therefore, X/W and Y/W also approach zero, causing the rendered primitives
to occupy less screen space and appear smaller.This is how computers simulate a perspective view.
As part of the perspective divide, Z is also divided by W. For objects that are already close to the back of the view volume, a change in distance of one coordinate unit has less impact on Z/W than if the object is near the front of the view volume.What you should realize is that because of this the z is not linear in precision and it's precision is proportional with the reciprocal of   (zFar / (zFar - zNear) + zFar * zNear / (zNear - zFar)) / z as a result we have a but load of precision near the camera and almost no precision at the far plane.The perspective divide, by its nature, causes more Z precision close to the front of the view volume than near the back.Half of the resolution of the z-buffer is "wasted"(read used) for the first 5% of the interval between the near and far planes.
This is not such a bad thing if you think about it,because you need more precision where the action lies near the camera, but this is something that you have to understand and work in your design.

-The depth buffer compression, when the depth is stored, it must be feted in 15,16 or 32 bits so : 
int storeZ = Math.Floor((1 << resolution) * depth); 
where the resolution is how many bits we have to spare for the precision.

-In Directx you don't have direct access to the depth-buffer as a result video card manufacturers use unicorn magic in the compression algorithms because of this the precision may be slightly smaller then you expect or the distribution may have a different shape then you expect on some devices so always use a hysteresis.

Possible solutions

-Understand that there is no magic bullet here(some people that work in the game industry still think there is)
-You can't have a depth buffer that will draw with high precision objects near the camera and objects far away,you must compromise.
-For huge distances you can use a logarithmic depth buffer, a technology made by the SGI people, where basically you want to simulate a logarithmic curve in your depth buffer, this is a god technique as it spreads the precision a little bit better(I will have a post about it),as an side-effect of the logarithmic evolution you will start having problems with the polygons that are near the camera especially if you have big polygons.
-The best thing you can do is to keep you near plane as far as possible from the camera and your far plane as close as possible, this is because the z-buffer distribution is almost hyperbolic, as a result if you compress it, it will become more linear, example of the error curve :
For 16bit depth buffer from 0.1 to 100











For 16bit depth buffer from 0.5 to 100









As you can see the error was reduced dramatically just by taking the near plane closer to the camera.

Remember
-The clip coordinate W after perspective transform  represents the distance from the eye.
-The clip coordinate Z represents the distance from the eye corrected by the perspective transform.
-The z-buffer contrary to it's name doesn't hold the z value but the z/w value.
-Near plane as far as possible without compromising the quality of your game.
-Far plane as close as possible without compromising the quality of your game.
-The z-buffer is discreet, you don't have an unlimited number of values, it can only grow with fixed increments of approximately 1/(2^number_of_bits - 1).
-Try not to use stencil buffers, every bit counts.
-If you need to render depth in to a texture don't save the z component save the z/w because in the depth buffer we need normalized device coordinates, that's coordinates that can be feted in to axis aligned bounding box with the min in [-1,-1,0] and max in [1,1,1],also don't do the division operation in the vertex shader, do it in the pixel shader because z and w don't change proportionally, if you don't have a very tessellated mesh you will encounter problems.
-Perspectiv ecuations :
z' =  z*(zf/zf-zn)-((zn*zf)/zf-zn)
w' = z
where z',w' are clip space coordinates, z is a camera space coordinate,zn is the near plane and zf is the far plane.
-In Directx you don't have direct access to the depth-buffer as a result video card manufacturers use unicorn magic in the compression algorithms because of this the precision may be slightly smaller then you expect or the distribution may have a different shape then you expect so always use a hysteresis.
 
-As a bonus because you used your precious time to read this article I uploaded a depth-buffer error calculator so you can calculate your near and far planes with more ease :












It's pretty straight forward to use, simply type in your near plane, your far plane, the biggest error that you are interested in and your bit depth and you will get a graph that you can sample presenting the error as you approach the far plane.

Here is the download link it's on Microsoft SkyDrive so if you have an account and you are not logged you may not see it, it was written in c# .net 4.0 and you will need at least .net 4.0 client framework installed, you also have the source there :


If you want to know more about the history of the depth buffer, see this article on Wikipedia and know that the guy who invented it was Edwin Catmull, the guy who also invented the Catmul-Rom spline and the Catmul-Clark subdivision also known as Mesh-Smooth,Sub-D or NURMS.



Thanks for reading,hope it was a useful experience for you, leave a comment if you think something is not write, or if you enjoyed it and good coding :)





Thursday, November 4, 2010

Targeting Reach and HiDef PCs with the same XNA 4.0 Game

I will present a short implementation on what I consider to be an easy way for a Windows PC XNA 4.0 game that can adapt on what assets to load based on the available video-card.

You can make a game that sets the proper profile with just a few lines :
-First make sure that that you set the Reach profile for your Game, in the property tab.








-Next in your Game constructor after the GraphicDeviceManager was created handle the .PreparingDeviceSettings event on the newly created device manager.


 graphics = new GraphicsDeviceManager(this);
 //This event is called when the device is created,reseated or recreated so it's the perfect place to set the profile.
 graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings);

-In the handling function simply iterate trough all the available devices and select the one that satisfies your needs.

#if !FORCE_REACH
   for (int i = 0; i < GraphicsAdapter.Adapters.Count; i++)
   {
      if (GraphicsAdapter.Adapters[i].IsProfileSupported(GraphicsProfile.HiDef))
         {
             e.GraphicsDeviceInformation.Adapter = GraphicsAdapter.Adapters[i];
             e.GraphicsDeviceInformation.GraphicsProfile = GraphicsProfile.HiDef;
             IsHiDef = true;
             return;
         }
   }
#endif

for (int i = 0; i < GraphicsAdapter.Adapters.Count; i++)
   {
      if (GraphicsAdapter.Adapters[i].IsProfileSupported(GraphicsProfile.Reach))
      {
         e.GraphicsDeviceInformation.Adapter = GraphicsAdapter.Adapters[i];
         e.GraphicsDeviceInformation.GraphicsProfile = GraphicsProfile.Reach;
         IsHiDef = false;
         return;
      }
}

-To work around the fact that we can't have ContentProjects with different profiles we can create little projects with different profiles that reference the content projects specific for each content type and reference those project in our main game.

That's all you have to do, now if you want to simplify the way you load content and not bother with the type of the content you are loading you can create a ContentManager that is aware of the current GraphicProfile, for this :
-Create a new class that inherits from  ContentManage.
-Create a new constructor that takes as parameters an instance of the IServiceProvider and 3 strings for the different kind of assets we need(Common,HiDef and Reach)

public ContentManager2(IServiceProvider services, string commonAssetRoot, string hiDefAssetRoot, string reachAssetRoot)
   : base(services)
{
   this.commonAssetRoot = commonAssetRoot;
   this.hiDefAssetRoot = hiDefAssetRoot;
   this.reachAssetRoot = reachAssetRoot;
}
-Then create a method that can detect if the current device is a HiDef device.

private IGraphicsDeviceService graphicsDeviceService;
private bool? usingHiDeffDevice;
/// <summary>
/// Returns true if the current graphic device supports the HiDef profile.
/// </summary>
public bool IsHiDef
{
   get
   {
      if (graphicsDeviceService == null)
      {
         graphicsDeviceService = this.ServiceProvider.GetService(typeof(IGraphicsDeviceService)) as IGraphicsDeviceService;
         if (graphicsDeviceService == null)
         {
            throw new Exception("No GraphicDevice available!!!");
         }
      }

      if (usingHiDeffDevice == null)
      {
         usingHiDeffDevice = graphicsDeviceService.GraphicsDevice.Adapter.IsProfileSupported(GraphicsProfile.HiDef);
      }

      #if FORCE_REACH
         return false;
      #endif

      return usingHiDeffDevice.Value;
   }
}

-Next we need to change the Load() method.
public override T Load<T>(string assetName)
{
    try
    {
        return base.Load<T>(commonAssetRoot + "\\" + assetName);
    }
    catch
    {
        if (IsHiDef)
        {
            return base.Load<T>(hiDefAssetRoot + "\\" + assetName);
        }
        else
        {
            return base.Load<T>(reachAssetRoot + "\\" + assetName);
        }
    }
}
 -We will have to change the default ContentManager that comes with the Game class with ours so in the Game class constructor we will.
Content = new ContentManager2(this.Services, "Common_Content", "HiDef_Content", "Reach_Content");
-And we are done now if we need an asset we will load it like with a standard ContentManager

-Here is a project set using what I was talking about, it's on SkyDrive so if you have an account and you are not logged you might not see it :

MultipleTargetProject 

-To force the  load in Reach profile you must define FORCE_REACH :








-As a last note if you use this method always test your game with and without forcing the Reach profile.