Work in progress: implementing SG translation for VRML1 models

This commit is contained in:
Cirilo Bernardo 2016-01-06 15:34:14 +11:00
parent 38543ab94f
commit 6b873ed46b
22 changed files with 632 additions and 293 deletions

View File

@ -616,8 +616,12 @@ void PANEL_PREV_3D::UpdateModelName( wxString const& aModelName )
#endif #endif
wxSizer* ws = new wxBoxSizer( wxHORIZONTAL ); wxSizer* ws = new wxBoxSizer( wxHORIZONTAL );
ws->Add( canvas, 10, wxEXPAND ); canvas->Set3DModel( *model );
preview->SetSizerAndFit( ws ); ws->Add( canvas, 1, wxEXPAND );
preview->SetSizer( ws );
preview->Layout();
ws->FitInside( preview );
return;
} }
canvas->Set3DModel( *model ); canvas->Set3DModel( *model );

View File

@ -15,13 +15,11 @@ add_library( kicad_3dsg SHARED
sg_coords.cpp sg_coords.cpp
sg_normals.cpp sg_normals.cpp
sg_index.cpp sg_index.cpp
sg_colorindex.cpp
sg_coordindex.cpp sg_coordindex.cpp
ifsg_node.cpp ifsg_node.cpp
ifsg_transform.cpp ifsg_transform.cpp
ifsg_appearance.cpp ifsg_appearance.cpp
ifsg_index.cpp ifsg_index.cpp
ifsg_colorindex.cpp
ifsg_coordindex.cpp ifsg_coordindex.cpp
ifsg_colors.cpp ifsg_colors.cpp
ifsg_coords.cpp ifsg_coords.cpp

View File

@ -173,7 +173,7 @@ bool IFSG_COLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
} }
bool IFSG_COLORS::SetColorList( size_t& aListSize, const SGCOLOR* aColorList ) bool IFSG_COLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
{ {
if( NULL == m_node ) if( NULL == m_node )
{ {

View File

@ -35,7 +35,6 @@ SGFACESET::SGFACESET( SGNODE* aParent ) : SGNODE( aParent )
{ {
m_SGtype = S3D::SGTYPE_FACESET; m_SGtype = S3D::SGTYPE_FACESET;
m_Colors = NULL; m_Colors = NULL;
m_ColorIndices = NULL;
m_Coords = NULL; m_Coords = NULL;
m_CoordIndices = NULL; m_CoordIndices = NULL;
m_Normals = NULL; m_Normals = NULL;
@ -107,13 +106,6 @@ SGFACESET::~SGFACESET()
m_Normals = NULL; m_Normals = NULL;
} }
if( m_ColorIndices )
{
m_ColorIndices->SetParent( NULL, false );
delete m_ColorIndices;
m_ColorIndices = NULL;
}
if( m_CoordIndices ) if( m_CoordIndices )
{ {
m_CoordIndices->SetParent( NULL, false ); m_CoordIndices->SetParent( NULL, false );
@ -173,14 +165,6 @@ SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller)
return np; return np;
} }
if( m_ColorIndices )
{
np = m_ColorIndices->FindNode( aNodeName, this );
if( np )
return np;
}
if( m_Coords ) if( m_Coords )
{ {
np = m_Coords->FindNode( aNodeName, this ); np = m_Coords->FindNode( aNodeName, this );
@ -241,12 +225,6 @@ void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild )
return; return;
} }
if( aNode == m_ColorIndices )
{
m_ColorIndices = NULL;
return;
}
if( aNode == m_CoordIndices ) if( aNode == m_CoordIndices )
{ {
m_CoordIndices = NULL; m_CoordIndices = NULL;
@ -377,21 +355,6 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
return true; return true;
} }
if( S3D::SGTYPE_COLORINDEX == aNode->GetNodeType() )
{
if( m_ColorIndices )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] assigning multiple ColorIndex nodes\n";
return false;
}
m_ColorIndices = (SGCOLORINDEX*)aNode;
m_ColorIndices->SetParent( this );
return true;
}
if( S3D::SGTYPE_COORDINDEX == aNode->GetNodeType() ) if( S3D::SGTYPE_COORDINDEX == aNode->GetNodeType() )
{ {
if( m_CoordIndices ) if( m_CoordIndices )
@ -440,9 +403,6 @@ void SGFACESET::ReNameNodes( void )
if( m_Colors ) if( m_Colors )
m_Colors->ReNameNodes(); m_Colors->ReNameNodes();
if( m_ColorIndices )
m_ColorIndices->ReNameNodes();
// rename all Coordinates and Indices // rename all Coordinates and Indices
if( m_Coords ) if( m_Coords )
m_Coords->ReNameNodes(); m_Coords->ReNameNodes();
@ -510,9 +470,6 @@ bool SGFACESET::WriteVRML( std::ofstream& aFile, bool aReuseFlag )
if( m_RColors ) if( m_RColors )
m_RColors->WriteVRML( aFile, aReuseFlag ); m_RColors->WriteVRML( aFile, aReuseFlag );
if( m_ColorIndices )
m_ColorIndices->WriteVRML( aFile, aReuseFlag );
aFile << "}\n"; aFile << "}\n";
return true; return true;
@ -553,7 +510,7 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
} }
aFile << "[" << GetName() << "]"; aFile << "[" << GetName() << "]";
#define NITEMS 8 #define NITEMS 7
bool items[NITEMS]; bool items[NITEMS];
int i; int i;
@ -588,10 +545,6 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
if( NULL != m_RColors ) if( NULL != m_RColors )
items[i] = true; items[i] = true;
++i;
if( NULL != m_ColorIndices )
items[i] = true;
for( int i = 0; i < NITEMS; ++i ) for( int i = 0; i < NITEMS; ++i )
aFile.write( (char*)&items[i], sizeof(bool) ); aFile.write( (char*)&items[i], sizeof(bool) );
@ -616,9 +569,6 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
if( items[6] ) if( items[6] )
aFile << "[" << m_RColors->GetName() << "]"; aFile << "[" << m_RColors->GetName() << "]";
if( items[7] )
m_ColorIndices->WriteCache( aFile, this );
if( aFile.fail() ) if( aFile.fail() )
return false; return false;
@ -629,7 +579,7 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
bool SGFACESET::ReadCache( std::ifstream& aFile, SGNODE* parentNode ) bool SGFACESET::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
{ {
if( m_Coords || m_RCoords || m_CoordIndices if( m_Coords || m_RCoords || m_CoordIndices
|| m_Colors || m_RColors || m_ColorIndices || m_Colors || m_RColors
|| m_Normals || m_RNormals ) || m_Normals || m_RNormals )
{ {
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
@ -637,7 +587,7 @@ bool SGFACESET::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
return false; return false;
} }
#define NITEMS 8 #define NITEMS 7
bool items[NITEMS]; bool items[NITEMS];
for( int i = 0; i < NITEMS; ++i ) for( int i = 0; i < NITEMS; ++i )
@ -838,28 +788,6 @@ bool SGFACESET::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
m_RColors->addNodeRef( this ); m_RColors->addNodeRef( this );
} }
if( items[7] )
{
if( S3D::SGTYPE_COLORINDEX != S3D::ReadTag( aFile, name ) )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] corrupt data; bad color index tag at position ";
std::cerr << aFile.tellg() << "\n";
return false;
}
m_ColorIndices = new SGCOLORINDEX( this );
m_ColorIndices->SetName( name.c_str() );
if( !m_ColorIndices->ReadCache( aFile, this ) )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] corrupt data while reading color index '";
std::cerr << name << "'\n";
return false;
}
}
if( aFile.fail() ) if( aFile.fail() )
return false; return false;
@ -969,62 +897,10 @@ bool SGFACESET::validate( void )
if( NULL != pColors ) if( NULL != pColors )
{ {
if( NULL == m_ColorIndices ) // we must have at least as many colors as vertices
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad model; no color indices\n";
#endif
validated = true;
valid = false;
return false;
}
// we must have at least 1 color in the list
size_t nColor = 0; size_t nColor = 0;
SGCOLOR* pColor = NULL; SGCOLOR* pColor = NULL;
pColors->GetColorList( nColor, pColor ); pColors->GetColorList( nColor, pColor );
if( nColor < 1 )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad model; no colors\n";
#endif
validated = true;
valid = false;
return false;
}
size_t nCLIdx = 0;
int* pCLIdx = NULL;
m_ColorIndices->GetIndices( nCLIdx, pCLIdx );
if( nCLIdx != nCoords )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad model; color indices do not match number of vertices\n";
#endif
validated = true;
valid = false;
return false;
}
// check that color[n] >= 0 and < nColors
for( size_t i = 0; i < nCLIdx; ++i )
{
if( pCLIdx[i] < 0 || pCLIdx[i] >= nCLIdx )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad model; color index out of bounds\n";
#endif
validated = true;
valid = false;
return false;
}
}
} }
validated = true; validated = true;

View File

@ -51,7 +51,6 @@ private:
public: public:
// owned objects // owned objects
SGCOLORS* m_Colors; SGCOLORS* m_Colors;
SGCOLORINDEX* m_ColorIndices;
SGCOORDS* m_Coords; SGCOORDS* m_Coords;
SGCOORDINDEX* m_CoordIndices; SGCOORDINDEX* m_CoordIndices;
SGNORMALS* m_Normals; SGNORMALS* m_Normals;

View File

@ -624,7 +624,6 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
} }
SGCOLORS* pc = pf->m_Colors; SGCOLORS* pc = pf->m_Colors;
SGCOLORINDEX* cidx = pf->m_ColorIndices;
SGCOORDS* pv = pf->m_Coords; SGCOORDS* pv = pf->m_Coords;
SGCOORDINDEX* vidx = pf->m_CoordIndices; SGCOORDINDEX* vidx = pf->m_CoordIndices;
SGNORMALS* pn = pf->m_Normals; SGNORMALS* pn = pf->m_Normals;
@ -643,6 +642,24 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
SGPOINT* pCoords = NULL; SGPOINT* pCoords = NULL;
pv->GetCoordsList( nCoords, pCoords ); pv->GetCoordsList( nCoords, pCoords );
size_t nColors = 0;
SGCOLOR* pColors = NULL;
if( pc )
{
// check the vertex colors
pc->GetColorList( nColors, pColors );
if( nColors < nCoords )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad model; not enough colors per vertex\n";
#endif
return true;
}
}
// set the vertex indices // set the vertex indices
size_t nvidx = 0; size_t nvidx = 0;
int* lv = NULL; int* lv = NULL;
@ -673,17 +690,39 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
return true; return true;
} }
// construct the final vertex list // construct the final vertex/color list
SFVEC3F* lColors = NULL;
SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ]; SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ];
double red, green, blue;
int ti, ii; int ti, ii;
for( size_t i = 0; i < vertices.size(); ++i ) if( pc )
{ {
ti = vertices[i]; SFVEC3F* lColors = new SFVEC3F[vertices.size()];
glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 ); m.m_Color = lColors;
pt = (*aTransform) * pt; }
lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
if( pc )
{
for( size_t i = 0; i < vertices.size(); ++i )
{
ti = vertices[i];
glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
pt = (*aTransform) * pt;
pColors[ti].GetColor( lColors[i].x, lColors[i].y, lColors[i].z );
lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
}
}
else
{
for( size_t i = 0; i < vertices.size(); ++i )
{
ti = vertices[i];
glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
pt = (*aTransform) * pt;
lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
}
} }
m.m_VertexSize = (unsigned int) vertices.size(); m.m_VertexSize = (unsigned int) vertices.size();
@ -718,30 +757,6 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
} }
m.m_Normals = lNorms; m.m_Normals = lNorms;
// use per-vertex colors if available
if( pc )
{
size_t ncidx = 0;
int* lcidx = NULL;
cidx->GetIndices( ncidx, lcidx );
// set the vertex colors
size_t nColors = 0;
SGCOLOR* pColors = NULL;
pc->GetColorList( nColors, pColors );
SFVEC3F* lColors = new SFVEC3F[ vertices.size() ];
double red, green, blue;
for( size_t i = 0; i < vertices.size(); ++i )
{
ti = vertices[i];
pColors[ lcidx[ti] ].GetColor( lColors[i].x, lColors[i].y, lColors[i].z );
}
m.m_Color = lColors;
}
meshes.push_back( m ); meshes.push_back( m );
return true; return true;

View File

@ -31,7 +31,6 @@
#include "plugins/3dapi/ifsg_colors.h" #include "plugins/3dapi/ifsg_colors.h"
#include "plugins/3dapi/ifsg_coords.h" #include "plugins/3dapi/ifsg_coords.h"
#include "plugins/3dapi/ifsg_faceset.h" #include "plugins/3dapi/ifsg_faceset.h"
#include "plugins/3dapi/ifsg_colorindex.h"
#include "plugins/3dapi/ifsg_coordindex.h" #include "plugins/3dapi/ifsg_coordindex.h"
#include "plugins/3dapi/ifsg_normals.h" #include "plugins/3dapi/ifsg_normals.h"
#include "plugins/3dapi/ifsg_shape.h" #include "plugins/3dapi/ifsg_shape.h"

View File

@ -50,7 +50,7 @@ public:
bool NewNode( IFSG_NODE& aParent ); bool NewNode( IFSG_NODE& aParent );
bool GetColorList( size_t& aListSize, SGCOLOR*& aColorList ); bool GetColorList( size_t& aListSize, SGCOLOR*& aColorList );
bool SetColorList( size_t& aListSize, const SGCOLOR* aColorList ); bool SetColorList( size_t aListSize, const SGCOLOR* aColorList );
bool AddColor( double aRedValue, double aGreenValue, double aBlueValue ); bool AddColor( double aRedValue, double aGreenValue, double aBlueValue );
bool AddColor( const SGCOLOR& aColor ); bool AddColor( const SGCOLOR& aColor );
}; };

View File

@ -27,6 +27,7 @@
#include "vrml1_base.h" #include "vrml1_base.h"
#include "vrml1_faceset.h" #include "vrml1_faceset.h"
#include "vrml1_coords.h" #include "vrml1_coords.h"
#include "vrml1_material.h"
#include "plugins/3dapi/ifsg_all.h" #include "plugins/3dapi/ifsg_all.h"
@ -172,6 +173,34 @@ bool WRL1FACESET::Read( WRLPROC& proc, WRL1BASE* aTopNode )
return false; return false;
} }
} }
else if( !glob.compare( "normalIndex" ) )
{
if( !proc.ReadMFInt( normIndex ) )
{
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] invalid normalIndex at line " << line << ", column ";
std::cerr << column << "\n";
std::cerr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
std::cerr << " * [INFO] message: '" << proc.GetError() << "'\n";
#endif
return false;
}
}
else if( !glob.compare( "textureCoordIndex" ) )
{
if( !proc.ReadMFInt( texIndex ) )
{
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] invalid textureCoordIndex at line " << line << ", column ";
std::cerr << column << "\n";
std::cerr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
std::cerr << " * [INFO] message: '" << proc.GetError() << "'\n";
#endif
return false;
}
}
else else
{ {
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 ) #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
@ -191,39 +220,74 @@ bool WRL1FACESET::Read( WRLPROC& proc, WRL1BASE* aTopNode )
SGNODE* WRL1FACESET::TranslateToSG( SGNODE* aParent, bool calcNormals ) SGNODE* WRL1FACESET::TranslateToSG( SGNODE* aParent, bool calcNormals )
{ {
#ifdef NOGO
S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
if( NULL != aParent && ptype != S3D::SGTYPE_SHAPE )
{
#ifdef DEBUG_VRML1
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] IndexedFaceSet does not have a Shape parent (parent ID: ";
std::cerr << ptype << ")\n";
#endif
return NULL;
}
if( m_sgNode ) if( m_sgNode )
{ {
if( NULL != aParent ) if( NULL != aParent && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{ return NULL;
if( NULL == S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
{
return NULL;
}
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{
return NULL;
}
}
return m_sgNode; return m_sgNode;
} }
if( m_Parent )
{
WRL1STATUS* cp = m_Parent->GetCurrentSettings();
if( NULL != cp )
m_current = *cp;
else
return NULL;
}
else
{
return NULL;
}
if( NULL == m_current.coord || NULL == m_current.mat )
return NULL;
// 1. create the vertex/normals/colors lists
std::vector< SGPOINT > vlist;
std::vector< SGVECTOR > nlist;
std::vector< SGCOLOR > colorlist;
SGCOLOR partColor;
SGNODE* sgcolor = NULL;
int nface = 1;
switch( m_current.matbind )
{
case BIND_OVERALL:
// use the first (non-default) appearance definition
sgcolor = m_current.mat->GetAppearance( 1 );
break;
case BIND_PER_FACE:
case BIND_PER_VERTEX:
case BIND_PER_FACE_INDEXED:
case BIND_PER_VERTEX_INDEXED:
// take the first color definition from the material
m_current.mat->GetColor( &partColor, 1 );
break;
default:
// use the default appearance definition
sgcolor = m_current.mat->GetAppearance( 0 );
break;
}
WRLVEC3F* pts;
size_t npts;
m_current.coord->GetCoords( pts, npts );
//while()
//qwerty;
#ifdef NOGO
size_t vsize = coordIndex.size(); size_t vsize = coordIndex.size();
if( NULL == coord || vsize < 3 ) if( NULL == coord || vsize < 3 )

View File

@ -44,6 +44,8 @@ class WRL1FACESET : public WRL1NODE
private: private:
std::vector< int > coordIndex; std::vector< int > coordIndex;
std::vector< int > matIndex; std::vector< int > matIndex;
std::vector< int > normIndex;
std::vector< int > texIndex;
public: public:
WRL1FACESET( NAMEREGISTER* aDictionary ); WRL1FACESET( NAMEREGISTER* aDictionary );

View File

@ -57,6 +57,13 @@ WRL1MATERIAL::~WRL1MATERIAL()
std::cerr << " * [INFO] Destroying Material node\n"; std::cerr << " * [INFO] Destroying Material node\n";
#endif #endif
// destroy any orphaned color nodes
for( int i = 0; i < 2; ++i )
{
if( NULL != colors[i] && NULL == S3D::GetSGNodeParent( colors[i] ) )
S3D::DestroyNode( colors[i] );
}
return; return;
} }
@ -84,6 +91,9 @@ void WRL1MATERIAL::setDefaults( void )
shininess.push_back( 0.2 ); shininess.push_back( 0.2 );
transparency.push_back( 0.0 ); transparency.push_back( 0.0 );
colors[0] = NULL;
colors[1] = NULL;
return; return;
} }
@ -297,3 +307,209 @@ SGNODE* WRL1MATERIAL::TranslateToSG( SGNODE* aParent, bool calcNormals )
return NULL; return NULL;
} }
SGNODE* WRL1MATERIAL::GetAppearance( int aIndex )
{
// invalid indices result in the default colors
if( aIndex != 0 && aIndex != 1 )
aIndex = 0;
if( NULL != colors[ aIndex ] )
return colors[ aIndex ];
IFSG_APPEARANCE app( true );
float red, green, blue, val;
if( aIndex > (int)transparency.size() )
val = transparency[0];
else
val = transparency[aIndex];
checkRange( val );
app.SetTransparency( val );
if( aIndex > (int)shininess.size() )
val = shininess[0];
else
val = shininess[aIndex];
checkRange( val );
app.SetShininess( val );
if( aIndex > (int)ambientColor.size() )
{
red = ambientColor[0].x;
green = ambientColor[0].y;
blue = ambientColor[0].z;
}
else
{
red = ambientColor[aIndex].x;
green = ambientColor[aIndex].y;
blue = ambientColor[aIndex].z;
}
checkRange( red );
checkRange( green );
checkRange( blue );
val = (red + green + blue)/3.0;
app.SetAmbient( val );
if( aIndex > (int)diffuseColor.size() )
{
red = diffuseColor[0].x;
green = diffuseColor[0].y;
blue = diffuseColor[0].z;
}
else
{
red = diffuseColor[aIndex].x;
green = diffuseColor[aIndex].y;
blue = diffuseColor[aIndex].z;
}
checkRange( red );
checkRange( green );
checkRange( blue );
app.SetDiffuse( red, green, blue );
if( aIndex > (int)emissiveColor.size() )
{
red = emissiveColor[0].x;
green = emissiveColor[0].y;
blue = emissiveColor[0].z;
}
else
{
red = emissiveColor[aIndex].x;
green = emissiveColor[aIndex].y;
blue = emissiveColor[aIndex].z;
}
checkRange( red );
checkRange( green );
checkRange( blue );
app.SetEmissive( red, green, blue );
if( aIndex > (int)specularColor.size() )
{
red = specularColor[0].x;
green = specularColor[0].y;
blue = specularColor[0].z;
}
else
{
red = specularColor[aIndex].x;
green = specularColor[aIndex].y;
blue = specularColor[aIndex].z;
}
checkRange( red );
checkRange( green );
checkRange( blue );
app.SetSpecular( red, green, blue );
colors[aIndex] = app.GetRawPtr();
return colors[aIndex];
}
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.
float red, blue, green;
float eRed, eBlue, eGreen;
if( aIndex <= 0 || ( aIndex >= (int)diffuseColor.size()
&& aIndex >= (int)emissiveColor.size() ) )
{
// If the index is out of bounds, use the default diffuse color.
red = diffuseColor[0].x;
green = diffuseColor[0].y;
blue = diffuseColor[0].z;
checkRange( red );
checkRange( green );
checkRange( blue );
aColor->SetColor( red, green, blue );
return;
}
if( aIndex >= (int)diffuseColor.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( aIndex >= (int)emissiveColor.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;
}
red = diffuseColor[aIndex].x;
green = diffuseColor[aIndex].y;
blue = diffuseColor[aIndex].z;
eRed = emissiveColor[aIndex].x;
eGreen = emissiveColor[aIndex].y;
eBlue = emissiveColor[aIndex].z;
checkRange( red );
checkRange( green );
checkRange( blue );
checkRange( eRed );
checkRange( eGreen );
checkRange( eBlue );
if( eRed > red )
red = eRed;
if( eGreen > green )
green = eGreen;
if( eBlue > blue )
blue = eBlue;
aColor->SetColor( red, green, blue );
return;
}
void WRL1MATERIAL::checkRange( float& aValue )
{
if( aValue < 0.0 )
aValue = 0.0;
else if( aValue > 1.0 )
aValue = 1.0;
return;
}

View File

@ -30,10 +30,12 @@
#define VRML1_MATERIAL_H #define VRML1_MATERIAL_H
#include <vector> #include <vector>
#include <map>
#include "vrml1_node.h" #include "vrml1_node.h"
class WRL1BASE; class WRL1BASE;
class SGNODE; class SGNODE;
struct SGCOLOR;
/** /**
* Class WRL1MATERIAL * Class WRL1MATERIAL
@ -48,7 +50,10 @@ private:
std::vector< float > shininess; std::vector< float > shininess;
std::vector< float > transparency; std::vector< float > transparency;
SGNODE* colors[2];
void setDefaults( void ); void setDefaults( void );
void checkRange( float& aValue );
public: public:
WRL1MATERIAL( NAMEREGISTER* aDictionary ); WRL1MATERIAL( NAMEREGISTER* aDictionary );
@ -61,7 +66,18 @@ public:
bool AddChildNode( WRL1NODE* aNode ); bool AddChildNode( WRL1NODE* aNode );
SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ); SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals );
// XXX - requires a function to create/retrieve a color /**
* Function GetAppearance
* returns an SGAPPEARANCE node representing the appearance
* for an IndexedFaceSet
*/
SGNODE* GetAppearance( int aIndex );
/**
* Function GetColor
* computes an SGCOLOR representing the appearance of a vertex or face
*/
void GetColor( SGCOLOR* aColor, int aIndex );
}; };
#endif // VRML1_MATERIAL_H #endif // VRML1_MATERIAL_H

View File

@ -286,6 +286,12 @@ WRL1NODES WRL1NODE::getNodeTypeID( const std::string aNodeName )
} }
size_t WRL1NODE::GetNItems( void ) const
{
return m_Items.size();
}
std::string WRL1NODE::GetError( void ) std::string WRL1NODE::GetError( void )
{ {
return m_error; return m_error;

View File

@ -220,6 +220,8 @@ public:
const char* GetNodeTypeName( WRL1NODES aNodeType ) const; const char* GetNodeTypeName( WRL1NODES aNodeType ) const;
size_t GetNItems( void ) const;
/** /**
* Function FindNode searches the tree of linked nodes and returns a * Function FindNode searches the tree of linked nodes and returns a
* reference to the current node with the given name. The reference * reference to the current node with the given name. The reference

View File

@ -140,20 +140,26 @@ SGNODE* WRL1SEPARATOR::TranslateToSG( SGNODE* aParent, bool calcNormals )
std::cerr << m_Items.size() << " items)\n"; std::cerr << m_Items.size() << " items)\n";
#endif #endif
return NULL; if( !m_Parent )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] Separator has no parent\n";
/*
if( m_Children.empty() && m_Refs.empty() )
return NULL; return NULL;
}
if( WRL1_BASE != m_Parent->GetNodeType() )
m_current = *( m_Parent->GetCurrentSettings() );
else
m_current.Init();
S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent ); S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM ) if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM )
{ {
#ifdef DEBUG_VRML1 #ifdef DEBUG_VRML2
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] Separator does not have a Separator parent (parent ID: "; std::cerr << " * [BUG] Separator does not have a Transform parent (parent ID: ";
std::cerr << ptype << ")\n"; std::cerr << ptype << ")\n";
#endif #endif
@ -162,80 +168,38 @@ SGNODE* WRL1SEPARATOR::TranslateToSG( SGNODE* aParent, bool calcNormals )
if( m_sgNode ) if( m_sgNode )
{ {
if( NULL != aParent ) if( NULL == aParent )
{ return NULL;
if( NULL == S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) ) if( !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{ return NULL;
return NULL;
}
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{
return NULL;
}
}
return m_sgNode; return m_sgNode;
} }
IFSG_TRANSFORM txNode( aParent ); IFSG_TRANSFORM txNode( aParent );
bool hasContent = false;
std::list< WRL1NODE* >::iterator sC = m_Children.begin(); std::list< WRL1NODE* >::iterator sI = m_Items.begin();
std::list< WRL1NODE* >::iterator eC = m_Children.end(); std::list< WRL1NODE* >::iterator eI = m_Items.end();
WRL1NODES type;
// Include only the following in a Separator node: SGNODE* node = txNode.GetRawPtr();
// Shape
// Switch
// Separator
// Inline
bool test = false; // set to true if there are any subnodes for display
for( int i = 0; i < 2; ++i ) while( sI != eI )
{ {
while( sC != eC ) if( NULL != (*sI)->TranslateToSG( node, calcNormals ) )
{ hasContent = true;
type = (*sC)->GetNodeType();
switch( type ) ++sI;
{
case WRL1_SHAPE:
case WRL1_SWITCH:
case WRL1_INLINE:
case WRL1_SEPARATOR:
if( NULL != (*sC)->TranslateToSG( txNode.GetRawPtr(), calcNormals ) )
test = true;
break;
default:
break;
}
++ sC;
}
sC = m_Refs.begin();
eC = m_Refs.end();
} }
if( false == test ) if( !hasContent )
{ {
txNode.Destroy(); txNode.Destroy();
return NULL; return NULL;
} }
txNode.SetScale( SGPOINT( scale.x, scale.y, scale.z ) ); m_sgNode = node;
txNode.SetCenter( SGPOINT( center.x, center.y, center.z ) );
txNode.SetTranslation( SGPOINT( translation.x, translation.y, translation.z ) );
txNode.SetScaleOrientation( SGVECTOR( scaleOrientation.x, scaleOrientation.y,
scaleOrientation.z ), scaleOrientation.w );
txNode.SetRotation( SGVECTOR( rotation.x, rotation.y, rotation.z), rotation.w );
m_sgNode = txNode.GetRawPtr(); return node;
return m_sgNode;
*/
} }

View File

@ -189,7 +189,8 @@ SGNODE* WRL1SWITCH::TranslateToSG( SGNODE* aParent, bool calcNormals )
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 ) #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
std::cerr << " * [INFO] Translating Switch with " << m_Children.size(); std::cerr << " * [INFO] Translating Switch with " << m_Children.size();
std::cerr << " children, " << m_Refs.size() << " references and "; std::cerr << " children, " << m_Refs.size() << " references and ";
std::cerr << m_BackPointers.size() << " backpointers\n"; std::cerr << m_BackPointers.size() << " backpointers (total ";
std::cerr << m_Items.size() << " items)\n";
#endif #endif
if( m_Items.empty() ) if( m_Items.empty() )
@ -201,7 +202,12 @@ SGNODE* WRL1SWITCH::TranslateToSG( SGNODE* aParent, bool calcNormals )
std::list< WRL1NODE* >::iterator ip = m_Items.begin(); std::list< WRL1NODE* >::iterator ip = m_Items.begin();
std::advance( ip, whichChild ); std::advance( ip, whichChild );
m_current = *( m_Parent->GetCurrentSettings() ); IFSG_TRANSFORM txNode( aParent );
if( WRL1_BASE != m_Parent->GetNodeType() )
m_current = *( m_Parent->GetCurrentSettings() );
else
m_current.Init();
return (*ip)->TranslateToSG( aParent, calcNormals ); return (*ip)->TranslateToSG( aParent, calcNormals );
} }

View File

@ -194,3 +194,30 @@ SGNODE* WRL2COLOR::TranslateToSG( SGNODE* aParent, bool calcNormals )
// any data manipulation must be performed by the parent node // any data manipulation must be performed by the parent node
return NULL; return NULL;
} }
bool WRL2COLOR::HasColors( void )
{
if( colors.empty() )
return false;
return true;
}
void WRL2COLOR::GetColor( int aIndex, float& red, float& green, float& blue )
{
if( aIndex < 0 || aIndex >= colors.size() )
{
red = 0.8;
green = 0.8;
blue = 0.8;
return;
}
red = colors[aIndex].x;
green = colors[aIndex].x;
blue = colors[aIndex].x;
return;
}

View File

@ -59,6 +59,18 @@ public:
bool AddRefNode( WRL2NODE* aNode ); bool AddRefNode( WRL2NODE* aNode );
bool AddChildNode( WRL2NODE* aNode ); bool AddChildNode( WRL2NODE* aNode );
SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ); SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals );
/**
* Function HasColors
* returns true if the color set is non-empty
*/
bool HasColors( void );
/**
* Function GetColor
* retrieves the given color (or default 0.8, 0.8, 0.8 if index is invalid)
*/
void GetColor( int aIndex, float& red, float& green, float& blue );
}; };
#endif // VRML2_COLOR_H #endif // VRML2_COLOR_H

View File

@ -27,6 +27,7 @@
#include "vrml2_base.h" #include "vrml2_base.h"
#include "vrml2_faceset.h" #include "vrml2_faceset.h"
#include "vrml2_coords.h" #include "vrml2_coords.h"
#include "vrml2_color.h"
#include "plugins/3dapi/ifsg_all.h" #include "plugins/3dapi/ifsg_all.h"
@ -632,44 +633,139 @@ SGNODE* WRL2FACESET::TranslateToSG( SGNODE* aParent, bool calcNormals )
std::vector< int > lCIdx; // coordinate index list for SG node (must be triads) std::vector< int > lCIdx; // coordinate index list for SG node (must be triads)
std::vector< SGVECTOR > lCNorm; // per-vertex normals std::vector< SGVECTOR > lCNorm; // per-vertex normals
std::vector< int > faces; // tracks the number of polygons for the entire set std::vector< int > faces; // tracks the number of polygons for the entire set
std::vector< SGCOLOR > lColors; // colors points (if any) for SG node
int nfaces = 0; // number of triangles for each face in the list int nfaces = 0; // number of triangles for each face in the list
// assuming convex polygons, create triangles for the SG node if( NULL == color )
for( idx = 3; idx < vsize; )
{ {
lCIdx.push_back( i1 ); // assuming convex polygons, create triangles for the SG node
for( idx = 3; idx < vsize; )
if( ccw )
{ {
lCIdx.push_back( i2 ); lCIdx.push_back( i1 );
lCIdx.push_back( i3 );
}
else
{
lCIdx.push_back( i3 );
lCIdx.push_back( i2 );
}
++nfaces; if( ccw )
i2 = i3;
i3 = coordIndex[idx++];
while( ( i1 < 0 || i2 < 0 || i3 < 0 ) && ( idx < vsize ) )
{
if( i3 < 0 )
{ {
faces.push_back( nfaces ); lCIdx.push_back( i2 );
nfaces = 0; lCIdx.push_back( i3 );
}
else
{
lCIdx.push_back( i3 );
lCIdx.push_back( i2 );
} }
i1 = i2; ++nfaces;
i2 = i3; i2 = i3;
i3 = coordIndex[idx++]; i3 = coordIndex[idx++];
// any invalid polygons shall void the entire faceset; this is a requirement while( ( i1 < 0 || i2 < 0 || i3 < 0 ) && ( idx < vsize ) )
// to ensure correct handling of the normals {
if( ( i1 < 0 && i2 < 0 ) || ( i1 < 0 && i3 < 0 ) || ( i2 < 0 && i3 < 0 ) ) if( i3 < 0 )
return NULL; {
faces.push_back( nfaces );
nfaces = 0;
}
i1 = i2;
i2 = i3;
i3 = coordIndex[idx++];
// any invalid polygons shall void the entire faceset; this is a requirement
// to ensure correct handling of the normals
if( ( i1 < 0 && i2 < 0 ) || ( i1 < 0 && i3 < 0 ) || ( i2 < 0 && i3 < 0 ) )
return NULL;
}
}
}
else
{
int cIndex;
WRL2COLOR* cn = (WRL2COLOR*) color;
SGCOLOR pc1, pc2, pc3;
WRLVEC3F tc;
cn->GetColor( 0, tc.x, tc.y, tc.z );
pc1.SetColor( tc.x, tc.y, tc.z );
if( colorPerVertex )
{
cIndex = 3;
cn->GetColor( 1, tc.x, tc.y, tc.z );
pc2.SetColor( tc.x, tc.y, tc.z );
cn->GetColor( 2, tc.x, tc.y, tc.z );
pc3.SetColor( tc.x, tc.y, tc.z );
}
else
{
cIndex = 1;
pc2.SetColor( tc.x, tc.y, tc.z );
pc3.SetColor( tc.x, tc.y, tc.z );
}
// assuming convex polygons, create triangles for the SG node
for( idx = 3; idx < vsize; )
{
lCIdx.push_back( i1 );
lColors.push_back( pc1 );
lColors.push_back( pc2 );
lColors.push_back( pc3 );
if( ccw )
{
lCIdx.push_back( i2 );
lCIdx.push_back( i3 );
}
else
{
lCIdx.push_back( i3 );
lCIdx.push_back( i2 );
}
++nfaces;
i2 = i3;
i3 = coordIndex[idx++];
if( colorPerVertex && i1 >= 0 && i2 >= 0 && i3 >= 0 )
{
pc1.SetColor( pc2 );
pc2.SetColor( pc3 );
cn->GetColor( cIndex++, tc.x, tc.y, tc.z );
pc3.SetColor( tc.x, tc.y, tc.z );
}
while( ( i1 < 0 || i2 < 0 || i3 < 0 ) && ( idx < vsize ) )
{
if( i3 < 0 )
{
faces.push_back( nfaces );
nfaces = 0;
if( !colorPerVertex )
{
cn->GetColor( cIndex++, tc.x, tc.y, tc.z );
pc1.SetColor( tc.x, tc.y, tc.z );
pc2.SetColor( tc.x, tc.y, tc.z );
pc3.SetColor( tc.x, tc.y, tc.z );
}
}
i1 = i2;
i2 = i3;
i3 = coordIndex[idx++];
if( colorPerVertex )
{
pc1.SetColor( pc2 );
pc2.SetColor( pc3 );
cn->GetColor( cIndex++, tc.x, tc.y, tc.z );
pc3.SetColor( tc.x, tc.y, tc.z );
}
// any invalid polygons shall void the entire faceset; this is a requirement
// to ensure correct handling of the normals
if( ( i1 < 0 && i2 < 0 ) || ( i1 < 0 && i3 < 0 ) || ( i2 < 0 && i3 < 0 ) )
return NULL;
}
} }
} }
@ -755,6 +851,12 @@ SGNODE* WRL2FACESET::TranslateToSG( SGNODE* aParent, bool calcNormals )
IFSG_NORMALS nmNode( fsNode ); IFSG_NORMALS nmNode( fsNode );
nmNode.SetNormalList( lCNorm.size(), &lCNorm[0] ); nmNode.SetNormalList( lCNorm.size(), &lCNorm[0] );
if( !lColors.empty() )
{
IFSG_COLORS nmColor( fsNode );
nmColor.SetColorList( lColors.size(), &lColors[0] );
}
m_sgNode = fsNode.GetRawPtr(); m_sgNode = fsNode.GetRawPtr();
return m_sgNode; return m_sgNode;
@ -805,3 +907,12 @@ void WRL2FACESET::unlinkRefNode( const WRL2NODE* aNode )
WRL2NODE::unlinkRefNode( aNode ); WRL2NODE::unlinkRefNode( aNode );
return; return;
} }
bool WRL2FACESET::HasColors( void )
{
if( NULL == color )
return false;
return ((WRL2COLOR*) color)->HasColors();
}

View File

@ -88,6 +88,12 @@ public:
bool AddRefNode( WRL2NODE* aNode ); bool AddRefNode( WRL2NODE* aNode );
bool AddChildNode( WRL2NODE* aNode ); bool AddChildNode( WRL2NODE* aNode );
SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ); SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals );
/**
* Function HasColors
* returns true if the face set has a color node
*/
bool HasColors( void );
}; };
#endif // VRML2_FACESET_H #endif // VRML2_FACESET_H

View File

@ -27,6 +27,7 @@
#include "vrml2_base.h" #include "vrml2_base.h"
#include "vrml2_shape.h" #include "vrml2_shape.h"
#include "plugins/3dapi/ifsg_all.h" #include "plugins/3dapi/ifsg_all.h"
#include "vrml2_faceset.h"
WRL2SHAPE::WRL2SHAPE() : WRL2NODE() WRL2SHAPE::WRL2SHAPE() : WRL2NODE()
@ -318,9 +319,20 @@ bool WRL2SHAPE::Read( WRLPROC& proc, WRL2BASE* aTopNode )
SGNODE* WRL2SHAPE::TranslateToSG( SGNODE* aParent, bool calcNormals ) SGNODE* WRL2SHAPE::TranslateToSG( SGNODE* aParent, bool calcNormals )
{ {
if( NULL == appearance || NULL == geometry ) // XXX - TO BE IMPLEMENTED:
if( NULL == geometry )
return NULL; return NULL;
// if there is no appearance, make use of the per vertex colors if available
if( NULL == appearance )
{
if( WRL2_INDEXEDFACESET != geometry->GetNodeType() )
return NULL;
if( !((WRL2FACESET*)geometry)->HasColors() )
return NULL;
}
S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent ); S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM ) if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM )
@ -356,10 +368,13 @@ SGNODE* WRL2SHAPE::TranslateToSG( SGNODE* aParent, bool calcNormals )
IFSG_SHAPE shNode( aParent ); IFSG_SHAPE shNode( aParent );
SGNODE* pShape = shNode.GetRawPtr(); SGNODE* pShape = shNode.GetRawPtr();
SGNODE* pApp = appearance->TranslateToSG( pShape, calcNormals );
SGNODE* pGeom = geometry->TranslateToSG( pShape, calcNormals ); SGNODE* pGeom = geometry->TranslateToSG( pShape, calcNormals );
SGNODE* pApp = NULL;
if( NULL == pApp || NULL == pGeom ) if( NULL != appearance )
pApp = appearance->TranslateToSG( pShape, calcNormals );
if( ( NULL != appearance && NULL == pApp ) || NULL == pGeom )
{ {
if( pGeom ) if( pGeom )
{ {

View File

@ -87,14 +87,15 @@ enum WRL1NODES
}; };
// VRML1 Material/Normal Binding values // VRML1 Material/Normal Binding values
// note: PART/FACE have the same meaning in the specification
enum WRL1_BINDING enum WRL1_BINDING
{ {
BIND_DEFAULT = 0, BIND_DEFAULT = 0,
BIND_OVERALL, BIND_OVERALL,
BIND_PER_PART, BIND_PER_PART,
BIND_PER_FACE = BIND_PER_PART,
BIND_PER_PART_INDEXED, BIND_PER_PART_INDEXED,
BIND_PER_FACE, BIND_PER_FACE_INDEXED = BIND_PER_PART_INDEXED,
BIND_PER_FACE_INDEXED,
BIND_PER_VERTEX, BIND_PER_VERTEX,
BIND_PER_VERTEX_INDEXED, BIND_PER_VERTEX_INDEXED,
BIND_END BIND_END