More experimenting revealed that Microsoft's skinmesh api is less than satisfactory - it does not support rigid binding - you can load a rigid-bound , animated skinmesh, sure... but all kinds of api will fail if you hand them this frametree, such as D3DXFrameCalculateBoundingSphere - even if the skinmesh is still in the Bind pose.
I would have thought that rigid skinmeshes would have been supported since they are much simpler, could have been implemented using the same framework, and would act as a good introduction to the more complex smooth-bound skinmesh - or simply to illustrate how matrix transformations work in the context of a frame hierarchy.
Its so bad that if you actually want rigidly-bound skinmeshes (say, for a tank simulation), you're better off implementing your own skinmesh class (AGAIN, from scratch) specifically for this purpose.
Adding support for this to OA32's D3D_SkinMesh class is quite possible, however I reiterate my utter disappointment in Microsoft for throwing new users to the wolves in this way.
Don't they like people to use their stuff?
Posted on 2008-07-27 08:08:39 by Homer
So what are the stumbling blocks in implementing rigid animated 'skinmesh' ?
Well, for a start, we don't get any skinning information for our MeshContainer(s).. and I've mentioned that we must be careful not to use certain api such as D3DXFrameCalculateBoundingSphere - we'll have to use per-mesh Bounds and maybe implement our own animated boundingsphere unioning method (made me think of onion rings for some reason).

So what are we missing out on?
Skinning information has two things in it:
-list of Bones which affect the (contained) Mesh.
-UpdateSkinnedMesh method which transforms the BindPose vertices according to the PROVIDED transform matrices.

Indirectly, this means that the AnimationController does NOT affect vertices - its only animating the BONES... and for a Rigid animation, that ALL WE WANT.
And the list of Bones affecting each (contained) Mesh? We don't need it - in a rigid binding, each mesh that is being animated is associated with exactly one Bone.

So - what DO we need to do?
Thankfully, not much... its not a matter of what we must do, its a matter of what we must NOT do :)
The AnimationController is directly messing with the array of bone matrices, and so after our typical 'concatenation' recursion, we already have our set of Bone-To-World matrices, all nicely animated, and ready to use.
All we need to do is update the animationcontroller, update the frame matrices (matCombined), and then Render the MeshContainers.

Well, I'm pretty sure that's right.
Interestingly it seems that either noone else has tackled this problem, or its so plainly obvious that it defies description (literally) as I could not find a single reference to rigidly-bound animated mesh hierarchies using .x files :)
Posted on 2008-07-28 06:32:53 by Homer
More weirdness?

Smooth Binding : During the loading of a MeshContainer, we Clone its Mesh object.
Then at runtime, we use the original Mesh as a vertex Source, and the Cloned one as a Target, and via our Skinning Information object, produce our warped and bent mesh for Drawing.. so we draw the Cloned one.

Rigid Binding : We never got any Skinning info .. we never Cloned the original Mesh. At runtime, if we try to Draw the original Mesh, we'll crash - the DrawSubSet function pointer is illegal... its the same legal object we would have otherwised used as a Vertex and Cloning source!!

Whats going on here then?

Did Microsoft write a COM object that doesn't comply with the COM standard?

Have you seen another example of Microsoft (or another company) breaching a standard which they inflicted apon the rest of us?

After all, I am not doing anything I shouldn't be doing, yet the so-called standard-compliant object is not behaving as expected.
Posted on 2008-07-28 07:25:40 by Homer
Yes, Steinberg's ASIO  COM object breaches all COM standards. Using that object in the standard COM way would lead to blue-screen of death (on Win2k/XP !!). The example code to use the object is in C++, so C++ absolutely allows you to breach all COM standards.
Solved that problem by disassembling working C++ samples and locating the oddities in calling conventions. 3 or 4 different calling conventions were being used in the same object.
Posted on 2008-07-28 07:33:19 by Ultrano
I have more bad news.

Much earlier in the frameword, in the ID3DXAllocateHierarchy.CreateMeshContainer method to be precise, I am Cloning my original Mesh from the transient XFileLoader data... this call is ALSO failing, its says D3DERR_INVALIDCALL but that is simply rubbish because theres nothing wrong with the call itself, its merely that we're now attemping to load a Rigid-bound mesh instead of a Smooth-bound one.

So - the problems begin way back in the XFile Loader api function that I am using (and probably in its variants).
I'm able to load all the animation data, all the frame hierarchy, everything EXCEPT that I am being fed illegal Mesh objects right from the very start... I'm being handed object pointers for these Meshes, but they're simply not valid... they do NOT point to instances of the expected interface.

I think I can get around this too, if I cheat a little..
What I'll do is export all the pieces of Mesh as static meshes.
Then when they fail to load, I'll try to load them AS static meshes, and INSERT them into my meshcontainers by hand... Now if THAT doesn't work, I'll get cranky :)

This isnt as bad as it sounds, because the goal was to create Breakable skinmeshes, and for that, we really need separate static meshes for the 'broken' pieces.
It just means we have a situation of 'all Rigidly bound mesh hierarchies are potentially Breakable' which sounds kinda fun and useful for games.

And I don't see why I can't still also apply the Breakability stuff to Smooth bound meshes as originally intended... they just don't have the Loading problems I'm seeing.



Posted on 2008-07-28 08:14:40 by Homer
Ah, finally getting somewhere.. the problem was that the problem Meshes don't export an FVF - we have to use the slightly more complex 'Decl' (vertex declaration) way of describing our vertex format... and there's a Decl-based version of CloneMesh.

Having added code to ID3DXAllocateHierarchy.CreateMeshContainer to detect the NULL FVF and switch to using Decl-based cloning of the transient mesh interface, and checking the return value, I see success - this worked.
Now the D3D_SkinMesh class should be seeing valid Meshes, but its not aware of the fact that we might be using the Decl method, so we completely and (assumed) successfully load the skinmesh, then we return to D3D_SkinMesh , only to crash and burn, which is just fine by me.

So all of these problems I've been having with Rigid-bound skinmeshes are based on the fact that the modeller used the newer Decl way of describing FVF :|
This is stuff I covered already in D3D_Mesh  :cry:
But it gave me somewhere to go for working code to implant and fix the problem :P

Happy Day, although still in a state of flux, the D3D_SkinMesh class just received a poignant makeover, which should be a big help with models that were actually created during this decade :P

Posted on 2008-07-28 09:11:39 by Homer
After I got the troublesome rigidbound skinmesh model to load successfully, I found it wouldn't render anything onscreen, so I went right to the source and asked the horse.
The material didn't have any Ambience - fixed.
To prove that it was renderable, I exported the static mesh, and tried to load and render it as a static mesh... again it would not render... worse, D3D_Mesh was crashing!
So I made some small improvements to D3D_Mesh.
It can now draw Materials that don't have any Texture.
At last I can see the model, at least in static form.
Since it just has color and no texture, and since theres no Lighting in my environment, it looks quite plain and the details are hard to make out ... I should probably think about adding a default light that is glued to the Camera, and maybe later some cool and simple shaders like Phong which make textureless meshes much more visually appealing and can give a false impression of smoothness especially when the polygon count is actually low.

Now back to the D3D_SkinMesh class :)
Posted on 2008-07-28 23:34:59 by Homer
I found a further problem with importing of this problematic skinmesh.
Not all of its component meshes have a Material!!!

ID3DXAllocateHierarchy.CreateMeshContainer wasn't expecting THAT!
I've added code to issue a Warning when the mesh has no Material.
But really I should be assigning a Default Material in this situation.

The more I work on this, the more weird and wonderful models I can load and render.
And in the real world, it is more often the case than not, that a given Model has been created without thought to the minimal requirements of a rendering engine.
So its up to us, we cannot assume anything about a model, we should check it conforms to our requirements, and if it doesnt, we should manipulate it at loadtime so that it does.

Bit quiet around here lately :P
Posted on 2008-07-30 00:11:21 by Homer
I found an interesting bug in Microsoft's D3DXLoadHierarchyFromX api function.
OK, its not so much of a bug as a 'feature' ...

If you have a MeshContainer associated with the Root Frame, it wont be released... you'll crash and burn.

Say we had 20 meshes in our model, and we named them nicely mesh_1 thru mesh_20.
We see them being loaded in numerical order.
But when we destroy our frametree, the first meshcontainer to be destroyed will be 2 (it should be 1) ... then theyll get destroyed in order, then in the 20th call to DestroyMeshContainer we shall be handed bad parameters.

Then baby go boom fall down.


Posted on 2008-07-30 22:14:39 by Homer
I've just removed all mention of FVF from the D3D_Mesh class.
Now it only uses the newer 'Decl' method of describing a flexible vertex format.
It uses more memory, and its potentially a lot slower than the old system.
So why did I do it? Why not use the old FVF when it is available?
Because we need to use the Decl method when working with SHADERS.

I'm expecting to be writing some simple pixelshaders in the next few days, and I'll want to apply them to my meshes.
Posted on 2008-07-31 02:43:19 by Homer
A new object called D3D_Shader has been written to implement both Vertex and Pixel shaders.
Demo was created to test the new object, and to test recent changes to D3D_Mesh in regards to supporting shaders.
Everything works :)

I'm pretty sure this file will make the next version release of OA32.

Ah - maybe I spoke too soon.

In regards to setting the values of input Constants, in this case VertexShader:
The ID3DXConstantTable.SetMatrix method is leaving the stack unbalanced (by one dword), yet the interface definition looks to be correct.
I think I'll confer with Biterider in regards to this anomoly, maybe I'm just not seeing the error in the def.

Nevermind, I found it - there's been one new Method added to that interface.
I've corrected the D3DXShader.inc

Now everything works 100% - the brave new world of shaders and gpu programming is at the fingertips of the OA32 user.

Posted on 2008-07-31 22:20:33 by Homer
I need a surface for my characters to walk on, and for playing with physics some more.
I have not found anything more cool or useful than the Terrain class I wrote two years ago.
It does the vertex manipulation (heightmapping) on the cpu so the physics code has access to the terrain geometry, and it can do the texture blending on the gpu via a pixelshader.
Its based on a quadtree which encodes LOD detail, terminating early in 'flat' regions, and switches the LOD based on an error metric that takes view distance into account.
The only thing it doesn't currently do is geomorphing, and it would be nice if I could blend more than 4 textures.

So my next job will be to revise my Terrain code, implant it in my GameClient framework, and write enough networking support to allow clients to connect to a server, cruise around in 3D and paint the terrain blendmap and heightmap, see each other and show the changes being made by all clients.

That will effectively be my first development tool, and a genuine milestone in more ways than one, as I am not aware of any other 3D game editor that allows multiple clients to edit the same virtual space in this fashion, it is therefore a bleeding edge tool, and no doubt someone out there who works in the industry will steal this idea and claim it as their own.
So be it, just mention me somewhere as a courtesy and I'll be content.



Posted on 2008-08-02 02:03:45 by Homer
Do you guys remember my 'splat' realtime 3D terrain painting demo?
I've just reworked the code to reflect changes in OA32's D3D framework (I could probably keep going too), and I've implanted the new objects in my GameClient demo project.
The idea is, as mentioned previously, to implement  a networked terrain editor tool, and the beginnings of a game network protocol.
I've deprecated the 'FF' render code in favor of pixelshader code, implemented as an embedded D3D_Shader object.
I'm also keen to expand the number of 'blender source' textures from 4 to 8.

The lack of recent posts is appalling.
What are you people up to?
I see that my pinned Physics post gets daily views now.
And nobody has a word to say :D

Biterider - I added a method to D3D_Camera called 'DistanceToPoint'.
Its function is obvious, and its location was considered.
Consider it a poor mans version of frustum culling, when we just wanna know how far the Camera is away from some point.
I guess it really should be 'IsPointVisible" :)



Posted on 2008-08-03 05:19:08 by Homer
Spent today rewriting my old Terrain class in order to implement a better Tesselator.
My old terrain was based on a TriangleFan which was recursively cut into four (ie, a quadtree).
The new one is based on two 'binary Triangle Trees' forming a Quad at the root level, and is using an algorithm similar to ROAM in order to recursively refine those two root triangles.
This gives us a slightly improved tesselation, and slightly fewer triangles need to be drawn.
Slightly faster rendering, and slightly better geometry, it seemed worthy.

Biterider is having problems building the D3D_Shader demo, so I'll probably spend the rest of today's free time just nailing that issue... it's perhaps the second time we've had to do this, I'm just concerned what we'll find because he's having problems with NEWER libs, and I'm NOT having problems with older ones.... so theres likely more changes in the Headers to account for.

Posted on 2008-08-04 06:58:55 by Homer
We were able to quickly narrow the problem down to the D3DX9.lib file , which is version-dependant and links to files with names such as D3DX9_30.dll (2004) and D3DX9_35.dll (August 2007) and D3DX9_36.dll (November 2007).

We find that the very old 2004 file works just fine.
But when we call certain functions using the newer lib, linking to the newer dlls, they fail.
We get NOT IMPLEMENTED errors.
BOOOO, Microsoft.
Shame on you, both debug and retail builds are missing functionality where they should fall back on the older versions.
I'm currently installing the June 2008 SDK, to see if they ever got around to fixing it.

Posted on 2008-08-04 07:41:44 by Homer
While I was waiting on the 2008 SDK to download, I decided to doublecheck the August 2007 version of D3DXShader9 against our OA32 header file.
There was heaps of stuff missing, among them was a particular flag:D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY

This flag, when selected, forces ps_1_x HLSL files to get compiled as ps_2_0 :D

For those who are as impatient as I am, I have attached a couple of files.

With these changes, I can build against the d3dx9_35.dll :)

Tomorrow, I promise to update this file again, against the JUNE 2008 header.
After tomorrow, we should all switch to the June 2008 Libs and DLLs.
I believe that is version 38.

Have a nice day :)
Posted on 2008-08-04 09:47:17 by Homer
Yesterday I got my Terrain code to draw something again (using a pixelshader to perform pixel-perfect alpha-splatting of textures).
But I still wasn't happy with the tesselator. Apparently neither is the spellchecker.
So I trashed my integer based code in favor of a float-driven scheme.
Now I'm using bilinear multisampling of the heightmap pixels, and generating vertices as I go rather than generating them as a flat array in advance of tesselation.... man, we're likely to generate less vertices than we have pixels, thats the whole point of the exercise - less triangles where they are not needed.
Tomorrow should bring me back on track, but the bottom line is that I spent my few small hours of coding time today reinventing code I wrote a long time ago.
Back then, each project was unique, its components were not easily transplanted.
I've grown up a lot in terms of design.
Instead of building slip-stone walls, I've learned to build them from regular bricks.

Biterider is going to release a new version of OA32 very soon, which will contain some of the objects I've been talking about... I hope he includes the new SkinmeshInstance object (which supports attachment of static mesh instances to the animated skinmesh instance), because it's gamedev gold, and it wouldn't take a lot of work to make an impressive demo or small game just based on that class.
Posted on 2008-08-06 10:23:08 by Homer
The terrain engine is working, but with no Batching of primitives and with no visibility culling and no view dependent LOD culling, the framerate is terrible.
I'm just going through the same stuff that I did two years ago :|

I guess the next step will be to introduce simple camera based culling, then reimplement the 'variance' stuff for LOD culling.
Sigh.

On the bright side, I've improved D3D_VertexBuffer.Resize and will make similar changes to D3D_IndexBuffer.
Posted on 2008-08-08 00:51:09 by Homer
Having implemented batching of primitives with 32bit indexing (I really dont need 32, 16 would have been adequate) , I scored an immediate speed increase of something over 200 times.. yes, 20,000 percent faster, thats the stuff.
And I still haven't implemented the heuristic for view based dynamic LOD (or any other kind of culling) :)

Think I'll give myself :thumbsup: two thumbs up :thumbsup:


Posted on 2008-08-10 20:12:52 by Homer
Today I'll briefly describe the algorithm used to tesselate the terrain, and perhaps in a few days I'll talk about the visibility based realtime dynamic Level Of Density rendering scheme.

Before reading on, please forget what you know (or think you know) about heightmaps.
This system isn't strictly based on a uniform grid, and can be easily adapted to work on massive heightmaps of any dimension.

Take a pen and some paper, and draw the four points of a square.
Now draw one triangle between three of them. Later we can make another triangle here, forming a Quad, but let's just concentrate on one triangle for now.

See that the triangle is a right angled triangle, look at the edge which forms the Hypotenuse of the triangle.
Mark a new point half way along the Hypotenuse edge.
Now draw a line from the new 'hypotenuse midpoint' to the point that opposes the hypotenuse (its the only one that isnt on an existing edge) such that we have split our original triangle into two triangles.

See that each child triangle is ALSO a right angled triangle, with a Hypotenuse.
Repeat the process until you get bored - you could keep going forever, in theory.

I keep going until I reach the 'sub-pixel' level of my heightmap resolution...
I am tesselating the terrain by sampling the four corners of the heightmap, using floating-point coordinates instead of integers. I then perform the above steps in order to create a binary tree of ever-diminishing triangles, and then do it all again to create two triangle-trees whose root triangles form a Quad.

I am using the Pixelmap.GetVirtualPixel function to perform bilinear-filtered pixel lookups with floating-point pixel coordinates, this is slower than integer but allows us to sample 'between pixels' and so allow the engine to create a more finely grained tesselation than would otherwise be possible - and also allows us to use heightmaps of arbitrary dimension.

Since the building of this tree is a preprocess, the extra time it takes is not important (or noticeable, really).

If you can't understand a word I just said, you're probably in the wrong place :P

Posted on 2008-08-11 06:38:48 by Homer