# Having some trouble implementing D3DXComputeNormals... any hints/advice?

Misha Koshelev misha680 at gmail.com
Mon Jul 12 15:43:54 CDT 2010

```On Mon, 2010-07-12 at 14:21 +0200, Henri Verbeet wrote:
> On 12 July 2010 04:48, Misha Koshelev <misha680 at gmail.com> wrote:
> > Index Buffer:
> >
> >        11,21,12,
> >                {0,1,-0.5},
> >                {0,1,-0.45},
> >                {0.587785,0.809017,-0.5},
> >                        {0.00954915,0.0293893,0},
> >        20,30,11,
> >                {-0.587785,0.809017,-0.5},
> >                {-0.587785,0.809017,-0.45},
> >                {0,1,-0.5},
> >                        {-0.00954915,0.0293893,0},
> >        11,30,21,
> >                {0,1,-0.5},
> >                {-0.587785,0.809017,-0.45},
> >                {0,1,-0.45},
> >                        {-0.00954915,0.0293893,0},
> >
> > Averaged Normals:
> >
> >        11      {-0.107677,0.994186,0}  {-1.99491e-008,1,0},
> >
>
> The part of the mesh you're interested in looks like this:
>
> 20---11---12
> |   /|   /|
> |B / |A / |
> | / C| /  |
> |/   |/   |
> 30---21---22
>
> The "real" vertex normal at a given vertex would be {x, y, 0} for this
> shape (for an open cylinder anyway, for a closed cylinder you'd have
> {0, 0, 1.0} and {0, 0, -1.0} for the vertices from the caps), so the
> {-1.99491e-008, 1.0, 0.0} d3dx calculates is pretty close.
>
> Vertex 11 is part of the faces A, B and C. Notice that faces B and C
> (must) have the same face normal. If you simply calculate the average
> (mean) of the normals for faces A, B and C, the resulting vector would
> be biased towards B/C. That's what happens with your code. You can
> mitigate that by assigning weights to the faces based on the area of
> the triangles and the angle between the edges at the vertex you're
> interested in. I'd expect d3dx to do something similar to that.
Thank you Henri for the explanation. In fact it seems that this flag is
default on D3DXComputeTangentFrameEx:

D3DXTANGENT_WEIGHT_BY_AREA
Weight the direction of the computed per-vertex normal
or partial derivative vector according to the areas of
triangles attached to that vertex. Mutually exclusive
with D3DXTANGENT_WEIGHT_EQUAL.

If I specify D3DXTANGENT_WEIGHT_EQUAL, then the normal vectors I
calculate are indeed correct.

However, the quirk is that, unless I am doing something wrong, all three
triangles actually have the same area (I am using 1/2 of cross product
of two vertices in the triangle, which I believe should in fact be
correct - see below):

FLOAT ComputeArea(D3DXVECTOR3* p0,
D3DXVECTOR3* p1,
D3DXVECTOR3* p2)
{
D3DXVECTOR3 u = *p1 - *p0;
D3DXVECTOR3 v = *p2 - *p0;
D3DXVECTOR3 out;

D3DXVec3Cross(&out, &u, &v);
return 0.5*D3DXVec3Length(&out);
}

and resulting areas and vertices:

Vertex Buffer:

11	{0,1,-0.5,-1.99491e-008,1,0}

Index Buffer:

11,21,12,
{0,1,-0.5},
{0,1,-0.45},
{0.587785,0.809017,-0.5},
{0.309017,0.951057,0},
Area = 0.0154509,
20,30,11,
{-0.587785,0.809017,-0.5},
{-0.587785,0.809017,-0.45},
{0,1,-0.5},
{-0.309017,0.951056,0},
Area = 0.0154509,
11,30,21,
{0,1,-0.5},
{-0.587785,0.809017,-0.45},
{0,1,-0.45},
{-0.309017,0.951056,0},
Area = 0.0154509,

Averaged Normals:

0.0154509	{0.309017,0.951057,0}
0.0154509	{-0.309017,0.951056,0}
0.0154509	{-0.309017,0.951056,0}
11	{-0.107677,0.994186,0}	{-1.99491e-008,1,0},

Eesh...

(as always relevant code attached for the interested reader)

>
> However, note that for simple, regular shapes like these it's *much*
> simpler to just generate the normals together with the vertices. E.g.
> for a cylinder, you'd simply have normalize(x, y, 0.0), {0.0, 0.0,
> 1.0} and {0.0, 0.0, -1.0}, for a sphere you'd have normalize{x, y, z},
> etc.
Thank you. I have made a relevant patch for D3DXCreateCylinder test:
http://github.com/misha680/wine/commit/20ed58d7ba39554d2628c00b4268843b089cd745
using this simplified version.

I will focus on this simple version for now, as the goal is to implement
the shape functions, and not to actually necessarily implement
D3DXComputeTangentFrameEx, although that would be quite nice as well.

Thank you
Misha
-------------- next part --------------
A non-text attachment was scrubbed...
Name: test.zip
Type: application/zip
Size: 17958 bytes
Desc: not available
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20100712/4a7460cf/attachment-0001.zip>
```