Thursday, December 06, 2007
3D Engine Design
Following is the "table of contents" of the Lightfeather 3D engine design:
Wednesday, November 28, 2007
Talk like an animal, walk like an animal ...
The new download link on windowsclient.net is this one https://windowsclient.net/downloads/folders/starterkits/entry1269.aspx
Browsing through MSDN has surfaced that Tom Anderson did a VB.NET port of Terrarium from .NET framework version 1.x to 2.0. You will find the respective MSDN post here
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=373738&SiteID=1
Unfortunately, he has stopped working on the project and there is no visible link to me where one can grab the .NET 2.0 port of Terrarium.
Maybe there is some time left to play around a bit ...
Saturday, October 06, 2007
Newbie on the CCR Road
This post is about the CCR part of MRS, in particular I am going to do some simple examples about ports and a simple arbiter the Receiver.
CCR components use ports to communicate with each other. Just like a human being uses speech, verbal speech, or mimicry to communicate, so do CCR components use ports to communicate with each other. Ports are used to
- Send a message to a particular receiver.
- Receive a message from a particular sender.
In terms of CCR port, we have to define how the message, looks like that our port is going to receive. For this, we have to define the message's underlying data type or more precisely we have to create a port, which receives a message with some particular data type.
Port<string> stringPort = new Port<string>();
This creates a new port, which is able to send and receive message of type string. Now, that we have defined our port, how are do we send a message? Nothing simpler than that, the port offers an instance method Post. This method accepts a formal parameter item of type string. So the canonical "Hello World" example looks like this
stringPort.Post("Hello World");
This passes the item of type string with value "Hello World" to our stringPort, where it waits to be taken from the port for whatever one wants to do with it. To illustrate that the sent item is really "sitting" on the stringPort, we could simply do the following:
if (inputPort.ItemCount > 0)
{
string item = inputPort.Test() as string;
if (!string.IsNullOrEmpty(item))
{
Console.WriteLine("Item: " + item);
}
}
This shows two things. The first (1) being, that you may query the number of items waiting on some port by the ports field ItemCount and the second (2) being that you may test the port for the presence of items. If there is one ore more items on the port, then Test will return this item as an object and remove it from the queue of available items. Fortunately, the removal of an item is an atomic process, so that we won't going to race condition hell.
At times you may want to be able to send and receive more than just one item on some port. Therefore, the CCR offers a so called PortSet, which is just that a set of Ports. For example, to create a PortSet accepting a string and DateTime message, we would do the following:
PortSet<string, DateTime> messageDateTimePort = new
PortSet<string, DateTime>();
To avoid passing ports around in some program and taking individual items of some port, the CCR offers arbiters. Arbiters coordinate incoming messages passed between ports. In order to not manually call the Test method on the stringPort, we are going to declare a so called Receiver, which will be active whenever an item is waiting on a port matching the Receiver's signature. For example,
Receiver<string> stringReceiver = new
Receiver<string>(
true,
stringPort,
null,
new
IterativeTask<string>(MessageHandler));
this creates a Receiver, which accepts string items waiting on stringPort. The first parameter with value true sets persistence to true for this receiver. This means that the Receiver continues to receive string items even after it has received one string item. The null value is passed to the constraints formal parameter and the last parameter wires up a message handler, which actually takes care of string items incoming from stringPort. The MessageHandler function is nothing special (of course, you are free to add your own logic to it) and looks like this
private static
IEnumerator<ITask> MessageHandler(string message)
{
Console.WriteLine("Received Message: " + message);
yield break;
}
To make things complete, a small sample illustrates the previous things. The example creates a simple string port, which is used by a secondary thread to to send the current time to. This message is received by a Receiver arbiter and printed out to the console. The program terminates if the user presses any key. In this case we stop the secondary thread and simple exit the program.
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Microsoft.Ccr.Core;
namespace CCRTest5
{
class Program
{
private static bool running = false;
static void Main(string[] args)
{
Console.WriteLine("CCRTest5 - send to a message port and use arbiter to receive");
Port<string> stringPort = new
Port<string>();
Console.WriteLine("Created Port<string>");
Thread messageThread = new Thread(new
ParameterizedThreadStart(AddItemFunc));
Receiver<string> stringReceiver = new
Receiver<string>(
true,
stringPort,
null,
new
IterativeTask<string>(MessageHandler));
Console.WriteLine("Created Receiver");
Console.WriteLine("Starting Arbiter");
Arbiter.Activate(new
DispatcherQueue(), stringReceiver);
Console.WriteLine("Starting AddItem Thread");
messageThread.Start(stringPort);
Console.WriteLine("Press key to exit");
Console.ReadLine();
//abort
running = false;
Thread.Sleep(500);
if (messageThread.ThreadState == ThreadState.Running)
{
try
{
messageThread.Abort();
}
catch { }
}
}
private static
IEnumerator<ITask> MessageHandler(string message)
{
Console.WriteLine("Received Message: " + message);
yield break;
}
private static void AddItemFunc(object port)
{
running = true;
Port<string> messagePort = port as
Port<string>;
while(running)
{
messagePort.Post(DateTime.Now.ToString());
Thread.Sleep(500);
}
}
}
}
More on arbiters and CCR in the next post.
Thursday, September 27, 2007
A simple GreatestCommonDivisor service in C# - Part2
Firstly, we have to (1) declare that our service supports the HTTPQuery operation, secondly we have to (2) implement a handler for this HTTPQuery request, and thirdly we may (3) test the service with a browser.
1.
Just add the HTTPQuery port to the GCD service's port set, which is defined in GCDTypes.cs (assuming that your service is named GCD).
[ServicePort()]
public class GCDOperations : PortSet<..., HttpQuery, ...>
{}
So now that we have declared that our service is capable of understanding a HttpQuery action, we need to implement a routine, which handles such HttpQuery requests - a HTTPQueryGCDHandler.
2. Add the following lines to the GCD.cs
[ServiceHandler(ServiceHandlerBehavior.Concurrent)]
public virtual IEnumerator HTTPQueryGCDHandler(HttpQuery httpQuery) {
if (!string.IsNullOrEmpty(httpQuery.Body.Query["Action"]) &&
httpQuery.Body.Query["Action"] == "GCD")
{
string _M = httpQuery.Body.Query["M"];
string _N = httpQuery.Body.Query["N"];
int _intM = 1;
int _intN = 1;
if (!Int32.TryParse(_M, out _intM))
{
this.LogError("Failed to parse M");
httpQuery.ResponsePort.Post(
new HttpResponseType(new GcdtestState(-1)));
yield break;
}
if (!Int32.TryParse(_N, out _intN))
{
this.LogError("Failed to parse N");
httpQuery.ResponsePort.Post(
new HttpResponseType(new GcdtestState(-1)));
yield break;
}
int _GDC = this.ComputeGCD(_intM, _intN);
this.LogError("GDC = " + _GDC);
httpQuery.ResponsePort.Post(
new HttpResponseType(new GcdtestState(_GCD)));
}
else
{
this.LogError("Action is not GDC");
httpQuery.ResponsePort.Post(
new HttpResponseType(new GcdtestState(-1)));
}
yield break;
}
Besides computing the greatest common divisor and returning it as a http response, this handler does not do too much. It analyses whether the passed Action equals GCD and if so it tries to take the (hopefully) supplied parameters M and N. The service uses M and N to compute their GCD and if successful, passes the result back. If an error occurs, this service returns -1. The handler does not update the service's internal GCD state because of the following recommendation from the MRS help :
"As both GET and QUERY requests are defined by DSSP as not having any
side-effects, GET and QUERY handlers should be marked as
ServiceHandlerBehavior.Concurrent using the ServiceHandler attribute so that the
infrastructure knows that these handlers can run concurrently. "
3.With the handler in place, we may test our service. So we execute it by opening a browser and typing in the following URL
http://localhost:50000/GCD?Action=GCD&M=15&N=3
and this will return the correct result of 3. Note, that depending on you configuration the port and service name might be different. In fact, in the previous tutorial the service's name was GCDService, so you might want to take this into consideratio.
Although this was only a minor sample, I am trying to do something more meaningful with DSS and I hope to provide another small tutorial soon. So read you soon.
Christian
Saturday, September 15, 2007
A simple GreatestCommonDivisor service in C# - Part 1
Based on this description of what the service does, the remainder of this post will guide you through the process of how I built such a rather simple DSS service using the MRS object model and C# as implementation language (as mentioned you could also choose VB.NET, C++).
This kind of tutorial is divided into distinct steps beginning at creating a new service project to the final result being the service we want.
- Create new DSS Service
The first thing one has to do in order to set up a basic GreatestCommonDivisor service is to create a new DSS service.We will do so by creating a new Visual Studio 2005 Project. More specifically it is a "Simple DSS Service (1.5)" project (it is assumed that you have MRS 1.5 installed). Select the mentioned project type and name it as you please (e.g., "GCDService") (see here for more detail). This will create a file for the service (e.g., GCDService.cs) a manifest file (e.g., *.manifest.xml) and a file for the types used by the service (e.g., GCDServiceTypes.cs). - Define what is the objective of the service
The service should do nothing special, just compute the greatest common divisor of two non-negative integer numbers m and n.This can be easily accomplished via euclids algorithm. In a previous post about python, I gave a recoursive implementation for this algorith, which is why I won't do it here again. So let us assume we have built a function, which implements euclids algorithm. The function's signature might look like thispublic static int ComputeGreatestCommonDivisor(int m, int n)
{/*function's implementation not shown*/} - Define the input message
A DSS Service accepts input messages of some form coming from some input port, handles these messages and sends some output message as a response to its ouput port. For example, to get information about the state of a DSS service, this service has to handle a Get request, i.e. a "Get" message sent to the input port of this service. The DSS service receives the "Get" message does something and might respond to this message by sending "Hello World" as answer to its output port.
Similarly, our "GreatestCommonDivisor" service might get a request to compute the greatest common divisor (GCD) of two non-negative integer numbers n and m. Therefore, such a request might incorporate the n, and m sent to our service and the expected response might be the GCD of m and n. Consequently, we have to define such a request or how such a GCD message must look like to be accepted as GCD message by our service and to be handled appropriately. The following lines of code, which we add to the types source code file (e.g., GCDServiceTypes.cs), define such a GCD request
[DataContract(Name="ComputeGreatestCommonDivisor")]
public class ComputeGCDRequest
{
private int _inputX;
[DataMember(IsRequired = true, Name = "InputX")]
public int InputX
{
get { return (this._inputX); }
set { this._inputX = value; }
}
private int _inputY;
[DataMember(IsRequired = true, Name = "InputY")]
public int InputY
{
get { return (this._inputY); }
set { this._inputY = value; }
}
public ComputeGCDRequest()
{
this.InputX = 1;
this.InputY = 1;
}
public ComputeGCDRequest(int x, int y)
{
this._inputX = x;
this._inputY = y;
}
}
The ComputeGCDRequest defines how a request to our service has to look like. It defines m and n (InputX, InputY). Each request has to be marked with the DataContractAttribute attribute, so DSS can wire things up for us. Fields we want to incorporate in our request have to be marked with DataMemberAttribute attribute (those fields are part of the message serialization process when the ComputeGCDRequest message is serialized over some channel). These two attributes take some optional arguments such as "Name" and "IsRequired". - Define a message handler for the input message
The sheer presence of such a GCD request message type won't bring us far. We have to do define a GCD request (I), and add this GCD request to list of requests understood by our service (II). Afterwards we have to set up a mechanism that whenever a GCD request is issued to our service, takes the message, which abstracts this request and acts accordingly (III). So defining a GCD request serive, involves defining what the incoming GCD request message body looks like and defining what the result of processing a GCD request is, may it be success or failure. The following lines of source code, added to the GCDServiceTypes.cs, define a ComputeGCD request type ...
public class ComputeGCD :
Query<ComputeGCDRequest, PortSet<GCDState, Fault>>{
public ComputeGCD(int m, int n) :
base(new ComputeGCDRequest(m, n))
{
this.Body.InputX = m;
this.Body.InputY = n;
}
public ComputeGCD() :
base()
{ }
}
The ComputeGCD request type, subclasses the Query<> type, and defines the incoming message to be our previously declared ComputeGCDRequest message and the result will be a GCDState on success and the pre-defined Fault on failure. A Portset is a collection of ports (a set of ports) and a port is just an abstraction that allows services to communicate with each other. So to signal that our GCDService actually understands the ComputeGCD type, we have to add this type to the GCDService service's operations port set, which is defined in the GCDServiceTypes.cs file.
[ServicePort()]
public class GCDServiceOperations :
PortSet<DsspDefaultLookup, DsspDefaultDrop, Get, ComputeGCD>
{}
Now that our GCDService declares being able to understand GCD requests, we have to make him do so. More specifically we have to set up a message handler that jumps in whenever a GCDRequest is sent to our GCDService. The following lines of code, added to the GCDService.cs will be in charge of this.
[ServiceHandler(ServiceHandlerBehavior.Exclusive)]
public virtual IEnumeratorComputeGCDHandler(ComputeGCD computeGCD)
{
int M = computeGCD.Body.InputX;
int N = computeGCD.Body.InputY;
int gcd = ComputeGreatestCommonDivisor(M, N);
this._state.GCD = gcd;
LogInfo("=========\r\nGcdTest\r\n=========");
LogInfo(string.Format("M = {0}\r\nN = {1}\r\nGCD= {2}",
computeGCD.Body.InputX,
computeGCD.Body.InputY,
this._state.GCD));
computeGCD.ResponsePort.Post(new GCDState(gcd));
yield break;
}
The ComputeGCDHandler handler takes the ComputeGCD request as input and unwraps the necessary InputX and InputY fields from message's body. It then uses these two numbers as input to our ComputeGreatestCommonDivisor method, which computes the greatest common divisor and stores it in the gcd parameter. This gcd parameter is stored into the state of the service, which is of type GCDState. This GCDState encapsulates the state of the service, which is the greatest common divisor computed by the service. Actually the state is not really necessary, because we don't do much with it. At last, the message handler outputs the result of the operation to the output port for success, which was of type GCDState. The LogInfo calls are merely for debugging. Since this service alters its internal state, we have to make sure that this happens in an exclusive fashion, i.e. while updating the state no access to the state is granted. This is what the
[ServiceHandler(ServiceHandlerBehavior.Exclusive)]
Attribute declaration is for. It ensures that no race condition can occur by exclusively granting access to the internals our service. - Define the GCDState type
What is left, is to define what the state of our GCDService looks like. As mentioned, our service doesn't need to have a state but I have to decided to give it one (mainly for learning purposes). The GCDState type is define in the GCDServiceTypes.cd and can be modified like this
[DataContract()]
public class GCDState
{
private int _GCD;
[DataMember(IsRequired=true, Name = "GreatestCommonDivisor")]
public int GCD
{
get { return (this._GCD); }
set { this._GCD = value; }
}
public GCDState()
{
this._GCD = 1;
}
public GCDState(int gcd)
{
this._GCD = gcd;
}
} - Let's test
Now that we have set things up. We are ready to build the service and test it. Therefore compile everything. Open the MRS Visual Programming Language to build a new test service using our GCDService. I have done that and the test service can be seen here (my GCDService is named "GreatestCommonDivisor").
I hope you enjoyed building this service as much as I did and I hope to have something ready for you asap.
Christian
Thursday, September 13, 2007
Online Lectures
Hi folks,
I found this link about online learning in video form on another blog and thought I could repost it here
http://videolectures.net/
so thanks goes out to
http://smart-machines.blogspot.com/
Both links are available in the sidebar.
Other online lectures
Saturday, September 08, 2007
Microsoft Robotics Studio - First Sight
I have recently come accross this great piece of new technology, offered for free by big MS [1]. MRS allows to program robots and other external devices via a visual programming language (VPL) or your prefered .NET programming language, such as VB.NET or C#. MRS main abstraction is a service.
[1] Microsoft Robotics Studio: http://msdn2.microsoft.com/de-de/robotics/bb625969.aspx
Friday, September 07, 2007
Working the Snake - Python
The first is some simple factorial program, which tries to find the greatest common divisor (gcd)of two numbers by employing the fact that gcd (x, y) = gcd (y, r) where r = x mod y. Since I do not know how a scope for loops can be created (scoping a while/for loop) I did the routine recoursively. The second function builds on the first and is allows to ask whether some number x is a prime number by using the simple strategy of finding a gcd within the range of 1..root(x)
import System
def gcd(x,y):
if y == 1 : return 1
elif y == 0: return y
elif x == y : return y
elif x return gdc(y,x)
n = x % y
if n == 0: return y
return gcd(y, n)
def IsPrime(x):
if x == 1 : return 1
elif x == 2 : return 1
elif x == 3 : return 1
tempsqrt = System.Math.Sqrt(x)
tempsqrt = System.Convert.ToInt32(tempsqrt)
for i in range(tempsqrt) :
j = i + 1
divisor = gcd(x,j)
if divisor != 1 : return 0
return 1
The second program is about the all time recursion favorite - the fibonaci numbers ...
the Fibonaci (Fib ) numbers are defined as follows
Fib(0) = 0
Fib(1) = 1
Fib(n) = Fib(n-2) + Fib(n-1)
example
n 0 1 2 3 4 5 6
Fib (n) 0 1 1 2 3 5 8
and here is the program - putting python suggar just around the exemplified formulae
import System
def Fibonaci(n):
if n <= 0: return 0
if n == 1: return 1
return Fibonaci(n-2) + Fibonaci(n-1)
References:
[1] IronPython - www.codeplex.com/IronPython
[2] Python - www.python.org
Thursday, March 22, 2007
The problems I have right now are:
- I want to implement basic triangle 2D screen-space clipping. Which itself is not a big deal but I do not want to implement a polygon filling scan-line algorithm. A polygon may be the outcome of a triangle clipped against a rectangular clip window. So what is there to do ? Either clip a triangle which produces a polygon and implement a "simple" scanline algorithm to fill that polygon. The other option is of course to split the triangle into a series of triangles. Either way has its intricacies.
- As mentioned in yesterday's I want to implement homogenous clipping for triangles. Which makes things even more complicated then a simple 2D clipper. The reason is that not only a triangle can be split into a series of triangles during the clipping process but also extra state is necessary. Remember, we do not only clip the triangle and generate new triangles that form the clipped triangle but we have to generate appropriate values for associated color, texture and normal data.
- I want the filling of the z-buffer and the filling of the framebuffer to be separate. Although expensive, I want to maintain this separation for flexibility.
For all the people who want to do some graphics stuff I recommend the following books. At least they served my understanding quite well.
- Practical Linear Algebra: A Geometry Toolbox
- Computer Graphics: Principles and Practise
- Real-time Rendering
- Math for 3D Game Programming & Computer Graphics
Happy reading
Wednesday, March 21, 2007
- Line drawing via DDA and Bresenham
- Basic Cohen-Southerland Clipping in 2D
- drawing of triangles (including basic fill)
- a Z-Buffer (at least I have already set up the basics)
- clipping in homogenous clip space
- simple scene-graph
divide all the pipeline elements into pipeline stages. Each stage has access to some renderstate and does only execute on some defined input. As a consequence one would get something similar to vertex and fragment programs and a non-fixed function pipeline. But of course this is only some thinking and I should better get things set up before reasoning about making it most flexible.
Tuesday, March 20, 2007
Of course, it takes some time to get the basics running. Until know it does only little (only perspective projection is covered), such as the transformation from an object's local space to actual screen space. But many things are left to do such as homogenous clipping, 2D clipping, painting ...
The things I want to implement as a next step are
- rasterization (lines via bresenham, basic filling - flat shading)
- homogenous clipping
- 2d clipping
- a primitive scene graph
- Enable double buffering for a control (e.g., Form) via setting a control's property DoubleBuffered = true
- Set a control's style via calling Control.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
- BufferedGraphics
- BufferedGraphicsContext
- BufferedGraphicsManager
Use a BufferedGraphicsContext.Allocate method to create a BufferedGraphics object and to render the contents of such a BufferedGraphics object to an output device use the BufferedGraphics.Render method, which allows you to set the desired output device or use the one supplied to the BufferedGraphics.Allocate method. Drawing to such an off-screen buffer is easily done via a BufferedGraphics.Graphics property.
Of course, if this is not what you want you may still use a Bitmap object to do all off-screen drawing and draw that bitmap to the display.
Sunday, March 11, 2007
Back again :D
Well, it has been a while since I wrote the last post. But since I was finally able to conclude my studies this thursday, the 8th of march, I hope to be around more often. I will probably start my first work on april the 2nd. My new employer will be Avanade Deutschland GmbH (german office of Avanade Inc.). And I am quite happy about that since I expect a great learning experience - well but let's see ...
Since I am not too busy these days I will try to have a look onto several things such as SQL Server 2005 and maybe I get my hands dirty with Phoenix again.
Best regards
Christian