Page 1 of 1

More information about normals

Posted: Mon Jun 19, 2017 5:46 pm
by mootools
Normals always need explanations, as there is 3 kind of normals in the SDK:

CPointNormalChannel => Auto generated normal channels on each point (allows normal breaks) => Ignored during optimization
CFaceNormalChannel => Auto generated normal channels on each face => Ignored during optimization
CSpecNormalChannel => User specified channel => Taken into account during optimization

The 2 first kind of normals are auto-generated, which means it can be autogenerated before optimization, but also after.

To generate normals automatically you may use:

Code: Select all

CPointNormalChannel *C3DGeomObject::GetPointNormalChannel(); // It is automatically computed by the SDK using the smooth angle (C3DGeomObject::SetSmoothAngle). CPointNormalChannel contains normal vectors and normal faces.

    CFaceNormalChannel *C3DGeomObject::GetFaceNormalChannel(); // It is automatically computed by the SDK. CFaceNormalChannel only contains normals (1 normal by geometric faces)
CSpecNormalChannel is the class through you can optimize some provided normal.
This is important to balance if the provided normals have a real interest. If auto generated normals are sufficient, this is better to not provide normals. Normal optimization adds important constraint and reduces the optimization quality, leading to lower optimization ratio.

If normals are important, then you provide them and use CSpecNormalChannel.

Code: Select all

// Add a normal channel to your C3DGeomObject *object;

CSpecNormalChannel *channel = NULL;
CNormalFaceList *channelfaces = NULL;
CNormalFace channelface;
                            
channel = xNew(CSpecNormalChannel);
                            
channelfaces = channel->GetNormalFaceList();
channelfaces->SetSize(normalFaceCount);
channelfaces->SetFacesFlags(FACE_IS_UNUSED, false);
                            
unsigned int i, j;
for (i=0; i< normalFaceCount; i++)
{
    if (myFaceIndexUse[i] == false)
    {
        channelface.SetFlag(FACE_IS_UNUSED, true);
        continue;
    }
                                
    channelfaces->GetFace(i, channelface);
                               
    int size2 = myFaceIndexNbr[i];                               
    channelface.SetSize(size2);
    int *pts_index = channelface.GetData(size2);
    for (j = 0; j < size2; j++)
        pts_index[j] = myFaceIndex[i][j];
                                
}
                            
C3DVector *channelnormal;
C3DVectorList *channelpoints = channel->GetNormalVectorList();
channelpoints->SetSize(normalPointCount);
                            
// Copy normals info
for (i=0; i< normalPointCount; i++)
{
    channelnormal = (*channelpoints)[i];
    channelnormal->x = myNormalValue[i].x;
    channelnormal->y = myNormalValue[i].y;
    channelnormal->z = myNormalValue[i].z;
}
                            
// Add channel
object->AddChannel(channel);
*** Normal optimization tweaks

To optimize properly normals you must define the normal optimization threshold (radian)

Code: Select all

bool CSceneOptimizer::SetNormalThreshold(double radianThreshold)
This threshold define an angle between normals above which optimization consider that there is a normal break.
A normal break constraint optimizer which will try to optimize something else.

There is several level of protection for normal optimization. OPTIMIZE_KEEP_NORMALS is the lowest (the one I would use). OPTIMIZE_KEEP_NORMALS|OPTIMIZE_PROTECT_NORMALS is stronger and OPTIMIZE_KEEP_NORMALS|OPTIMIZE_EXCLUDE_NORMALS will freeze any points that has a normal break above specified threshold.