D3DXMesh.ComputeNormals() causes exception...

Started by
8 comments, last by Toolmaker 18 years, 7 months ago
I'm currently loading a few converted models using the D3DXMesh(Mind you, I'm using C# and Managed DirectX, but it's just a layer over the C++ libraries). When I load the X file in the Microsoft X viewer, it works fine, however, when I load it myself and call ComputeNormals() on the model, I get this as result: 18446744071704021100 : D3DERR_INVALIDCALL I looked it up in the error viewer, and well, not much help there. This is my code, but I can't see what's wrong with it:

			ExtendedMaterial[] mtrls = null;

			mesh = Mesh.FromFile(@"c:\klingon.x", MeshFlags.Managed, engine.Device, out adj, out mtrls);

			materials = new Material[mtrls.Length];
			textures = new Texture[mtrls.Length];

			for (int i = 0; i < mtrls.Length; ++i)
			{
				materials = mtrls.Material3D;
				textures = null;
			}

			if ((mesh.VertexFormat & VertexFormats.Normal) != VertexFormats.Normal)
			{
				Mesh tmp = mesh.Clone(mesh.Options.Value, mesh.VertexFormat | VertexFormats.Normal, engine.Device);
				tmp.ComputeNormals(adj);

				mesh.Dispose();
				mesh = tmp;
			}

I tried ComputeNormals with and without adjacency information, but in both cases, it just throws an exception. For those interested in the model, you can find it here. It's both the original PRJ model and the converted X model(Exported using the 3ds max X exporter). If I don't compute the normal information, the ship shows up completely white in game, which seems a bit weird to me... Toolmaker

Advertisement
The compute normals function uses the index buffer (or at least it did with DX8).
Make sure you don't have any index out of range.
I discovered it works without computing the normals. I then experimented with scaling the ship up and down, and discovered it goes white when I scale it down too much.

So, I removed the scaling, and it showed up fine, but still looked WEIRD. Like below:


I added 1 light to the scene, like this:
	dev.Lights[0].Type = LightType.Point;	dev.Lights[0].Position = new Vector3(0.0f, 30.0f, 0.0f);	dev.Lights[0].Diffuse = Color.White;	dev.Lights[0].Ambient = Color.White;	dev.Lights[0].Range = 10000.0f;	dev.Lights[0].Attenuation0 = 0.1f;	dev.Lights[0].Update();	dev.Lights[0].Enabled = true;


I removed the light and set dev.Render.Ambient = Color.White, but my entire scene goes black when I do that. And the higher I move my light(But increasing the 30 to 500), the more white the ship ends up.

I have NO IDEA what I did wrong, or how to solve this...

Toolmaker

when you tried to call ComputeNormals and had the function throw up an exception, what did the debug spew say? Whenever a DirectX function fails, it always prints the reason why it failed to the debug spew. Make sure you're using the Debug Runtime when developing DirectX applications. If you're not sure what I'm talking about, see the Forum FAQ.

From the screenshot you posted, it looks like there is something wrong with the mesh. Try calling ValidMesh and CleanMesh on the model to spruce things up a bit.

neneboricua
Ok, I added calls to Validate() and Clean(), but I still get an exception on calling ComputeNormals.

My new Mesh loading function now looks like this:
		public static Mesh LoadMesh(string file, Engine engine, out Material[] materials, out Texture[] textures)		{			GraphicsStream adj = null;			ExtendedMaterial[] mtrls = null;			Mesh mesh = null;			mesh = Mesh.FromFile(file, MeshFlags.Managed, engine.Device, out adj, out mtrls);			materials = new Material[mtrls.Length];			textures = new Texture[mtrls.Length];			for (int i = 0; i < mtrls.Length; ++i)			{				materials = mtrls.Material3D;				if (mtrls.TextureFilename != null && mtrls.TextureFilename != string.Empty)				{					try					{						textures = TextureLoader.FromFile(engine.Device, mtrls.TextureFilename);					}					catch (Exception e)					{						Console.WriteLine(string.Format("Failed to load {0}", mtrls.TextureFilename));						textures = null;					}				}			}			// Validate our mesh			string errorsAndWarnings = "";			mesh.Validate(adj, out errorsAndWarnings);			System.Console.WriteLine(errorsAndWarnings);			// Let's clean our mesh a bit			mesh = Mesh.Clean(CleanType.Simplification | CleanType.Optimization | CleanType.BackFacing, mesh, adj, adj, out errorsAndWarnings);			System.Console.WriteLine(errorsAndWarnings);			// Add in normal data to our model			if ((mesh.VertexFormat & VertexFormats.Normal) != VertexFormats.Normal)			{				Mesh tmpMesh = mesh.Clone(mesh.Options.Value, mesh.VertexFormat | VertexFormats.Normal, engine.Device);				tmpMesh.ComputeNormals();				mesh.Dispose();				mesh = tmpMesh;			}			return mesh;		}


No idea what's wrong...

EDIT: I haven't found a way to actually obtain the Debug output from the debug runtime. I have set the debug output to maximum and I use the debug runtimes, but MSVS doesn't show any debug output. Perhaps this has to do with Managed DirectX.

Is there a way to enable the debug output under C#?

Toolmaker

Bumping

Make sure you have both Direct3D Debugging and "Enable Unmanaged Debugging" on. The downside of this is that it brings your programs to a screeching halt, in my experience the unmanaged debugging slows down the game to the point that it isn't acceptable for normal development work, only when you know there is an error to catch.
Turring Machines are better than C++ any day ^_~
I couldn't get D3D debug info to appear in VC# 2005 Express Edition debugger, but luckily I found DebugView when browsing forum FAQ.
Quote:Original post by Toolmaker
I discovered it works without computing the normals. I then experimented with scaling the ship up and down, and discovered it goes white when I scale it down too much.

The normals get scaled as well and won't be normalized anymore. That's the problem. Set NormalizeNormals in the renderstate to true and the effect should disappear.

Regards,
Andre

Andre Loker | Personal blog on .NET
Quote:Original post by intrest86
Make sure you have both Direct3D Debugging and "Enable Unmanaged Debugging" on. The downside of this is that it brings your programs to a screeching halt, in my experience the unmanaged debugging slows down the game to the point that it isn't acceptable for normal development work, only when you know there is an error to catch.


It starts up EXTREMELY slow, but it shows the debug output after all. Problem is, it throws an exception on the ComputeNormals, but doesn't output any error.

Thanks for the info on how to get output info, rating++.

This topic is closed to new replies.

Advertisement