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 :)

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.

Wednesday, October 27, 2010

Simple collection that returns random objects based on a stored probabilities

Simple collection that returns a random object based on a probability(weight)
Add an object using the Add() function and use the Next() function to return a random object:

Here is a download link from Microsoft SkyDrive:

Random by probability/weight 

public class RandomByProbabilityCollection<T>
{
    /// <summary>
    /// The object you are pooling.
    /// </summary>
    private List<T> options;

    /// <summary>
    /// The inverse of the probability that object will be selected.
    /// </summary>
    private List<byte> probability;
    /// <summary>
    /// Inverse probability that the items had last SelectNext call.
    /// </summary>
    private List<byte> lastCallProbability;
    /// <summary>
    /// Currently selectable objects.
    /// </summary>
    private List<int> currentList;
    /// <summary>
    /// Objects that can't be selected now.
    /// </summary>
    private List<int> candidateList;
    /// <summary>
    /// Rendom number generator.
    /// </summary>
    private Random randomGenerator;

    /// <summary>
    /// Generate a new collection of items that can be selected based on a probability.
    /// </summary>
    /// <param name="initialSize">The initial size of the collection.</param>
    /// <param name="maxProbability">The maximum priority for an item.</param>
    /// <param name="maxExtraIterations">Extra iteration to try and load more then 2 items.</param>
    public RandomByProbabilityCollection(int initialSize, byte maxProbability, int maxExtraIterations)
    {
        probability = new List<byte>(initialSize);
        lastCallProbability = new List<byte>(initialSize);
        options = new List<T>(initialSize);
        currentList = new List<int>(initialSize);
        candidateList = new List<int>(initialSize);
        randomGenerator = new Random();

        this.max2Iteration = maxExtraIterations;
        this.maxProbability = maxProbability;
    }

    //Disabled items iteration step.
    private byte min = 1;
    //The maximum available priority.
    private readonly byte maxProbability = 75;
    //Maximum number of iteration used to discover atleast 2 comparable objects.
    private readonly int max2Iteration = 10;
    //Set the items iteration step.
    private void SetMin(byte current)
    {
        if (current < min && current > 0)
        {
            min = current;
        }
    }
    //Calculate the priority for a given item.
    private byte CalculatePriority(int probability)
    {
        int p = (probability > maxProbability ? maxProbability : probability);
        p = (maxProbability - p);
        return (byte)p;
    }

    /// <summary>
    /// Add an item to the collection.
    /// </summary>
    /// <param name="probability">The probability that this item will be selected 0 to 75.</param>
    /// <param name="obj">The object.</param>
    public void Add(byte probability, T obj)
    {
        byte p2 = CalculatePriority(probability);
        SetMin(p2);
        this.probability.Add(p2);
        this.lastCallProbability.Add(p2);
        this.candidateList.Add(this.probability.Count - 1);
        this.options.Add(obj);
    }

    //Check if there are any objects available for selection.
    private void CheckPosibility()
    {
        if (candidateList.Count > 0)
        {
            for (int i = 0; i < candidateList.Count; i++)
            {
                int theIndex = candidateList[i];

                if (probability[theIndex] == maxProbability)
                {
                    continue;
                }

                int lastProbability = lastCallProbability[theIndex];

                if (lastProbability < 1)
                {
                    lastCallProbability[theIndex] = probability[theIndex];
                    candidateList.RemoveAt(i);
                    currentList.Add(theIndex);
                    i--;
                }
                else
                {
                    if (lastCallProbability[theIndex] < min)
                    {
                        lastCallProbability[theIndex] = min;
                        continue;
                    }
                    lastCallProbability[theIndex] -= min;
                }
            }
        }
    }

    /// <summary>
    /// Select a random object from the collection based on it's probability.
    /// </summary>
    /// <returns></returns>
    public T Next()
    {
        if (options.Count < 1)
        {
            //throw new Exception("The collection is empty but you are trying to ge a value");
            return default(T);
        }

        if (options.Count == 1)
        {
            return options[0];
        }

        int skipCount = max2Iteration;
        while (currentList.Count < 2 && skipCount > 0)
        {
            skipCount--;
            CheckPosibility();
        }

        int overflowTest = 0;
        while (currentList.Count < 1)
        {
            overflowTest++;
            CheckPosibility();
            if (overflowTest > 100)
            {
                for (int i = 0; i < probability.Count; i++)
                {
                    if (probability[i] != maxProbability)
                    {
                        overflowTest = 0;
                        break;
                    }
                }
                if (overflowTest != 0)
                {
                    throw new Exception("All objects have a priority of 0, this function will never return");
                }
            }
        }

        int option = randomGenerator.Next(0, currentList.Count);
        int selectedIndex = currentList[option];
        candidateList.Add(selectedIndex);
        currentList.RemoveAt(option);
        return options[selectedIndex];
    }

    /// <summary>
    /// Remove an item from the collection based on it's index in the collection.
    /// </summary>
    /// <param name="index">The index of the item to remove.</param>
    /// <returns>True if an item was removed.</returns>
    public bool RemoveAt(int index)
    {
        if (options.Count > index)
        {
            int maxProbability = probability[index];
            this.probability.RemoveAt(index);
            int currentLastCallProbability = lastCallProbability[index];
            this.lastCallProbability.RemoveAt(index);

            if (currentLastCallProbability >= maxProbability)
            {
                this.currentList.Remove(index);
            }
            else
            {
                this.candidateList.Remove(index);
            }

            this.options.RemoveAt(index);

            for (int i = 0; i < currentList.Count; i++)
            {
                if (currentList[i] > index)
                {
                    currentList[i]--;
                }
            }

            for (int i = 0; i < candidateList.Count; i++)
            {
                if (candidateList[i] > index)
                {
                    candidateList[i]--;
                }
            }


            return true;
        }
        else
        {
            return false;
        }

    }

    /// <summary>
    /// Remove an item from the collection.
    /// </summary>
    /// <param name="obj">The item to remove.</param>
    /// <returns>True if an item was removed.</returns>
    public bool Remove(T obj)
    {
        int indexOfT = options.IndexOf(obj);
        return RemoveAt(indexOfT);
    }

    /// <summary>
    /// Clear the collection.
    /// </summary>
    public void Clear()
    {
        this.probability.Clear();
        this.lastCallProbability.Clear();
        this.currentList.Clear();
        this.candidateList.Clear();
        this.options.Clear();
    }

    /// <summary>
    /// Sets the capacity to the actual number of elements in the list,
    /// if that number is less than a threshold value.
    /// </summary>
    public void TrimExcess()
    {
        options.TrimExcess();
        probability.TrimExcess();
        lastCallProbability.TrimExcess();
    }

    /// <summary>
    /// Change priority on a item at a given index.
    /// </summary>
    /// <param name="index">The index of the item that you want to change probability for.</param>
    /// <param name="probability">The new probability.</param>
    /// <returns>True if changed.</returns>
    public bool ChangeProbabilityAt(int index, byte probability)
    {
        if (options.Count > index)
        {

            this.probability[index] = CalculatePriority(probability);
            if (this.currentList.Contains(index))
            {
                this.currentList.Remove(index);
                this.candidateList.Add(index);
            }
            return true;
        }
        return false;
    }

    /// <summary>
    /// Change priority on a item.
    /// </summary>
    /// <param name="index">The item that you want to change probability for.</param>
    /// <param name="probability">The new probability.</param>
    /// <returns>True if changed.</returns>
    public bool ChangeProbability(T obj, byte probability)
    {
        int indexOfT = options.IndexOf(obj);
        return ChangeProbabilityAt(indexOfT, probability);
    }

    /// <summary>
    /// Number of items in the collection.
    /// </summary>
    public int Count
    {
        get
        {
            return options.Count;
        }
    }

    /// <summary>
    /// Indexed return.
    /// </summary>
    /// <param name="index">The index of the object.</param>
    /// <returns>The object.</returns>
    public T this[int index]
    {
        get
        {
            return options[index];
        }
    }
}