Bug in CMeshManipulator.cpp, Irrlicht Release 1.7.2

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
Squarefox
Competition winner
Posts: 117
Joined: Tue Aug 19, 2008 6:46 pm
Location: Delta quadrant, Borg nexus 0001
Contact:

Bug in CMeshManipulator.cpp, Irrlicht Release 1.7.2

Post by Squarefox »

Hello,

I think I've discovered a bug in CMeshManipulator.cpp (Irrlicht Release 1.7.2)

Function: void CMeshManipulator::recalculateNormals(IMeshBuffer* buffer, bool smooth, bool angleWeighted) const
Line: 102-107

old code:

Code: Select all

 
if (angleWeighted)
        normal *= getAngleWeight(v1,v2,v3);
 
buffer->getNormal(idx[i+0]) += normal;
buffer->getNormal(idx[i+1]) += normal;
buffer->getNormal(idx[i+2]) += normal;
 
The getAngleWeight-Method gives back a weight for each vertex. So it should be used this way:

Code: Select all

 
core::vector3df angleWeight(1.f,1.f,1.f);
 
if (angleWeighted)
        angleWeight = getAngleWeight(v1,v2,v3);
 
buffer->getNormal(idx[i+0]) += angleWeight.X * normal;
buffer->getNormal(idx[i+1]) += angleWeight.Y * normal;
buffer->getNormal(idx[i+2]) += angleWeight.Z * normal;
 
Greetings,
Squarefox
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: Bug in CMeshManipulator.cpp, Irrlicht Release 1.7.2

Post by hybrid »

Yes, that seems correct. The docs of getAngleWeight is pretty sparse, but the other function does this like that as well. I guess we should make some test case for these methods sometimes.
Squarefox
Competition winner
Posts: 117
Joined: Tue Aug 19, 2008 6:46 pm
Location: Delta quadrant, Borg nexus 0001
Contact:

Re: Bug in CMeshManipulator.cpp, Irrlicht Release 1.7.2

Post by Squarefox »

Code: Select all

static inline core::vector3df getAngleWeight(const core::vector3df& v1,
                const core::vector3df& v2,
                const core::vector3df& v3)
{
        // Calculate this triangle's weight for each of its three vertices
        // start by calculating the lengths of its sides
        const f32 a = v2.getDistanceFromSQ(v3);
        const f32 asqrt = sqrtf(a);
        const f32 b = v1.getDistanceFromSQ(v3);
        const f32 bsqrt = sqrtf(b);
        const f32 c = v1.getDistanceFromSQ(v2);
        const f32 csqrt = sqrtf(c);
 
        // use them to find the angle at each vertex
        return core::vector3df(
                acosf((b + c - a) / (2.f * bsqrt * csqrt)),
                acosf((-b + c + a) / (2.f * asqrt * csqrt)),
                acosf((b - c + a) / (2.f * bsqrt * asqrt)));
}
getAngleWeight() calculates the angles in the corners v1,v2,v3 of the triangle (v1,v2,v3) with the law of cosines.

Assume you have a normal (1,0,0). The original code multiplies each element of the normal and the angle-weight seperately. So you get (1*Alpha,0*Beta,0*Gamma) as result. This ist (Alpha,0,0).
So every vertex-normal is now (Alpha,0,0) bigger.
Assume you have a normal (0,1,0). Then you get (0,Beta,0). With (0,0,1) you get (0,0,Gamma).
So the normal is calculated very randomly, and each vertex-normal is increased by the same amount, independent from the angle of its corner.

The new method (as I think it was supposed to be) actually weights the normal for each vertex seperately. The bigger the angle in this corner is, the heavier the normal is weighted.
Post Reply