Sign in to follow this  
NickGravelyn

Reversing Mesh Normals

Recommended Posts

Culling doesn't care about the normals, it only cares about the winding order.

Thus, you should (ideally) build the box with inverted faces in your modeler, before you export it. However, if that's not an option, then you can change the culling mode render state, to cull away CW faces (such that CCW faces get rendered).

Of course, this means that the normals will point the wrong way if you want to actually do lighting, so in that case, you ALSO need to invert the normals. Typically, you do that by locking the vertex buffer, and walking the buffer, multiplying each normal vector by -1. This is easy if you know C++ and pointers; it's harder if you want to use Managed DirectX; you pretty much have to use unsafe code.

If that's all too cumbersome (manage winding order and updating normals), you can also lock the index buffer, and swap the two first indices of each triangle -- if the triangle index list is 0,1,2, 2,3,0 (for two triangles making a quad), you can swap the first two of each triangle to make it 1,0,2 3,2,0. Then call CalculateNormals to re-calculate the new normals if you want lighting to work right.

Share this post


Link to post
Share on other sites
Oh, I already took care of culling by simply turning it off (a temporary fix, really). I just want to try my hand at shadows and needed a quick way to get an area to project onto so I used the D3DXCreateBox() function to get my box. I'll try the pointers and reverse the normals. I don't need to change any vertices or indices at all.

Share this post


Link to post
Share on other sites
One way of doing this is using the CD3DXCrackDecl class which can read and write arbitrary elements from a vertex stream in a very flexible way. The class can be found in the UVAtlas sample directory.

Here's an example that uses it to invert all the normals in the vertex buffer:


void *pVertexData;
mesh->LockVertexBuffer(D3DLOCK_NOSYSLOCK, &pVertexData);
D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
mesh->GetDeclaration(decl);
CD3DXCrackDecl cd;
cd.SetDeclaration(decl);
cd.SetStreamSource(0, pVertexData, 0);

for (int i=0; i<mesh->GetNumVertices(); i++)
{
D3DXVECTOR3 norm;
cd.DecodeSemantic(D3DDECLUSAGE_NORMAL, 0, i, (float*)&norm, 3);
norm *= -1.0f;
cd.EncodeSemantic(D3DDECLUSAGE_NORMAL, 0, i, (float*)&norm, 3);
}
mesh->UnlockVertexBuffer();

Share this post


Link to post
Share on other sites
from your post you said that you are using D3DXCreateBox. So the easiest way to do what you are trying to do is.

First of all D3DXCreateBox will give you a mesh wchich has this attribute

D3DXVECTOR3 position;
D3DXVECTOR3 normal;

so basically the normal will be the second coordinate.

The next step you want to do is lock the vertexbuffer and modify each normal like so.

PBYTE p=NULL;
mesh->LockVertexBuffer(0,(LPVOID*)&p);
for(int i=0;i<mesh->GetNumVertices();i++)
{
//Skip the position
p+=sizeof(float)*3;
//Modify the Normal.
(*(float*)&*p)=(*(float*)&*p)*-1;p+=4;
(*(float*)&*p)=(*(float*)&*p)*-1;p+=4;
(*(float*)&*p)=(*(float*)&*p)*-1;p+=4;
//Go to the next vertex
p+=D3DXGetFVFVertexSize(mesh->GetFVF())-24;
}
mesh->UnlockVertexBuffer();

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this