Intel sponsors gamedev.net search:   
Excursions into the UnknownBy Mike.Popoloski      

Thursday, December 17, 2009
Currently in SlimDX our Matrix class exposes a large set of methods to create projection matrices. This closely mirrors the methods provided by D3DX, which was the original choice behind the design. While moving everything to C# and away from D3DX, I have a chance now to do some refactoring, so I thought I'd try it out and see what came of it.

This is the set of methods that we have currently:
public static void OrthoLH(float width, float height, float znear, float zfar, out Matrix result)
{
}

public static Matrix OrthoLH(float width, float height, float znear, float zfar)
{
}

public static void OrthoRH(float width, float height, float znear, float zfar, out Matrix result)
{
}

public static Matrix OrthoRH(float width, float height, float znear, float zfar)
{
}

public static void OrthoOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
{
}

public static Matrix OrthoOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar)
{
}

public static void OrthoOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
{
}

public static Matrix OrthoOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar)
{
}

public static void PerspectiveLH(float width, float height, float znear, float zfar, out Matrix result)
{
}

public static Matrix PerspectiveLH(float width, float height, float znear, float zfar)
{
}

public static void PerspectiveRH(float width, float height, float znear, float zfar, out Matrix result)
{
}

public static Matrix PerspectiveRH(float width, float height, float znear, float zfar)
{
}

public static void PerspectiveFovLH(float fov, float aspect, float znear, float zfar, out Matrix result)
{
}

public static Matrix PerspectiveFovLH(float fov, float aspect, float znear, float zfar)
{
}

public static void PerspectiveFovRH(float fov, float aspect, float znear, float zfar, out Matrix result)
{
}

public static Matrix PerspectiveFovRH(float fov, float aspect, float znear, float zfar)
{
}

public static void PerspectiveOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
{
}

public static Matrix PerspectiveOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar)
{
}

public static void PerspectiveOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
{
}

public static Matrix PerspectiveOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar)
{
}



As you can see, there are quite a few. We double each method to provide a ref version for those who want very high speeds and a normal version for people who don't care as much.

My new proposed version looks like this:
public static Matrix PerspectiveFov(Handedness handedness, float fov, float aspect, float znear, float zfar)
{
    float yScale = (float)(1.0 / Math.Tan(fov / 2.0f));
    float xScale = yScale / aspect;

    float width = 2 * znear / xScale;
    float height = 2 * znear / yScale;

    return Projection(ProjectionType.Perspective, handedness, -width / 2.0f, width / 2.0f, -height / 2.0f, height / 2.0f, znear, zfar);
}

public static Matrix Perspective(Handedness handedness, float width, float height, float znear, float zfar)
{
    return Projection(ProjectionType.Perspective, handedness, -width / 2.0f, width / 2.0f, -height / 2.0f, height / 2.0f, znear, zfar);
}

public static Matrix Orthographic(Handedness handedness, float width, float height, float znear, float zfar)
{
    return Projection(ProjectionType.Orthographic, handedness, -width / 2.0f, width / 2.0f, -height / 2.0f, height / 2.0f, znear, zfar);
}

public static Matrix Projection(ProjectionType type, Handedness handedness, float left, float right, float bottom, float top, float znear, float zfar)
{
    Matrix result = new Matrix();
    result.M11 = 2.0f / (right - left);
    result.M22 = 2.0f / (top - bottom);
    result.M33 = 1.0f / (zfar - znear);
    result.M43 = znear / (znear - zfar);

    if (type == ProjectionType.Orthographic)
    {
        result.M41 = (left + right) / (left - right);
        result.M42 = (top + bottom) / (bottom - top);
        result.M44 = left;
    }
    else
    {
        result.M11 *= znear;
        result.M22 *= znear;
        result.M33 *= -zfar;
        result.M43 *= zfar;
        result.M31 = (left + right) / (left - right);
        result.M32 = (top + bottom) / (bottom - top);
        result.M34 = 1.0f;
    }

    if (handedness == Handedness.Right)
    {
        result.M31 *= -1.0f;
        result.M32 *= -1.0f;
        result.M33 *= -1.0f;
        result.M34 *= -1.0f;
    }

    return result;
}



Note that I haven't listed the ref overloads here. With ref overloads, the new method would have 8 total functions, whereas the old method has 20. Now, ignoring the actual creation of the matrix in there, since I haven't quite tested it yet, which design do you think is better? Here is my thought process so far:

First, the pros. The new method has drastically less functions to maintain, and everything boils down to the one actual method for implementation. Additionally, it better follows the design guidelines of .NET by not encoding functional information into the name and instead allowing users to specify it via enum. I find it to be a slightly cleaner method over all.

Now the cons. The new method is slightly less optimal due to the extra branches occurring. This is less bad than it seems, however, since creating projection matrices is never done more than several times over the course of a frame, and usually much less than that, so it's unlikely to make any sort of impact on performance. If this were determined to be a huge issue, I have a slightly more hackish version of Projection that avoids the branches by making tricky use of the enum values Also, the new version breaks all existing code using SlimDX, since we'd be relying on these slightly new names. As said before, we have a new "2.0" version coming that will encapsulate all of these breaking changes, but it could still be considered an issue.

Ultimately the pros and cons nearly balance each other, and I think it comes down to a style issue, so I'm trying to take a poll here. Which do you prefer? I've talked to several people already, and the responses have been all over the board. Some people like the new methods and say the style is cleaner, some people want the old ones back, and a few people have said that the new method is better but they still prefer the old one due to stylistic reasons. How about you? What's your opinion?

Comments: 4 - Leave a Comment

Link



Monday, December 14, 2009
There's no doubt about it, SlimDX has finally caught up to DirectX in terms of features. Sure, there are still little things here and there, but for the most part we cover every major part of the DirectX SDK, as well as several secondary libraries deemed beneficial for multimedia and game development. Once our next release hits (probably around February, if our covert intel is correct), things should be pretty stable in D3D11 land as well. Of course there is still plenty of bug fixing, documenting, and sample writing to do, but you don't plan future library development based upon maintenance tasks like that.

So we started postulating as to future plans for our little brainchild which is now all growed up. We've gathered up a list of changes we'd like to make, big ones that mean breaking changes for just about all our users, which we had held off on before in favor of library stability. These changes will be part of what we are internally referring to as our "2.0" release. The SlimDX version number is already higher than that, but this will be the first major shift in the library since we came out beta several years ago.

What might this "2.0" release entail? Well for starters, Josh has been chomping at the bit to switch us over to using interfaces instead of concrete classes as much as possible. This facilitates unit testing not only for ourselves but for our clients as well. While this requires a huge set of changes across the library, users will face only mild breaking changes where we end up returning an interface where previously we had a concrete class, which will require an additional cast to fix.

Ever since things slowed down on SlimDX, the team has been branching out to other side projects. Promit started SlimTune, a free profiler for managed applications. Josh started an overhaul of the sample framework, and has only recently started work on SlimBuffer, which will contain a refactored version of the DataStream functionality currently in SlimDX. "2.0" will depend on this new library for its native memory management needs.

Washu and I started work on SlimGen, which is a tool that injects ASM into a managed assembly at runtime, allowing us to use hand-optimized SIMD instructions directly from managed code with no interop overhead. This will play hand-in-hand with SlimMath, which is an all-managed implementation of the math functionality currently living within SlimDX. SlimDX "2.0" will rely on this library, and external projects can make use of the math functionality without needing the rest of SlimDX, or indeed even needing to be on Windows at all.

Finally, mesh and model handling is a common complaint I see across many different APIs, so I started work on SlimMesh, which will handle the loading of 3D models from several different formats in an API agnostic manner. This will include D3D9, D3D10, and D3D11 renderers via SlimDX to make it usable out of the box, but I suspect users of libraries like OpenTK might find it useful as well.

So yes, we're all still hard at work. The SlimDX group is rapidly becoming a multimedia middle-ware group SlimDX might be all growed up, but the rest of us are just getting started.

PS. Promit was a genius picking out the "Slim" name for SlimDX. It's a great branding tool and easy to slap on to almost any project.

Comments: 4 - Leave a Comment

Link


All times are ET (US)

 
S
M
T
W
T
F
S
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

OPTIONS
Track this Journal

 RSS 

ARCHIVES
December, 2009
August, 2009
July, 2009
June, 2009
May, 2009
March, 2009
January, 2009
December, 2008
November, 2008
October, 2008
August, 2008
July, 2008
June, 2008
May, 2008
April, 2008
March, 2008
February, 2008
October, 2007
September, 2007