Howdy Denis.

Sorry for answering so late, but i was on the vacations :-)

Problem:
Vertices normals are incorrectly calculated for "cube.3ds".

I investigated this and came to the following conclusion:

*Error with vertices normals calculation is inherited from 3DS format
itself.*

That's because in 3DS there is no separation between points indices and
uv indices.
Such separation of course is possible in modeller - 3DSMax: max's face
looks a bit like this:

class MaxFace
{
public:
    int points[3];
    int texCoords[3];
    unsigned int smoothing;
};

If for example in modeller(3DSMax) we have two faces with same smoothing
group and sharing two points but having different uv coordinates:
maxface0
    points = 0, 1, 2;
    texCoords = 0, 1, 2;
    smooth = 2;
maxface1
    points = 1, 0, 3;
    texCoords = 3, 4, 5;
    smooth = 2;

- such model will be incorrectly exported to old 3DS format. Exporter
will detect different texCoords and will duplicate shared points to get
"one point - one texCoord" situation:

3dsface0
    points = 0, 1, 2;
    smooth = 2;
3dsface1
    points = 4, 5, 3;
    smooth = 2;

with points 4 and 5 being clones of 1 and 0.

And because vertices normals may be smoothed only between same points
the lighting will be obviously incorrect.

Resolution:

Because of format shorthcomings we need additional post-loading
preprocess pass to recover informations lost during export to 3DS.
Suprisingly it's quite easy and possible.
First we need to introduce new "class Lib3dsFace2" with separate indices
for uv tex coords:

class Lib3dsFace2: public Lib3dsFace
{
public:
    Lib3dsWord texCoords[3];
};

second post-loading preprocess in three steps:

Step 1. Create new list of "Lib3dsFace2" and copy old "Lib3dsFace" faces
to this. Also to ensure correct texCoords indices we need to copy
"Lib3dsFace::points" to "Lib3dsFace2::texCoords".

Step 2. We need to identify duplicated points and then replace clones
with first original point:

    for( int i = 0; i < mesh->points; ++i )
        {
             if( processedPoints[i] )
                      continue;
            for( j = i + 1; j < mesh->points; ++j )
                {
                       if( processedPoints[j] )
                               continue;
#define EPSILON   0.01f
                       if( ( fabs( mesh->pointL[i][0] -
mesh->pointL[j][0] ) < EPSILON ) &&
                            ( fabs( mesh->pointL[i][1] -
mesh->pointL[j][1] ) < EPSILON ) &&
                            ( fabs( mesh->pointL[i][2] -
mesh->pointL[j][2] ) < EPSILON ) )
                            {
                                  /// @todo: replace every occurence of
"j" point with "i"
                                  for( int k = 0; k < mesh->faces; ++k )
                                        for( int l = 0; l < 3; ++l )
                                              if(
mesh->faceL[k].points[l] == j )

mesh->faceL[k].points[l] = i;
                                  processedPoints[j] = true;
                            }
                }
        }

Step 3.
Calculate vertices normals, this time they will be correct.
<Code is too complicated to put here.>



Well, that's all folks. Sorry for being too bloated.
Hope that will help.

Rafał Kamraj









-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
lib3ds-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/lib3ds-devel

Reply via email to