Blog
Rambling, musing, and coding.
-
Osiris SceneGraph Development Part 1 - Introduction
-
This series will describe the development of a scene graph toolkit. This is a non-work project so I can't promise regular updates, but I will do my best.
Motivation
I wondered about calling this YASG (Yet Another Scene Graph). There's quite a few of them out there. However, nothing quite suited.
My primary goal in writing a scene graph is to use it as the basis of an XNA game. However, I've got some other projects on the go. One is a ray tracer, and the other is a software renderer. The software renderer will be used in an ASP.NET control that I am developing for my company.
I realised that I was writing very similar code for each of these three projects: specifically, code to manage the scene data. All three required code for some sort of tree involving transforms; all three required code for camera transformations; all three required code for storing triangular meshes.
It seemed to me that it would be highly desirable to completely separate the scene data from the rendering. If this was possible, I could write one scene graph system, and three renderers (ray tracer, hardware rasterizer, software rasterizer).
If at this point you're thinking "uh oh - I see where this is going - it's going to be a nightmare to abstract away the differences between those renderers", then you'd be completely right. And if this was a commercial project, it would almost certainly be dead in the water, in terms of reward for time spent. But this is a hobby project, and I love abstraction.
Problems
Immediately I began to hit problems. Possibly the most basic requirement of any graphics library is a good set of maths classes - i.e. vector, matrix, etc. Since the primary usage of the scene graph is going to be for an XNA game, it would make sense to use the maths classes available in XNA (Vector3, Matrix, etc.) right? Sadly not. I am exposing the other two renderers (software rasterizer, ray tracer) through an ASP.NET web control. I don't want to have Microsoft.Xna.Framework as a dependency for an ASP.NET control. The same goes for the maths classes in WPF (Vector3D, Point3D, etc.).
Core classes
So I decided to write my own maths classes. Having now done this, I can say it's not fun, when it feels so much like re-inventing the wheel. But I wanted a scene graph which could be used by multiple renderers. So I don't have much choice. I used both WPF (the Media3D namespace) and XNA as a model for my maths classes. I like how WPF separates out Vector3D and Point3D. I know you can accomplish everything you need to with just a Vector3D, but it seems more rigorous to provide separate types. I have implemented the following types:
- Color
- Matrix3 (used for some physics calculations)
- Matrix4
Plane- Point (for texture coordinates)
- Point3D
- Ray3D
- Vector3D
Scene graph
Whew! I haven't even started describing the design of the scene graph but I'm going to finish soon. In summary: in this series of blog posts I will be describing the development of a scene graph, starting from scratch. I will try to describe the major problems I face along the way. Later on I will talk about how I've implemented / am implementing each of the three renderers (ray tracer, software rasterizer, hardware rasterizer).
I did quite a lot of research of existing scene graphs (including OpenSceneGraph and Nvidia Scene Graph), and tried to distil what I liked from them, together with my own ideas. I also had the restriction of needing the scene graph to work with a ray tracer, which is a limitation not faced by most existing scene graphs (which are optimised for a particular renderer, such as OpenGL). At the same time, the scene graph needed to cope with a hardware renderer, which (for example) requires vertices to be stored in a vertex buffer in graphics memory. I will describe the solutions I came up with in Part 2.
-
29 July, 2008 at 21:00
0
Comments
-
Setting the default button for a nested control in ASP.NET
-
In ASP.NET 2.0, you can declaratively set which button which be "clicked" when the user presses the Enter key. This can be done on either the
-
24 June, 2008 at 11:55
0
Comments
-
XNA 3.0 Hybrid Ray Tracer
-
Download XNA 3.0 Hybrid Tracer (source code, requires Visual Studio 2008 and XNA 3.0 CTP)
Last week while going through my personal software graveyard, I "dug up" a ray tracer I started a few years ago. I had written it using C#, and it was rendered using GDI+. I decided to bring it up to date - and you can't get newer than the XNA 3.0 CTP, released last week. At this stage there's hardly any new features related to Windows development, apart from audio, but I like being able to use Visual Studio 2008 and LINQ.
Anyway, one thing that annoyed me about my previous implementation was how difficult it was to move the camera around. So, I decided to write a hybrid ray tracer:
- When the camera is static, ray tracing is used.
- When the camera is moving, XNA hardware rasterization is used.
Features
- Automatically switches from ray tracing to hardware rasterization when camera is moving
- Loads scenes from an XML file using the XNA Content Pipeline
- Supports sphere and plane primitives, with other primitives coming soon (including triangles, and hence meshes)
- Point lights, with other light types coming soon
The current version is fairly basic, both in terms of ray tracing and rasterization. The two render methods are also not very similar - about the only thing they are the same at is object position. However, I know it's usually better for me to upload something, however basic, just to get the ball rolling. So here it is. Feel free to use the code in any way you like. Hopefully you'll find it logically structured.
The camera has two modes:
- Pan: This took me a while to get right. I eventually realised that software like 3D Studio Max converts mouse coordinates from screen space to world space, and then pans in world space. So I did the same.
- Arc ball: I'm not happy with my implementation of this. It sort of works though - I set it to rotate around a point 5 world units in front of the camera.
- In either mode, you can use the mouse scroll wheel to zoom (although this doesn't work very well yet).
My todo list:
- Ray tracer
- Refraction
- Photon mapping
- Textures
- kd-tree for spatial sorting
- XNA rasterization
- Specular lighting
- Environment mapping
- Planar reflections and refractions
- Both renderers
Screenshots




-
15 May, 2008 at 23:49
0
Comments
-
ASP.NET HTML Control Mapping
-
Ever wondered how ASP.NET takes an HTML tag, such as <head>, and maps it to an System.Web.UI.HtmlControls.HtmlHead object? Well, me neither, till today. But if you ever want to know, Reflector comes in handy. In the System.Web.UI namespace, there's an internal class called HtmlTagNameToTypeMapper. In here, there's a method called GetControlType, which looks like this:
Type ITagNameToTypeMapper.GetControlType(string tagName, IDictionary attributeBag)
{
Type type;
if (_tagMap == null)
{
Hashtable hashtable = new Hashtable(10, StringComparer.OrdinalIgnoreCase);
hashtable.Add("a", typeof(HtmlAnchor));
hashtable.Add("button", typeof(HtmlButton));
hashtable.Add("form", typeof(HtmlForm));
hashtable.Add("head", typeof(HtmlHead));
hashtable.Add("img", typeof(HtmlImage));
hashtable.Add("textarea", typeof(HtmlTextArea));
hashtable.Add("select", typeof(HtmlSelect));
hashtable.Add("table", typeof(HtmlTable));
hashtable.Add("tr", typeof(HtmlTableRow));
hashtable.Add("td", typeof(HtmlTableCell));
hashtable.Add("th", typeof(HtmlTableCell));
_tagMap = hashtable;
}
if (_inputTypes == null)
{
Hashtable hashtable2 = new Hashtable(10, StringComparer.OrdinalIgnoreCase);
hashtable2.Add("text", typeof(HtmlInputText));
hashtable2.Add("password", typeof(HtmlInputPassword));
hashtable2.Add("button", typeof(HtmlInputButton));
hashtable2.Add("submit", typeof(HtmlInputSubmit));
hashtable2.Add("reset", typeof(HtmlInputReset));
hashtable2.Add("image", typeof(HtmlInputImage));
hashtable2.Add("checkbox", typeof(HtmlInputCheckBox));
hashtable2.Add("radio", typeof(HtmlInputRadioButton));
hashtable2.Add("hidden", typeof(HtmlInputHidden));
hashtable2.Add("file", typeof(HtmlInputFile));
_inputTypes = hashtable2;
}
if (StringUtil.EqualsIgnoreCase("input", tagName))
{
string str = (string) attributeBag["type"];
if (str == null)
{
str = "text";
}
type = (Type) _inputTypes[str];
if (type == null)
{
throw new HttpException(SR.GetString("Invalid_type_for_input_tag", new object[] { str }));
}
return type;
}
type = (Type) _tagMap[tagName];
if (type == null)
{
type = typeof(HtmlGenericControl);
}
return type;
}
Unfortunately, there's no way I can see of overriding this behaviour - for example, if you wanted to map the <li> element to a custom HtmlListItemControl, it's impossible.
Labels: ASP.NET
-
02 January, 2008 at 16:47
0
Comments
-
A few things I wonder about
-
Continuing the line of thought from a previous blog post, here's some more things I wonder about, complete with answers that I have helpfully researched for you:
How many ants live in an ants' nest?
An ant colony can range in size from a few 10s of individuals to over a million, depending on species and age of the colony.
Can a swan really break your arm?
Yes, but only in exceptional cases.
How do the screens at London bus stops calculate when buses are due?
Currently, they use a tag and beacon system, which records the location of the bus when it passes roadside beacons along the route. However, Transport for London has been trialling a GPS system where a GPS device on each bus would update a central computer every 30 seconds. They plan eventually to be able to send SMS updates to passengers' mobile phones, which would be pretty cool.
[What is RFID and] when will it appear in supermarkets?
Radio Frequency Identification (RFID) is an automatic identification method; tiny electronic tags are attached to an item, and these tags can be read remotely, within a range of a few metres. In Japan, the government wanted consumers to be able to track food right back to the producer, so tags are applied to the packaging of fruit and vegetables right after they have been picked and packed. RFID readers attached to mobile phones allow consumers to view information about the produce. Bring it on! Although I suspect the British government will cripple the technology in some way; I'm not particularly cynical about our government, but there's simply too many Sun and Daily Mail readers to let any technology that exciting into the country.
How many countries are there in the world?
According to a Wikipedia entry, there are 245 entities that are considered countries. Of the countries eligible to be members of the United Nations (i.e. sovereign states), all but one or two are. I say one or two, because it depends on how you define Taiwan's status as a country (in 1971 it was replaced in the United Nations by the People's Republic of China, but since 1991 has been actively trying to rejoin) . The other one is Vatican City which has chosen not to join.
-
19 May, 2007 at 22:40
0
Comments
-
Milky Way + Andromedia = Milkomeda
-
Astronomers have calculated that, in five billion years, the Milky Way and our closest neighbouring galaxy, Andromeda, will violently collide, creating a new merged galaxy, which has been dubbed Milkomeda. The two galaxies will (apparently) swing past each other in less than 2 billion years, then again 1.5 billion years after that, before merging 5 million years from now. Scientists have calculated that there is a 3% chance that the sun will defect to Andromeda during the second close pass, in which case viewers on Earth (assuming there's any left by that point) would see the Milky Way as a spiral in the night sky.
If you'd like to see what the "merger" might look like, watch this video. I find it oddly beautiful, given how cataclysmically destructive the whole thing is. It's funny to think that each of the two spirals of white contains hundreds of billions of stars.
-
19 May, 2007 at 00:01
0
Comments
-
Depressible buttons on drink carton lids
-

If you're anything like me (and God help you if you are), you'll have wondered why those little buttons on the plastic lids of soft drink cartons, such as you get from McDonalds, are never actually pressed by the fast food operative. I don't remember ever seeing them used.
However, while enjoying a nutritional* dinner at a Burger King "restaurant", I noticed that the "diet" button on one of my friend's drinks had, in fact, been pressed. After recovering from the initial feeling of jealousy that my button had never been pressed, so to speak, I realised it might have something to do with never ordering diet drinks. That said, some fast food chains have a more advanced drink lid configuration which allows for the flavour to be selected as well, and I've also never seen that used.
But apparently I've been living in the dark, and it's quite common in some countries, such as the United States, to have these buttons used on a regular basis. I can only dream.
If you think depressible buttons on plastic lids are boring, then check this out.
*Burger King helpfully provide a colour-coded table listing all the Good Things contained in each burger, so it must be nutritional.
-
10 May, 2007 at 23:22
3
Comments
-
Reversible quotations
-
Walking around the Imperial War Museum today, I saw this quote:
"Mankind must put an end to war, or war will put an end to mankind."
-- John F. Kennedy
I realised that this kind of quote, which I'll call a "reversible quote", is pretty popular. But all you really need to do is sit down and think of two concepts (i.e. "mankind" and "war"), join them with a verb (i.e. "end"), and then reverse it. Or, for another form, think of a verb (i.e. "fail") and a noun that can also be a verb (i.e. "plan"). Here's a few other quotes I found. I'm sure there's lots of others, feel free to suggest them and we can create a master list of reversible quotations.
"And so, my fellow Americans, ask not what your country can do for you; ask what you can do for your country."
-- John F. Kennedy
"Let us never negotiate out of fear. But let us never fear to negotiate."
-- John F. Kennedy
"A pessimist is one who makes difficulties of his opportunities and an optimist is one who makes opportunities of his difficulties."
-- Harry S. Truman
"And in the end it's not the years in your life that count. It's the life in your years."
-- Abraham Lincoln
"For those who like this sort of thing, this is the sort of thing they like." [eh?!]
-- Abraham Lincoln
"Peace is not absence of conflict, it is the ability to handle conflict by peaceful means."
-- Ronald Reagan
"He who fails to plan, plans to fail."
-- Unknown
It's not exactly a reversible quotation, but I couldn't resist:
"I just want you to know that, when we talk about war, we're really talking about peace."
-- George W. Bush
This all looks pretty easy to me, so I'm inspired to try some of my own:
"A photographer may think he is taking a photograph of a place, but really the photograph is taking the photographer... places."
-- Tim G. Jones
Okay, so it's not that easy. Let's try again using the second form.
"He who prizes the win, wins the prize."
-- Tim G. Jones
See? Instant eloquence guaranteed. It doesn't even need to be true.
-
09 April, 2007 at 22:20
3
Comments
-
Overriding the meaning of ~ in ASP.NET
-
Random techie discovery... You can override the meaning of the tilde (~) in paths in ASP.NET.
I often use the ~ so that it doesn't matter whether my web application is sitting at the root level or in a virtual directory. For example, I could include this as the href of a link tag to make ASP.NET write out the correct path of a stylesheet:
~/App_Assets/Css/Screen.css
I discovered today that you can override the meaning of that ~, to potentially point anywhere you like, such as a subfolder. See here for details.
-
05 April, 2007 at 17:35
0
Comments
-
Clever shit
-
Coming back home on the tube tonight, I met a man who tried to do the human race a favour by removing himself from the gene pool, using alcohol as his tool of choice.
I first noticed him when, on a nearly empty train, he lurched over to my area of the carriage and sort of hung over me. I glanced up at him, with a look calculated to convey a message along the lines of "my personal space ends about a metre beyond where you are now", which seemed to work because he backed off.
A few seconds later he decided to sit down - I say "decided", actually it had more to do with a sudden change in the train's velocity which caught him off balance. I had cunningly placed my man-bag on the seat next to me so he careered into the seat beyond that.
He then did his best to engage me in conversation. Conversation, that is, in the form of Antipodean grunts. I believe he used the word "brethren" a lot although I couldn't be sure. Again, cunningly, I had my iPod(tm) headphones in, so I could pretend I didn't hear anything.
At Earl's Court, the train filled with people, and a girl sat down on the previously empty seat between the hero of the story, and me. I instantly felt guilty, mainly because of the pungent odour he was emitting, and thought about offering to switch places with her, but it was too late. He had already started making his "moves", which consisted of the following conversation:
Him: "Hello gorgeous."
Her: "You stink."
Him: "Oh."
She got off at the next stop.
The rest of the journey was spent with him trying to come up with increasingly desperate insults, I assume directed at me, although because the motion of the train had a direct effect on his ability to stay in his seat, the insults could have been directed at the floor, it was difficult to tell.
He went through the basics: "you're bald" (true), "you're wearing a checked shirt" (also true), "Mr. iPod" (clutching at straws). My personal favourite, and the one that I feel summarises his ability to stay in the gene pool, was his critique on the copy of New Scientist that was I was reading:
"Clever shit."
-
25 March, 2007 at 23:26
2
Comments