Improved VRML1 support, including relaxed rules to support poorly structured models

This commit is contained in:
Cirilo Bernardo 2016-01-19 15:21:00 +11:00
parent ec9acfd410
commit 39ca807ac4
2 changed files with 152 additions and 57 deletions

View File

@ -287,7 +287,9 @@ SGNODE* WRL1FACESET::TranslateToSG( SGNODE* aParent, WRL1STATUS* sp )
std::vector< SGCOLOR > colorlist;
SGNODE* sgcolor = NULL;
switch( m_current.matbind )
WRL1_BINDING mbind = m_current.matbind;
switch( mbind )
{
case BIND_PER_FACE:
case BIND_PER_VERTEX:
@ -301,7 +303,9 @@ SGNODE* WRL1FACESET::TranslateToSG( SGNODE* aParent, WRL1STATUS* sp )
std::cerr << " * [INFO] bad model: per face indexed but no indices\n";
#endif
return NULL;
// support bad models by temporarily switching bindings
mbind = BIND_OVERALL;
sgcolor = m_current.mat->GetAppearance( 0 );
}
break;
@ -315,7 +319,9 @@ SGNODE* WRL1FACESET::TranslateToSG( SGNODE* aParent, WRL1STATUS* sp )
std::cerr << matIndex.size() << "\n";
#endif
return NULL;
// support bad models by temporarily switching bindings
mbind = BIND_OVERALL;
sgcolor = m_current.mat->GetAppearance( 0 );
}
break;
@ -371,7 +377,7 @@ SGNODE* WRL1FACESET::TranslateToSG( SGNODE* aParent, WRL1STATUS* sp )
std::vector< SGCOLOR > lColors; // colors points (if any) for SG node
int nfaces = 0; // number of triangles for each face in the list
if( BIND_OVERALL == m_current.matbind || BIND_DEFAULT == m_current.matbind )
if( BIND_OVERALL == mbind || BIND_DEFAULT == mbind )
{
// no color list
// assuming convex polygons, create triangles for the SG node
@ -445,7 +451,7 @@ SGNODE* WRL1FACESET::TranslateToSG( SGNODE* aParent, WRL1STATUS* sp )
int cIndex;
SGCOLOR pc1, pc2, pc3;
switch( m_current.matbind )
switch( mbind )
{
case BIND_PER_VERTEX:
cIndex = 3;
@ -493,8 +499,8 @@ SGNODE* WRL1FACESET::TranslateToSG( SGNODE* aParent, WRL1STATUS* sp )
bool colorPerVertex = false;
if( BIND_PER_VERTEX == m_current.matbind
|| BIND_PER_VERTEX_INDEXED == m_current.matbind )
if( BIND_PER_VERTEX == mbind
|| BIND_PER_VERTEX_INDEXED == mbind )
colorPerVertex = true;
bool noidx = false;

View File

@ -417,77 +417,166 @@ void WRL1MATERIAL::GetColor( SGCOLOR* aColor, int aIndex )
if( NULL == aColor )
return;
// Calculate the color based on the given index.
// If the index points to a valid diffuse and emissive colors,
// take the higher value of each component.
// Calculate the color based on the given index using the formula:
// color = ( emission + ambient + diffuse + shininess * specular ) / N
// where N = number of non-zero components or 1 (if all zero)
// If the index exceeds the number of items in a list, use the FIRST
// item rather than the default; this behavior caters to some bad
// models.
float red, blue, green;
WRLVEC3F rgb;
float dRed, dBlue, dGreen;
float eRed, eBlue, eGreen;
float aRed, aBlue, aGreen;
float sRed, sBlue, sGreen;
float shiny;
if( aIndex < 0 || ( aIndex >= (int)diffuseColor.size()
&& aIndex >= (int)emissiveColor.size() ) )
if( aIndex < 0 || ( aIndex >= (int)diffuseColor.size() ) )
{
// If the index is out of bounds, use the default diffuse color.
red = 0.8;
green = 0.8;
blue = 0.8;
aColor->SetColor( red, green, blue );
return;
if( !diffuseColor.empty() )
{
rgb = diffuseColor.front();
dRed = rgb.x;
dGreen = rgb.y;
dBlue = rgb.z;
}
else
{
dRed = 0.8;
dGreen = 0.8;
dBlue = 0.8;
}
}
else
{
rgb = diffuseColor[aIndex];
dRed = rgb.x;
dGreen = rgb.y;
dBlue = rgb.z;
}
if( aIndex >= (int)diffuseColor.size() )
if( aIndex < 0 || ( aIndex >= (int)emissiveColor.size() ) )
{
red = emissiveColor[aIndex].x;
green = emissiveColor[aIndex].y;
blue = emissiveColor[aIndex].z;
checkRange( red );
checkRange( green );
checkRange( blue );
aColor->SetColor( red, green, blue );
return;
if( !emissiveColor.empty() )
{
rgb = emissiveColor.front();
eRed = rgb.x;
eGreen = rgb.y;
eBlue = rgb.z;
}
else
{
eRed = 0.0;
eGreen = 0.0;
eBlue = 0.0;
}
}
else
{
rgb = emissiveColor[aIndex];
eRed = rgb.x;
eGreen = rgb.y;
eBlue = rgb.z;
}
if( aIndex >= (int)emissiveColor.size() )
if( aIndex < 0 || ( aIndex >= (int)ambientColor.size() ) )
{
red = diffuseColor[aIndex].x;
green = diffuseColor[aIndex].y;
blue = diffuseColor[aIndex].z;
checkRange( red );
checkRange( green );
checkRange( blue );
aColor->SetColor( red, green, blue );
return;
if( !ambientColor.empty() )
{
rgb = ambientColor.front();
aRed = rgb.x;
aGreen = rgb.y;
aBlue = rgb.z;
}
else
{
aRed = 0.2;
aGreen = 0.2;
aBlue = 0.2;
}
}
else
{
rgb = ambientColor[aIndex];
aRed = rgb.x;
aGreen = rgb.y;
aBlue = rgb.z;
}
red = diffuseColor[aIndex].x;
green = diffuseColor[aIndex].y;
blue = diffuseColor[aIndex].z;
if( aIndex < 0 || ( aIndex >= (int)specularColor.size() ) )
{
if( !specularColor.empty() )
{
rgb = specularColor.front();
sRed = rgb.x;
sGreen = rgb.y;
sBlue = rgb.z;
}
else
{
sRed = 0.2;
sGreen = 0.2;
sBlue = 0.2;
}
}
else
{
rgb = specularColor[aIndex];
sRed = rgb.x;
sGreen = rgb.y;
sBlue = rgb.z;
}
eRed = emissiveColor[aIndex].x;
eGreen = emissiveColor[aIndex].y;
eBlue = emissiveColor[aIndex].z;
checkRange( red );
checkRange( green );
checkRange( blue );
if( aIndex < 0 || ( aIndex >= (int)shininess.size() ) )
{
if( !shininess.empty() )
shiny = shininess.front();
else
shiny = 0.2;
}
else
{
shiny = shininess[aIndex];
}
checkRange( aRed );
checkRange( aGreen );
checkRange( aBlue );
checkRange( eRed );
checkRange( eGreen );
checkRange( eBlue );
checkRange( dRed );
checkRange( dGreen );
checkRange( dBlue );
checkRange( sRed );
checkRange( sGreen );
checkRange( sBlue );
if( eRed > red )
red = eRed;
int n = 0;
if( eGreen > green )
green = eGreen;
if( aRed + aGreen + aBlue > 0.01 )
++n;
if( eBlue > blue )
blue = eBlue;
if( eRed + eGreen + eBlue > 0.01 )
++n;
if( dRed + dGreen + dBlue > 0.01 )
++n;
if( (sRed + sGreen + sBlue) * shiny > 0.01 )
++n;
if( 0 == n )
++n;
float red, green, blue;
red = (eRed + aRed + dRed + sRed * shiny) / n;
green = (eGreen + aGreen + dGreen + sGreen * shiny) / n;
blue = (eBlue + aBlue + dBlue + sBlue * shiny) / n;
checkRange( red );
checkRange( green );
checkRange( blue );
aColor->SetColor( red, green, blue );
return;