Category Archives: code

CGDataProviderCreateDirect

It’s hard to find an example using CGDataProviderCreateDirect, so here’s a quick snippet:

static unsigned int* data; // used for manipulating pixel data directly

const void * getBytePointerCallback(void *info)
{
	return (void*)data;
}

@implementation SomeView

- (void)createImage
{
    CGDataProviderDirectCallbacks callbacks;
    callbacks.version = 0;
    callbacks.getBytePointer = getBytePointerCallback;
    callbacks.releaseBytePointer = NULL;
    callbacks.getBytesAtPosition = NULL;
    callbacks.releaseInfo = NULL;
    
    float w = self.layer.frame.size.width;
    float h = self.layer.frame.size.height;
    
    w *= [UIScreen mainScreen].scale;
    h *= [UIScreen mainScreen].scale;
    
    int numComponents = 4;
    uint dataLength = w * h * numComponents;
    
    data = malloc(dataLength * sizeof(uint)); // TODO: free
    
    uint r = 255;
    uint g = 0;
    uint b = 0;
    for(int i = 0; i < dataLength; ++i)
    {
        data[i] = 255 << 24 | b << 16 | g << 8 | r;
    }
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
    CGDataProviderRef bitmapProvider = CGDataProviderCreateDirect(data,dataLength,&callbacks);

    CGImageRef bitmap = CGImageCreate(w,
                                      h,
                                      8,    // bits per component
                                      8*numComponents,  // total bits
                                      w*numComponents,  // bytes per row
                                      colorSpace,
                                      kCGBitmapByteOrderDefault,
                                      bitmapProvider,
                                      NULL,
                                      false,
                                      kCGRenderingIntentDefault);    
    
    self.layer.contents = (__bridge id)(bitmap);
    
    CGImageRelease(bitmap);
    CGDataProviderRelease(bitmapProvider);
    CGColorSpaceRelease(colorSpace);
}

couchdb reader_acl

I installed CouchDB 1.0.1 with MacPorts 1.9.1 and quickly ran into problems:

  • The ‘attachments’ test hung in Chrome 6.0.472.55. I ran the same test in Firefox 3.6.9 and it worked.
  • The ‘reader_acl’ failed with an exception.
  • I couldn’t create an admin.

The couchdb.log certainly had errors but I couldn’t find a solution online. I tried uninstalling the port and reinstalling with no luck. Eventually I gave up and downloaded CouchDBX. Creating an admin worked but it also had problems running the Test Suite (I had to Force Quit).

Then I tried Homebrew. After installation I ran the Test Suite with 100% success and was able to create an admin! Awesome, now I’ll just add org.apache.couchdb to launchctrl…hmm it’s not under /Library/LaunchDaemons or /opt/local/Library/LaunchDaemons. After a little digging I eventually found it under /usr/local/Cellar/couchdb/1.0.1/Library/LaunchDaemons/. Only a few steps remain:

  • Copy org.apache.couchdb.plist into /Library/LaunchDaemons
  • Change the value under the UserName key to your user short name (hint: look under /Users)
  • sudo launchctl start org.apache.couchdb or you can test it for sure by restarting (shortcut key: Control-Command-Eject)

Everything now appears to be in working order.

adding FLEX_HOME and building as3-signals on a mac

Fire up a terminal:

  • cd ~/Library/SDKs
  • git clone http://github.com/robertpenner/as3-signals.git

You can find the above url on the as3-signals homepage on github. My personal pref is to put 3rd party libraries under ~/Library/SDKs

If you look inside the as3-signals dir, there is a build.xml file which requires a FLEX_HOME variable to be set. So, I downloaded the Flex 4 SDK and dropped it under /Developer/SDKs/flex_sdk_4. In the terminal, we need to set the env variable FLEX_HOME. First, lets check if you have an existing one defined. In the shell, type

  • env

You should see a list of defined variables. If you need to remove an existing FLEX_HOME, you can do so by typing

  • export -n FLEX_HOME

Otherwise, you can add a new FLEX_HOME by typing:

  • FLEX_HOME=”/Developer/SDKs/flex_sdk_4″
  • export FLEX_HOME

If you type env again FLEX_HOME is now added to the list. Now we can build as3-signals.

  • cd ~/Library/SDKs/as3-signals/
  • ant

Ant looks for a build.xml by default. Upon a successful build you’ll find a .swc in the bin folder.

Note: Setting FLEX_HOME this way will only last for 1 terminal session. If you’d like a more permanent solution, see: http://mactip.blogspot.com/2004/04/setting-environment-variables.html

C# finite state machine (fsm)

Take a look at the following output:

The above output was generated by an Orc entity with an associated finite state machine (FSM). Although a FSM can be used for many things, in game development it’s typically used to model character behaviour. Why? It’s simple and easy to debug.

Let’s have a look at Main to get a high-level feel for using an Orc entity:


static void Main(string[] args)
{
    Orc o = new Orc();

    o.Event = OrcEvent.Wander;
    o.UpdateState();

    o.Event = OrcEvent.Eat;
    o.UpdateState();

    o.Event = null;
    o.UpdateState();

    Console.ReadLine();
}
 

In a real game loop the UpdateState method would be called once per frame. Continuing with a top-down approach, let’s see the components that make up an Orc entity. First, we find a enum to represent simple event identifiers.


enum OrcEvent
{
    Eat,
    Wander
}
 

Events can trigger a change in state. It’s possible to use a table to map events to associated states. For example, the OrcEvent.Eat maps to the EatState and the OrcEvent.Wander maps to the WanderState. However, states don’t always have a 1-to-1 correspondence. For example, an OrcEvent.SeeEnemy could map to an AttackState. Here we see a transition table specific to Orcs:


class OrcTransitionTable : Ai.StateTransitionTable
{
    public OrcTransitionTable()
    {
        base.table.Add(OrcEvent.Eat, new EatState());
        base.table.Add(OrcEvent.Wander, new OrcWanderState());
    }
}
 

The base type StateTransitionTable handles housekeeping chores for the table:


abstract public class StateTransitionTable
{
    protected Dictionary<object, IState> table = new Dictionary<object, IState>();

    public void SetState(object evt, IState state)
    {
        table.Add(evt, state);
    }

    public IState GetState(object evt)
    {
        Ai.IState i = null;

        try
        {
            i = table[evt];

        }
        catch (KeyNotFoundException)
        {
            return null;
        }

        return i;
    }
}

What exactly is IState? It’s an interface with 3 methods for state processing:


public interface IState
{
    void Enter(Entity e);
    void Execute(Entity e);
    void Exit(Entity e);
}
 

Each method takes an entity type as a parameter. When switching states, the Exit method is called for the current state. The new state’s Enter method is then called. The current state is then assigned the new state. Execute is called once per frame to perform state processing.


abstract public class Entity
{
    protected Ai.StateTransitionTable transitionTable = null;
    protected IState currentState = null;

    public void UpdateState()
    {
        if (currentState != null)
            currentState.Execute(this);
        else
            System.Diagnostics.Trace.WriteLine("zero state");
    }

    public object Event
    {
        set
        {
            if (value == null)
            {
                currentState.Exit(this);
                currentState = null;
                return;
            }

            IState i = transitionTable.GetState(value);

            if (i != null)
            {
                if (currentState != null)
                    currentState.Exit(this);

                currentState = i;
                currentState.Enter(this);
            }
        }
    }
}
 

Implementing an Orc entity is trivial:

  • Inherit from Ai.Entity
  • Set the transition table in the constructor
  • Start adding methods for the new character

class Orc : Ai.Entity
{
    static Orc()
    {
        transitionTable = new OrcTransitionTable();
    }

    public void Drool()
    {
        Console.WriteLine("drooling...");
    }
}
 

Of course, an entity will need a variety of states to transition to. To create a new state type implement the IState interface. For example, here are a few Orc-related states:


class EatState : Ai.IState
{
    public void Enter(Ai.Entity e)
    {
        Console.WriteLine("entering eat state");
    }

    public void Execute(Ai.Entity e)
    {
        Console.WriteLine("executing eat state");
    }

    public void Exit(Ai.Entity e)
    {
        Console.WriteLine("exiting eat state");
    }
}

class OrcWanderState : Ai.IState
{
    public void Enter(Ai.Entity e)
    {
        Console.WriteLine("entering wander state");
    }

    public virtual void Execute(Ai.Entity e)
    {
        Console.WriteLine("executing wander state");

        Orc o = e as Orc;

        if (o != null)
            o.Drool();
    }

    public void Exit(Ai.Entity e)
    {
        Console.WriteLine("exiting wander state");
    }
}

class CustomizedOrcWanderState : OrcWanderState
{
    public override void Execute(Ai.Entity e)
    {
        base.Execute(e);

        Console.WriteLine("unique orc personality here...");
    }
}
 

Those are the basics of implementing a finite state machine for character control. You can download the source code here.

game of life

Conway’s ‘Game of Life’ produces some interesting patterns from a few simple rules. This demo utilizes WPF with simple styling and animation.

One day I’ll have to learn how to record, edit, and post videos online. Until then, it’s nothing but a static screenshot for you:

You can download the source here.

win32 nostalgia

Remember the first time you learned Win32 programming? I thought I’d post a couple of old demos I made during my first encounter with Win32 many, many, years ago.

The above image is from the demo called Elasticity. Drag the square and then let it go. The square will snap back to the origin as if it were attached to an elastic band.

The next image is from the demo called Swarm. It tries to mimic a swarm of fruit flies chasing your cursor.

I cleaned up the source just enough so that it would run. You can download the source for Elasticity and Swarm here.

novo

Novo1.zip – “Lesson 101 – Box on a Plane” is the first sample in the PhysX SDK Training Programs. Here’s a screenshot of a DirectX port written in C++:

The first thing to do is download the PhysX SDK. After it’s installed, you’ll need to set the directory paths in Visual Studio for the include files:

The demo has standard first-person camera controls. Also, be sure to check out WM_KEYDOWN in the WindowProc for a list of other controls.

Novo2.zip – Lesson 102 – Sphere and Torque:

Novo3.zip – Lesson 103 – Capsule, Local Pose, and Center of Mass:

Novo4.zip – Lesson 104 – Convex Shapes and Anisotropic Friction:

Novo5.zip – Lesson 105 – The User Contact Report and the Contact Stream Iterator:

Novo6.zip – Lesson 106 – Static and Kinematic Actors. The screenshot doesn”t look like much, however, the user can control the middle cube (as a kinematic actor) bouncing it off the other actors.

file type associations

Applications typically have some type of project file format. For example, Maya saves scenes using a binary file:

This file type is associated with Maya, it has the .mb extension and a custom icon. Double-clicking the file will open it in Maya. Today, we’re going to associate TestApp with the .testapp extension:

To associate a file type, you need to do three things:

  1. Add the file extension and associated application to the registry.
  2. When double-clicking a .testapp file, determine whether an instance of the associated process is already running.
  3. If the application is already running, pass the file across process boundaries.

The first step is easy and makes use of the following Win32 functions to create and set entries:

  • RegOpenKeyEx
  • RegCreateKeyEx
  • RegSetValueEx

The code to create key/value pairs in the registry is straightforward. Therefore, I’m not going to list it here so please reference the source code included in today’s download.

After executing the registration code, you should have new keys under HKEY_CLASSES_ROOT with the following structure:

And a new TestApp key where we assoicate the file with a default icon (which is indexed at 0 as an embedded resource in the executable):

The executable to launch is set under the Command section, with %1 being the command line param:

Use RegEdit to verify the above entries after executing today’s demo. To execute RegEdit use the Run prompt:

Once the file associations have been added to the registry, the next thing to do is determine if an instance of TestApp is running. The Process class in the System::Diagnostics namespace makes this step trivial.

So how does one application communicate with another across process boundaries? Under Win32 you use named pipes. A pipe connects two ends together – a client and server. Under .NET, named pipes have been wrapped up in the System::Runtime::Remoting::Channels::Ipc namespace. An IpcChannel is used when one application needs to communicate with another application in a different process on the same machine.

However, before we look at inter-process communication (IPC) let’s have a look at class SimpleFile which represents our .testapp file format.


public ref class SimpleFile : public MarshalByRefObject
{
    public: delegate void LoadDelegate(SimpleFile^ simpleFile);
    private: LoadDelegate^ loadDel;

    public: event LoadDelegate^ LoadEvent
    {
        void add(LoadDelegate^ value)
        {
            loadDel += value;
        }

        void remove(LoadDelegate^ value)
        {
           loadDel -= value;
        }
    }
 

Remoting is used for communication between app domains. An app domain is a logical container for a .NET applciation and is often refered to as a “lightweight process”.

The same remoting mechanism is used between two app domains whether those app domains are in the same process, in different processes on the same machine, or different processes on different machines. Any type that wants to expose its availability across app domains must inherit from MarshalByRefObject or be serializable.

To keep things as simple as possible, the SimpleFile “format” only contains a single value, which is parsed and stored:


private: int ultimateAnswer;
public: property int TheAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything
{
    int get() { return this->ultimateAnswer; }
}

public: void Load(String^ filePath)
{
    XmlTextReader^ xtr = gcnew XmlTextReader(filePath);

    while( xtr->Read() )
    {
        if( xtr->NodeType == XmlNodeType::Element )
        {
            if( xtr->Name == "UltimateAnswer" )
            {
                xtr->Read();
                this->ultimateAnswer = int::Parse(xtr->Value);
            }
       }
    }

    xtr->Close();
    delete xtr;

    if (loadDel != nullptr)
        loadDel(this);
}
 

Here we see the value stored in the sample file foobar.testapp:

The constructor in the Form class is overloaded to accept an array of arguments:


public: Form1(array<String^>^ args)
{
    InitializeComponent();

    // - in this example, we register the file type associations every time
    //   the application runs (overwriting keys)
    // - however, you would normally do this only once as part of your
    //   installation process
    RegisterFileAssociations();

    // - cache any arguments passed from Main
    this->args = args;
}
 

If there were no arguments passed, the application is starting up for the first time.


private: System::Void OnFormLoad(System::Object^ sender,
                                 System::EventArgs^ e)
{
    // - application is loading for the first time
    if( args->Length == 0 )
    {
        RegisterService();
    }
 

The host or server has to tell .NET which object’s it’s willing to expose. These objects or well-known types are registered using the static method RegisterWellKnownServiceType of the RemotingConfiguration class.

The host also has to register a channel with ChannelServices. A channel will monitor a port and accept incoming calls, servicing those calls with a thread from the thread pool. The IpcChannel is a welcome addition because prior versions of .NET provided only the TcpChannel and HttpChannel for communication. Both TcpChannel and HttpChannel have associated overhead for the network stack regardless if the communication taking place is on the same machine or across a network. IPC provides a direct line, reducing overhead and increasing performance.


private: void RegisterService()
{
    BinaryServerFormatterSinkProvider^ serverProv = 
        gcnew BinaryServerFormatterSinkProvider();
    serverProv->TypeFilterLevel = TypeFilterLevel::Full;

    Hashtable^ properties = gcnew Hashtable();
    properties["portName"] = "SimpleFileServer";

    IpcChannel^ ipc = gcnew IpcChannel(properties, nullptr, serverProv);
    ChannelServices::RegisterChannel(ipc, false);

    RemotingConfiguration::RegisterWellKnownServiceType(
                                      SimpleFile::typeid,
                                      "SimpleFile.rem",
                                      WellKnownObjectMode::Singleton);

    file = (SimpleFile^)Activator::GetObject(
                                      SimpleFile::typeid,
                                      "ipc://SimpleFileServer/SimpleFile.rem");

    file->LoadEvent += gcnew SimpleFile::LoadDelegate(this,
                                                      &Form1::OnProjectFileOpen);
}
 

During server registration, a SimpleFile is activated and its LoadEvent is hooked up to the following:


private: delegate void InvokeDelegate(SimpleFile^ simpleFile);
private: void OnProjectFileOpen(SimpleFile^ simpleFile)
{
    // cross-thread op
    array<Object^>^ arr = { simpleFile };
    this->Invoke(gcnew InvokeDelegate(this, &Form1::ProcessFile), arr);
}

public: void ProcessFile(SimpleFile^ simpleFile)
{
    this->label2->Text =
        simpleFile->TheAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything.ToString();
}
 

Invoke is used to update the Form’s user interface. Execution has to take place on the caller’s thread to avoid a cross-thread exception.

Back to OnFormLoad, where a list of processes is then assembled. It’s possible the process was launched with a double-click on a .testapp file. If so, services need to be registered and a SimpleFile loaded:


array<Process^>^ processArray =
    Process::GetProcessesByName(Process::GetCurrentProcess()->ProcessName);

// application loading for the first time from a double-click on file
if( processArray->Length == 1 )
{
    RegisterService();

    SimpleFile sf;
    sf.LoadEvent += gcnew SimpleFile::LoadDelegate(this,
                                                   &Form1::OnProjectFileOpen);
    sf.Load(filePath.ToString());
}
 

Otherwise, a process is already running and SimpleFile needs to get its information across process boundaries. Here we see the client registering an IpcChannel and activating the well-known file (SimpleFile):


else if( processArray->Length > 1 )
{
    MessageBox::Show("Instance already running, passing args along");

    for each( Process^ p in processArray )
    {
        if( p->Id != Process::GetCurrentProcess()->Id )
        {
            try
            {
                IpcChannel^ ipc = gcnew IpcChannel("SimpleClient");
                ChannelServices::RegisterChannel(ipc, false);

                SimpleFile^ file =
                    (SimpleFile^)Activator::GetObject(
                                        SimpleFile::typeid,
                                        "ipc://SimpleFileServer/SimpleFile.rem");

                if (file == nullptr)
                {
                    MessageBox::Show("Failure to connect with remote server");
                    this->Close();
                }

                file->Load(args[0]);
                this->Close();
            }
            catch(Exception^ e)
            {
                MessageBox::Show(e->Message);
            }

        } // end if

   } // end for each

} // end else if
 

In summary, the application is now assoicated with a file type. Double-clicking the file will launch the app. If the app is already running, IPC will be used to pass the file info across process boundaries, allowing the application already running to open the file as a new “project”.

Build and run the demo once to associate the file type in the registry. If you don’t see a blue icon for “foobar.testapp”, hit F5 in the explorer window to refresh it. Shut down the application and then try double-clicking various files with the .testapp extension.

You can download the source here.