Limegarden.net Personal site of Wouter Lindenhof

25Jan/100

Procedural story

story_03

A little while ago I was meeting a good friend of mine and we had a lot of things to talk about. For one he had just returned from Kenya and he had a lot to show and tell and the things he told me where amazing. But as the day went one, we almost always seem to come back to one subject: Games and developing of games. Funny enough the two of us have almost had the same kind of ideas.
Both of us are developing games in our free time and both have the idea of trying to make as much as possible procedural generated. One of the things we are both interested in is creating the story. While I look for an infinite solution (where the player can play forever and has an interesting storyline) he has a more pragmatic approach.
As we discussed procedural generated stories he pointed out that a story teller needs to tell his audience what happens where and when (not to be confused with why). This triggered a thinking path I had not yet explored. Until then I had simply assumed events happen in a certain order. When a user is playing a computer game he will grow a certain emotional attachment to the player. Emotions in a story are important. For example Romeo and Juliet is a story about hate between families, love between two person and has a lot of betray. Romeo and Juliet is considered one of the classic romantic stories and by some it is considered one of the most romantic stories ever written.
So after the talk and some thinking a procedural story generator could be written as a system that tries to move from emotion to another emotion both for individuals as a culture. To give yet another example: The player gets betrayed by a general and while he was betrayed the general does end the war (and the country he fought for sees him as a hero), while at the other side (the defeating side) wants to see the general death. You now have four elements: The player, the general, the winning country and the losing country. The player is angry as he is betrayed. The general is content and pleased as he is being seen as hero. The winning country feels superior to the losing country and the losing country feels disgust towards all other elements. See the diagram.

At this point the computer needs to "write" the next part of the story. The computer could now plot a new scheme by just adding or removing some story elements. The player could for example become the leader of the rebellion or he could join the general as one of his right-hand leaving his feelings of betray or he could kill the general and become the new general. In this case I want to add another character say the princess of the winning country and make the player the leader of the rebellion. The princess finds out that the generals betray and for some reasons she encounters the player and they fall in love with each other. Yet they can't be with each other as one country hates the other ruler. The general at this point hates the player. The graph might be clearer.

Moving forward we arrive at a point in the story where the player and the princess are married and they rule both countries. The general is now hated by all. And here is another graph.

For the story generator the only thing is how the possible futures of all elements could be. Once he knows the possible futures all it has to do is create "story chapters" which move the story toward the possible features. If needed a chapter could have a branch which excludes one of the possible features, for example the player kills the general before the princess was able to find out about the betray of the player so she never finds out the wrong he did and therefore never encounters the player.
Of course a lot more thought needs to go in this, but it solved for the procedural "writers-block".

10Jan/100

Undesired template specification

Updated 10 January 2010: The download was not working, this is now fixed

Yesterday I decided to improve my math library and to make it more flexible. One of the things that I wanted to do was convert it to a template, so that I could easily make vectors of different types. However when it was finished and I started testing it I came across a lot of issues which my old math library didn't have. The reason that my old library didn't have them was because all of the structures used floats and when used with any other variable type would be automatically be casted, promoted or demoted to match the type float. However templates are more strict on that area since templates need to specialize. I know this is confusing so let me explain by example.
I will show three examples of the above problem and I will explain how to solve any of them. I hope that throughout the progress you will also understand why the problems happen.
But first let me define the class that I use. This piece of code won't change until I cover the solution of the third problem.
The Vector2 class:

[cc_cpp]
template class tVector2
{
public:
T X, Y;
tVector2(T x, T y) : X(x), Y(y) {}
// Assigrnent operator
tVector2 operator = (tVector2 v) { X = v.X, Y=v.Y; return *this; }
};
// Multiplication operator
template tVector2 operator * (tVector2 v, T r) { return tVector2(v.X*r, v.Y*r); }
[/cc_cpp]

FIRST PROBLEM: ONLY A SINGLE TEMPLATE ARGUMENT

The first problem shows itself rather fast.

[cc_cpp]
int testMain1() // Think of this as a normal main
{
tVector2 Vec2(1,1);
Vec2 = Vec2 * 2.0f; // Does compile
Vec2 = Vec2 * 2.0; // Does not compile
return 0;
}
[/cc_cpp]

Visual Studio comes with two errors:

[ccWN_text]error C2782: 'tVector2 operator *(tVector2,T)' : template parameter 'T' is ambiguous
error C2676: binary '*' : 'tVector2' does not define this operator or a conversion to a type acceptable to the predefined operator[/ccWN_text]

If we think about the reason for this problem is rather easy. If we would think as the compiler we would have the following two forms of multiplication:

[cc_cpp]
tVector2 operator * (tVector2 v, float r);
tVector2 operator * (tVector2 v, double r);
[/cc_cpp]

The first multiplication in the example does compile as it makes use of the first form, the second multiplication in the example however raises two errors. As you can see neither form can be applied on our multiplication, which has the form [cci_cpp]tVector2[/cci_cpp] multiplied by a double. Since the compiler can't figure out whether template argument T is a float or a double, he throws the error that is ambiguous.
The second error comes forth because the compiler still tries to solve. However it cannot convert [cci_cpp]tVector2[/cci_cpp] to a [cci_cpp]tVector2[/cci_cpp] and he can't demote the second argument "2.0" to a float because their second form exists and denies him from demoting just like the following examples forbids only using the first form.

[cc_cpp]
void TestFunction(float v);
void TestFunction(double v);

int main()
{
TestFunction(2.0f); // Use first form
TestFunction(2.0 ); // Use second form
return 0;
}
[/cc_cpp]

FIRST SOLUTION: USE MULTIPLE TEMPLATE ARGUMENTS

The title of the first solution might feel contradicting as [cci_cpp]tVector2[/cci_cpp] does not change, but it is rather easy. We simply add another operator which look as followed.

[cc_cpp]
template
tVector2 operator * (tVector2 v, R r) {
return tVector2(v.X*r, v.Y*r);
}[/cc_cpp]

The biggest change is that because of using two template arguments, which are used for the first and second argument, is that compiler no longer have to match the types. So the compiler can generate the following:

[cc_cpp]
tVector2 operator * (tVector2 v, int r);
tVector2 operator * (tVector2 v, float r);
tVector2 operator * (tVector2 v, double r);
[/cc_cpp]

And the everything works. You can even remove the old multiplication method if you want.

SECOND PROBLEM: MULTIPLYING DIFFERENT TYPES

This problem is exactly the same as the first one, but I cover it none the less as it took me a few seconds more to realize this than I wanted.

[cc_cpp]
int testMain2() // Think of it as a seperate program
{
// Second problem: Multiplying different types
tVector2 Vec2(1,1);
tVector2 Vec2d(1,1);
Vec2d = Vec2d * Vec2; // tVector2=tVector2*tVector2
return 0;
}[/cc_cpp]

When we compile this visual studio comes two times with two different errors (total is four):

[ccWN_text]error C2784: 'tVector2 operator *(tVector2,R)' : could not deduce template argument for 'tVector2' from 'double'
error C2677: binary '*' : no global operator found which takes type 'tVector2' (or there is no acceptable conversion)[/ccWN_text]

The errors all take place in the solution of the previous problem as it tries to solve that function in to the following form:

[cc_cpp]tVector2 operator * (tVector2 v, tVector2 r){
return tVector2(v.X*r, v.Y*r);
}[/cc_cpp]

I have added on purpose also the body of the form because that is what you should concentrate on. As you can see it tries to multiply [cci_cpp]v.X[/cci_cpp] with [cci_cpp]r[/cci_cpp]. While [cci_cpp]v.X[/cci_cpp]is a float, which is correct. [cci_cpp]r[/cci_cpp] is of the type [cci_cpp]tVector2[/cci_cpp] and although there are times where this kind of multiplication is correct, the result would be a tVector2 which is wrong. In fact the above code could even be made working with a few simple steps. It would not give the result we are looking for, but it would work. The wrong steps would be, adding a new constructor which has as input two vectors and allowing numbers be multiplied by vectors (like in the first solution, but then the two function arguments switched around). However I will provide you with the correct solution.

SECOND SOLUTION: USE MULTIPLE TEMPLATE ARGUMENTS WITH TYPES

Similar to the first problem we add the following function:

[cc_cpp]template
tVector2 operator * (tVector2 v, tVector2 r) {
return tVector2(v.X*r.X, v.Y*r.Y);
}[/cc_cpp]

There is however one down side to this solution and that is that type returned is the same as the first template argument, even if the second template argument would be bigger. For example the first template argument is a float and the second is of the type double. In that case we would lose precision.

THIRD PROBLEM: CONVERTING FROM ONE TYPE TO ANOTHER TYPE

The test case is similar to that of the second problem, but with a little change.

[cc_cpp]int testMain3() // Think of it as a seperate program
{
// Third problem: Storing different types
tVector2 Vec2(1,1);
tVector2 Vec2d(1,1);
Vec2d = Vec2 * Vec2d; // tVector2 = tVector2 * tVector2
return 0;
}[/cc_cpp]

As you can see the result of the multiplication is now [cci_cpp]tVector2[/cci_cpp] while it previously was a [cci_cpp]tVector2[/cci_cpp]. This multiplication works, but the problem is the assignment operation. We try to store a [cci_cpp]tVector2[/cci_cpp] in a [cci_cpp]tVector2[/cci_cpp] and that is not allowed. If you look back at the original class you will see that the assignment operator requires that the function argument is of the same type as the class to which it belongs. And if there is one thing I have learned from the previous problem then it is that is not allowed.
However unlike the solutions of the first two problems, this operator needs to be a member function. So we should store a tVector of a unknown type in a tVector of a specialized type (which is actually also unknown, but the compiler specializes this so it is known to him, but not to us).

THIRD SOLUTION: TEMPLATE FUNCTION INSIDE A TEMPLATE CLASS

To be honest, I didn't think this was at all possible but since I had solved the previous two problems I was intended to find a solution for this one as well. In retrospect the solution was just as simple as the previous one, but then again everything seems easy in retrospect.
The new class looks as followed:

[cc_cpp]template class tVector2
{
public:
T X, Y;
tVector2(T x, T y) : X(x), Y(y) {}
// Assigment operator (didn't solve the third problem)
tVector2 operator = (tVector2 v) { X = v.X, Y=v.Y; return *this; }

// Assigment operator which allows other types (solved third problem)
template tVector2 operator = (tVector2 v){
X = v.X, Y=v.Y; return *this; }
};[/cc_cpp]

As you can see a new function has been added, which is a template function. Quite a simple and elegant solution once you accept the fact that you are allowed to create template functions inside a class as well.

FINAL WORDS

Although the title of the article is "Undesired template specification" it was only how I felt when I encountered all these problems. Afterwards I think it was not undesired at all, because this is how the language should work. If it wouldn't work like this we would barely have control what some of the functions would and then it would really become undesired.
I hope that the all of the above was easy enough to follow (assuming you are familiar with templates) and helped you understand in what went wrong and how to solve it.
As usual I have added the full source code at the bottom of the article. All the functions are in it, however in a production environment I would recommend you remove the old versions of some of the functions since the new functions also cover the functionality of the old ones.

Source code: templatetest_0.zip (2 kb)

4Jan/100

Gamer or developer?

Over the last few weeks I have constantly wondering one thing. Am I gamer or a developer? Today I have decided to find an answer.

My first encounter with games
Many years ago, when I was still a child I played a lot outside. I loved playing outside as I would climb trees, played hide & seek and got in to all kinds of petty fights. Your average kid. At a sunny day I went with a friend to her home and she showed something that would change my world. For the first time I played a game on a video console, I never remembered the name but for this entry I have looked it up. It was “Super Mario Bros. 2”. I looked at it and was stunned, she was not good at it and I refused to play as I was more interested in looking at it then actually playing. The only things I remember was the player select and the first level. I think I have only seen the game played once more after that until we got kicked out because it was such nice weather outside. I remember thinking it was such a stupid argument. But summer started and they went on vacation and just before they got back we left, then school started.

Becoming a gamer
But from that moment I was interested in computer games and I started nagging about it that some kids have a game console and we don’t. I threw the entire “it’s not fair” argument but my parents decided against it. Until 5 December and it was Saint Nicholas’ eve (he is something like Santa). To our surprise the good Saint had given me and my brother our very first game console. A Sega Mega Drive II and the game that was with it was a US version of Street Fighter 2. Now candy was competing with games for my allowance. Years later I was in a local shop and saw a game magazine, I didn’t know they existed (I dislike shopping, it takes so much time) and on the cover was an image of a young child holding a sword in front of a pedestal while blue energy was around him. It took me a few days, but then I decided to spend my money on that magazine. The kid on the cover was Link from the Zelda: The Ocarina of Time and it was about the Japanese preview. I remember that they showed a boss that was not in the actual release (although I think it was later modified and included in Majora’s Mask). We sold our Mega Drive and bought an Nintendo 64 with Lylat Wars (Star Fox 64).

Deciding my future
When I entered high school I told my parents I wanted to work in the video game industry and they shook their heads but later on changed that in “we shall see”.
So that is my history where I became a gamer. But now starts my history in becoming a developer. I sucked at a lot of high school subjects, but I had a lot of trouble fitting in and failed first year. I remember the huge contradiction on what level I should start. The previous school said I should started at the second lowest level, while an national independent organization said I should start at the second highest. As I struggled through high school there were a lot of strange events. In my first year I failed France but when I retook that year I was the only one as far as they can remember who had 10 on his pre-midterm report. Normally the range was between a 3 and an 8 but since I had done everything perfect they decided to give me a ten. I struggled through high school with a lot of help from my parents and teachers.Since there was no game education I decided to do IT. On the ICT course I made a lot of friends and had a lot of fun and me and a friend where “the best programmers”. I was surprised to see how little effort it took me to program.

Am I gamer or am I a developer?
Now I’m a student of the International Game Architecture and Design (IGAD) program. I’m having an internship at Codeglue, Rotterdam. And the internship has made some things really clear for me. I don’t think I’m a gamer in the same sense as others are at the IGAD course or at my internship. I like to play games from time to time and in my drawer I have two complete game design and an half dozen ideas that still need work.
But when I’m working I don’t think like a gamer especially when it’s programming that needs to be done. Oh yes, I know I’m working on a game, but a game is nothing more than an illusion. And because I know that I realize that I’m not a gamer but an illusionist. I let people thinkthat they are saving the world. I know that the a kid dressed in green is nothing more than a lot of different colored triangles. And it’s my job to uphold such illusions in new games. Because of the above conclusion, I should not be a gamer. A true illusionist is not bedazzled with his own illusions or those from others. And although as a programmer you don’t always design the tricks, you make certain that they work. You create parts of the machine, you help artists apply the paint and you listen and tell what is and what is not impossible to those who designed the illusion. Once the work is done and the illusion is complete you demonstrate it to the public and watch them enjoy (and pay) for something that is nothing more than a good illusion. So the only conclusion is that I’m a developer. I look in despair at near broken machines and I enjoy myself immensely when I see a proper created machine. I love to create superior machines that support the illusion and are often capable of much more than the one who designed it wants it to.

I’m not just a developer. I’m a developer who loves my job. I’m a developer who loves to see his creations being the cause of entertainment of thousands. 

Final words
I know this has been a long rant but it has been something I want to get off my chest for a long time. Personally I find the game industry as it’s now young and naïve. It believes a little too much in its own illusion. But the cold hard truth is that in the end you are creating an illusion. Some people use poor quality machine parts, don’t give every detail or the painting thought or think that once a simple design is done you can work as it goes. Some companies require that the staff to go in crunch mode extended periods of consecutive overtime) with all it’s faults.
From a business perspective I think it should look and learn more from a young but more mature market, the IT sector. But at the ICT course I had one teacher who I understood after I started on the IGAD course. He said: “Always take in account the three P’s: Product, Project and process”. And many game developers are ignorant of the last one. The process is that what breaks or makes your illusion better than the rest.

Filed under: Uncategorized No Comments
4Jan/102

The new and improved acyclic visitor with observer pattern (C++)

I have improved my “Acyclic Visitor with Observer” pattern (here is a link to the old one). Now you can create classes that are derived from two Acyclic visitors, something that was not possible with the previous version. On top of that I have made it less complex to use. On top of that they no longer have generic names (like “INotification”). The coolest thing is the registering. Previously you had to create the objects in the user code and also specify the class that should receive it. Now, it's simply done when you define the class.

Anyway just compare the code:

The old code


class HelloWorldReceiver : public IReceiver
{
public:
	HelloWorldReceiver()
	{
		m_Translators.push_back( CTranslator<HelloWorldReceiver, WorldNote>() );
		m_Translators.push_back( CTranslator<HelloWorldReceiver, HelloNote>() );
	}
	void Receive(WorldNote* aWorld) {	}
	void Receive(HelloNote* aHello) {	}
};

The new code


class HelloWorldVisitor : public tAcyclicVisitor<HelloWorldVisitor>
public:
	HelloWorldVisitor() {
		RegisterAVObject<Hello>();
		RegisterAVObject<World>();
	}
	void Receive(Hello* obj) {	}
	void Receive(World* obj) {	}
};

And here is all the code you need to start using it, it's licensed as I promised in the previous post, but as you can see you all you need to do is keep the license in the code (all 21 lines).


// The MIT License
//
// Copyright (c) 2009 Wouter Lindenhof (http://limegarden.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the &quot;Software&quot;), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#ifndef __ACYCLIC_VISITOR_H__
#define __ACYCLIC_VISITOR_H__
#include <list>

/**
 * @brief if set to 1 it will allows the user to combine derived acyclic
 * visitors, but this is likely to have a cost because of virtual inheritance.
 */
#define AV_ALLOW_VIRTUAL_INHERITANCE 1

/**
 * @brief this is the base object
 */
class AVBaseObject
{
public:
	virtual ~AVBaseObject() {}
};

class AcyclicVisitor;

class IAVTranslator
{
public:
	virtual const bool Accept(AVBaseObject* object, AcyclicVisitor* visitor) const = 0;
};

class AcyclicVisitor
{
	typedef std::list<IAVTranslator*> TransList;
protected:
	TransList m_AV_Translators;
public:
	virtual ~AcyclicVisitor() {
		for( TransList::iterator it = m_AV_Translators.begin(); it != m_AV_Translators.end(); ++it )
			delete (*it);

		m_AV_Translators.clear();
	}
	void Visit(AVBaseObject* baseObject)
	{
		for( TransList::iterator it = m_AV_Translators.begin(); it != m_AV_Translators.end(); ++it )
			(*it)->Accept(baseObject, this);
	}
};

template <typename V, typename O>
class tAVTranslator : public IAVTranslator
{
public:
	const bool Accept(AVBaseObject* object, AcyclicVisitor* visitor) const
	{
		V* original_visitor = dynamic_cast<V*>(visitor);
		O* original_object  = dynamic_cast<O*>(object);
		if(original_object == 0 || original_visitor == 0) return false;
		original_visitor->Receive(original_object);
		return true;
	}
};

template <typename V>
#if AV_ALLOW_VIRTUAL_INHERITANCE == 1
class tAcyclicVisitor : public virtual AcyclicVisitor
#else
class tAcyclicVisitor : public AcyclicVisitor
#endif
{
protected:
	template <typename O> void RegisterAVObject()
	{
		m_AV_Translators.push_back(new tAVTranslator<V, O>());
	}
};

#endif 

I have also uploaded the entire example that I have used while testing so that you can some more interesting stuff.

4Jan/100

Rewriting examples: Direct3D tutorial 1 with D3DVERTEXELEMENT9

A while ago a friend asked me how to do something with Direct3D (better known as DirectX) about streams. I really enjoyed it since it was sometime I have worked with my favorite 3D API and so I explained the usage of VertexDeceleration by rewriting the very first tutorial of Direct3D of which you can see the result below


#include <windows.h>
#include <d3d9.h>
#pragma comment(lib, "d3d9.lib")
#include <d3dx9.h>
#pragma comment(lib, "d3dx9.lib")

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	static TCHAR szAppName[] = TEXT ("DirectXStreamExample");
	HWND         hwnd;
	MSG          msg;
	WNDCLASSEX   wndclassex = {0};
	wndclassex.cbSize        = sizeof(WNDCLASSEX);
	wndclassex.style         = CS_HREDRAW | CS_VREDRAW;
	wndclassex.lpfnWndProc   = WndProc;
	wndclassex.cbClsExtra    = 0;
	wndclassex.cbWndExtra    = 0;
	wndclassex.hInstance     = hInstance;
	wndclassex.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
	wndclassex.hCursor       = LoadCursor (NULL, IDC_ARROW);
	wndclassex.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
	wndclassex.lpszMenuName  = NULL;
	wndclassex.lpszClassName = szAppName;
	wndclassex.hIconSm       = wndclassex.hIcon;

	if (!RegisterClassEx (&amp;wndclassex))
	{
		MessageBox (NULL, TEXT ("RegisterClassEx failed!"), szAppName, MB_ICONERROR);
		return 0;
	}
	hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW,
		szAppName,
		TEXT ("DirectXStreamExample"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		640,
		480,
		NULL,
		NULL,
		hInstance,
		NULL); 

	ShowWindow (hwnd, iCmdShow);
	UpdateWindow (hwnd);

	// Now setup DirectX
	IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
	D3DPRESENT_PARAMETERS presentParameters;
	memset(&amp;presentParameters, 0, sizeof(D3DPRESENT_PARAMETERS));
	presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
	presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
	presentParameters.Windowed = true;
	IDirect3DDevice9* device = 0;
	d3d9->CreateDevice(0, D3DDEVTYPE_HAL, hwnd, D3DCREATE_MIXED_VERTEXPROCESSING, &amp;presentParameters, &amp;device);

	// Create our custom vertex format
	struct POSCOLORVERTEX
	{
		float X, Y, Z, W;
		DWORD color;
	};
	POSCOLORVERTEX vertices[] = {
		{150.0f,  50.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(255,0,0)},
		{250.0f, 250.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0,255,0)},
		{ 50.0f, 250.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0,0,255)},
	};

	// Create a vertex decleration
	// Think of a vertex decleration as an object that describes a single custom
	// vertex.

	// 	typedef struct _D3DVERTEXELEMENT9
	// 	{
	// 		WORD    Stream;     // Stream index
	// 		WORD    Offset;     // Offset in the stream in bytes
	// 		BYTE    Type;       // Data type
	// 		BYTE    Method;     // Processing method
	// 		BYTE    Usage;      // Semantics
	// 		BYTE    UsageIndex; // Semantic index
	// 	} D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9;

	// Example 1: Tutorial 1 of the DirectX SDK
	// using weighted position (aka screen coordinates) and colors but without
	// using the Fixed Pipeline
	D3DVERTEXELEMENT9 PosColorVertexElements[] = {
		{0, 0,  D3DDECLTYPE_FLOAT4,		D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,	0},
		{0, 16, D3DDECLTYPE_D3DCOLOR,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,		0},
		D3DDECL_END()
	};

#if 0
	// Example 2: If you want to add UV it would become something like this:
	D3DVERTEXELEMENT9 PosColorUVVertexElements[] = {
		{0, 0,  D3DDECLTYPE_FLOAT4,		D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,	0},
		{0, 16, D3DDECLTYPE_D3DCOLOR,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,		0},
		{0, 20, D3DDECLTYPE_FLOAT2,		D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,	0},
		D3DDECL_END()
	};
	// Example 3: And if you want UVs first
	D3DVERTEXELEMENT9 PosColorNormalVertexElements[] = {
		{0, 0,		D3DDECLTYPE_FLOAT2,		D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,	0},
		{0, 8,		D3DDECLTYPE_FLOAT4,		D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,	0},
		{0, 8+16,	D3DDECLTYPE_D3DCOLOR,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,		0},
		D3DDECL_END()
	};
	// Example 4: And if you want to send two UV's
	D3DVERTEXELEMENT9 PosColorNormalVertexElements[] = {
		{0, 0,  D3DDECLTYPE_FLOAT4,		D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,	0},
		{0, 16, D3DDECLTYPE_D3DCOLOR,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,		0},
		{0, 20, D3DDECLTYPE_FLOAT2,		D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,	0}, // Maps to TEXCOORD0 in shader
		{1, 28, D3DDECLTYPE_FLOAT2,		D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,	0},	// Maps to TEXCOORD1 in shader
		D3DDECL_END()
	};
#endif

	IDirect3DVertexDeclaration9* vertexDecleration = 0;
	device->CreateVertexDeclaration(PosColorVertexElements, &amp;vertexDecleration);
	device->SetVertexDeclaration(vertexDecleration);

	// Create vertex buffer
	IDirect3DVertexBuffer9*  vertexBuffer;
	device->CreateVertexBuffer(
		3*sizeof(POSCOLORVERTEX),
		0,
		0,								// DON'T pass the FVF code if you are using vertex decleration
		D3DPOOL_DEFAULT,
		&amp;vertexBuffer,
		0);

	// Fill the vertex buffer
	void* pVertices = 0;
	vertexBuffer->Lock(0, sizeof(vertices), (void**)&amp;pVertices, 0);
	memcpy(pVertices, vertices, sizeof(vertices));
	vertexBuffer->Unlock();

	bool keepRunning = true;

	while(keepRunning)
	{
		// Render
		device->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
		device->BeginScene();
		// Rendering of scene objects happens here
		// 1. Set the vertex decleration
		// 2. Set the stream source
		device->SetVertexDeclaration(vertexDecleration);
		device->SetStreamSource(0, vertexBuffer, 0, sizeof(POSCOLORVERTEX));
		device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
		// End the scene
		device->EndScene();
		device->Present(0,0,0,0);

		if (PeekMessage(&amp;msg, NULL, 0, 0, PM_REMOVE))
		{
			if(msg.message == WM_QUIT) keepRunning = false;
			else
			{
				TranslateMessage (&amp;msg);
				DispatchMessage (&amp;msg);
			}
		}
	}

	vertexBuffer->Release();
	vertexDecleration->Release();
	device->Release();
	d3d9->Release();

	return msg.wParam;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_DESTROY:
		{
			PostQuitMessage (0);
			return (0);
		}break;
	}
	return DefWindowProc (hwnd, message, wParam, lParam);
}
4Jan/100

Donuts! (Procedural Torus in C++)

Donut

Recently I got a mail through the contact form of my website about texture mapping on torus (a donut) who said that [cci_cpp]D3DXCreateTorus[/cci_cpp] didn't not provide texture coordinates. The reason why DirectX and OpenGL (and GLUT) don't provide texture coordinates with these function is best seen when you generate a cube. A cube has 8 vertices, however when you add texture coordinates it will increase because otherwise they will share the same texture coordinate. With normals it is no problem (in fact you would prefer that) but if you have a dice (from 1 to 6) than each vertex would use a single texture coordinate for three sides. Just draw an unfolded dice on paper where each edge is connected, but does not cross another edge. It is simply not possible. These complexities are the reason why those procedural mesh functions are so simple. Adding these functionalities would increase complexity of the function and requires you to explain it. On top of that the developers have no idea how you are going to use that function. Maybe you don't want to use the legal texture range [0...1] but [0...3].

Anyway I have decided to take it on and here is the result. You can download the source code here: TorusDX.zip.I have not commented it, but it is pretty straight forward. The texture that I used is from Dilbert.

4Jan/100

Finishing my school project

This is an old post from my previous blog which might show up again in your feed

As some know I have talked a lot about procedural generation and since last summer one of my ideas has been accepted. And now two months later I have finished my research paper.

I never really liked research papers, in many cases there is too much data to work through and in generally I’m only interested in the solution. However when you have to write your very  own research paper of 3000 words your glad to have much data except when it reaches 4500 words then it becomes a pain since you have to spell-check and grammar-check those extra 1500 words. And then to think that I’m still not glad with some explanations and think some part of the document needs to be improved. Currently I’m guessing it’s going to be around the 5250 words. 

The cool thing is that I’m going to make the research paper freely available for everyone. I have been pleasantly surprised that some people have used the feedback form to either respond or ask me a question. Some of the feedback was really nice and has been a great help to me. Those people have my thanks. As for releasing the paper it will most likely be next week. 

Filed under: Uncategorized No Comments
4Jan/100

Writing using Latex

Writing is something I always enjoyed, but there were always obstacles that I had to work around. In the past I always had to deliver documents but this became more and more troublesome as there was a difference between Microsoft Word and Word Perfect and these days I sometimes encounter someone who has MS Word 2003, which is really outdated by now.

I have made it a habit to present my documents in PDF format. I have never been a fan of PDF until I noticed that nobody complained about it (which often happened with Doc(x)-files). However word documents are hardly flexible and often enough I’m more busy with formatting than I’m busy writing. Also as a programmer I noticed that I can rarely write comments in the document and when working with others I have to explain the “Keep track of changes” function that is in Word.

For my research paper I started writing in Word but at certain point I got so fed up because I had to print the document, write comments as I read it and then go back to my computer to act on my own remarks. At the same time it was no longer possible to have the document being split in multiple files, something I do when I’m programming. Instead I look through the entire document, finding the correct section and then correct it.

As you can understand this is quite time consuming and I’m quite certain it could be done better. I had heard of LaTeX before but it seems complicated and more for *NIX systems than for windows. But I finally decided to see how it can be done and installed both MikTex and TeXnicCenter, which are awesome pieces of software. While at the same time I started reading up on LaTeX. And after using it for a week I must say I wish I had discovered it earlier.

LaTeX was made for programmers who often need to write documentation. It can be compared to programming and it often feels like that. It was not hard as I thought it would be and by now I prefer it to working in word. I don’t have to worry about formatting, it converts to a PDF, I can split my documents over various source files, write comments and with a little bit of work using the viewers (you can export to DVI or PDF) I can double click on a paragraph I think that needs to be changed and it brings me directly to the source code. The only thing that I really miss is the grammar checking (it does have a spell-checker) but that is not that important for me now.

One really cool thing is that I don’t have to worry about the formatting of images. I just include them like \includegraphics{myImageFile} and when I compile it gives me a warning that the file does not exist. Normally I was always busy creating images while I wanted to be writing and fixing the images until they matched the format of the rest of the document but that all seems to be in the past.

However there are a few things that I wished were different. For one exporting it to a different format is hard, which means that if someone wants to give feedback by highlighting the text and then write some comments they have to extract it since they don’t have access to the source files or have the knowledge to work with it. The exported text however uses hard returns every time it needs to wrap the text. But I think I can fix that by compiling it to html. And of course it takes some time to get used to writing LaTeX. So far I’m quite positive about LaTeX and I hope that it stays that way.

Filed under: Uncategorized No Comments