From 6b873ed46bf7265f88da7cf9c0b8ba1857e0d995 Mon Sep 17 00:00:00 2001 From: Cirilo Bernardo Date: Wed, 6 Jan 2016 15:34:14 +1100 Subject: [PATCH] Work in progress: implementing SG translation for VRML1 models --- .../3d_cache/dialogs/panel_prev_model.cpp | 8 +- 3d-viewer/3d_cache/sg/CMakeLists.txt | 2 - 3d-viewer/3d_cache/sg/ifsg_colors.cpp | 2 +- 3d-viewer/3d_cache/sg/sg_faceset.cpp | 132 +---------- 3d-viewer/3d_cache/sg/sg_faceset.h | 1 - 3d-viewer/3d_cache/sg/sg_shape.cpp | 77 ++++--- include/plugins/3dapi/ifsg_all.h | 1 - include/plugins/3dapi/ifsg_colors.h | 2 +- plugins/3d/vrml/v1/vrml1_faceset.cpp | 118 +++++++--- plugins/3d/vrml/v1/vrml1_faceset.h | 2 + plugins/3d/vrml/v1/vrml1_material.cpp | 216 ++++++++++++++++++ plugins/3d/vrml/v1/vrml1_material.h | 18 +- plugins/3d/vrml/v1/vrml1_node.cpp | 6 + plugins/3d/vrml/v1/vrml1_node.h | 2 + plugins/3d/vrml/v1/vrml1_separator.cpp | 92 +++----- plugins/3d/vrml/v1/vrml1_switch.cpp | 10 +- plugins/3d/vrml/v2/vrml2_color.cpp | 27 +++ plugins/3d/vrml/v2/vrml2_color.h | 12 + plugins/3d/vrml/v2/vrml2_faceset.cpp | 165 ++++++++++--- plugins/3d/vrml/v2/vrml2_faceset.h | 6 + plugins/3d/vrml/v2/vrml2_shape.cpp | 21 +- plugins/3d/vrml/wrltypes.h | 5 +- 22 files changed, 632 insertions(+), 293 deletions(-) diff --git a/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp b/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp index af2638ebd7..dd3f54e88f 100644 --- a/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp +++ b/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp @@ -616,8 +616,12 @@ void PANEL_PREV_3D::UpdateModelName( wxString const& aModelName ) #endif wxSizer* ws = new wxBoxSizer( wxHORIZONTAL ); - ws->Add( canvas, 10, wxEXPAND ); - preview->SetSizerAndFit( ws ); + canvas->Set3DModel( *model ); + ws->Add( canvas, 1, wxEXPAND ); + preview->SetSizer( ws ); + preview->Layout(); + ws->FitInside( preview ); + return; } canvas->Set3DModel( *model ); diff --git a/3d-viewer/3d_cache/sg/CMakeLists.txt b/3d-viewer/3d_cache/sg/CMakeLists.txt index f517600923..f4c5d7db2c 100644 --- a/3d-viewer/3d_cache/sg/CMakeLists.txt +++ b/3d-viewer/3d_cache/sg/CMakeLists.txt @@ -15,13 +15,11 @@ add_library( kicad_3dsg SHARED sg_coords.cpp sg_normals.cpp sg_index.cpp - sg_colorindex.cpp sg_coordindex.cpp ifsg_node.cpp ifsg_transform.cpp ifsg_appearance.cpp ifsg_index.cpp - ifsg_colorindex.cpp ifsg_coordindex.cpp ifsg_colors.cpp ifsg_coords.cpp diff --git a/3d-viewer/3d_cache/sg/ifsg_colors.cpp b/3d-viewer/3d_cache/sg/ifsg_colors.cpp index d267bb239d..9d6edbe9a1 100644 --- a/3d-viewer/3d_cache/sg/ifsg_colors.cpp +++ b/3d-viewer/3d_cache/sg/ifsg_colors.cpp @@ -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 ) { diff --git a/3d-viewer/3d_cache/sg/sg_faceset.cpp b/3d-viewer/3d_cache/sg/sg_faceset.cpp index fdb533db7f..af24e31f11 100644 --- a/3d-viewer/3d_cache/sg/sg_faceset.cpp +++ b/3d-viewer/3d_cache/sg/sg_faceset.cpp @@ -35,7 +35,6 @@ SGFACESET::SGFACESET( SGNODE* aParent ) : SGNODE( aParent ) { m_SGtype = S3D::SGTYPE_FACESET; m_Colors = NULL; - m_ColorIndices = NULL; m_Coords = NULL; m_CoordIndices = NULL; m_Normals = NULL; @@ -107,13 +106,6 @@ SGFACESET::~SGFACESET() m_Normals = NULL; } - if( m_ColorIndices ) - { - m_ColorIndices->SetParent( NULL, false ); - delete m_ColorIndices; - m_ColorIndices = NULL; - } - if( m_CoordIndices ) { m_CoordIndices->SetParent( NULL, false ); @@ -173,14 +165,6 @@ SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller) return np; } - if( m_ColorIndices ) - { - np = m_ColorIndices->FindNode( aNodeName, this ); - - if( np ) - return np; - } - if( m_Coords ) { np = m_Coords->FindNode( aNodeName, this ); @@ -241,12 +225,6 @@ void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild ) return; } - if( aNode == m_ColorIndices ) - { - m_ColorIndices = NULL; - return; - } - if( aNode == m_CoordIndices ) { m_CoordIndices = NULL; @@ -377,21 +355,6 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild ) 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( m_CoordIndices ) @@ -440,9 +403,6 @@ void SGFACESET::ReNameNodes( void ) if( m_Colors ) m_Colors->ReNameNodes(); - if( m_ColorIndices ) - m_ColorIndices->ReNameNodes(); - // rename all Coordinates and Indices if( m_Coords ) m_Coords->ReNameNodes(); @@ -510,9 +470,6 @@ bool SGFACESET::WriteVRML( std::ofstream& aFile, bool aReuseFlag ) if( m_RColors ) m_RColors->WriteVRML( aFile, aReuseFlag ); - if( m_ColorIndices ) - m_ColorIndices->WriteVRML( aFile, aReuseFlag ); - aFile << "}\n"; return true; @@ -553,7 +510,7 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode ) } aFile << "[" << GetName() << "]"; - #define NITEMS 8 + #define NITEMS 7 bool items[NITEMS]; int i; @@ -588,10 +545,6 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode ) if( NULL != m_RColors ) items[i] = true; - ++i; - if( NULL != m_ColorIndices ) - items[i] = true; - for( int i = 0; i < NITEMS; ++i ) aFile.write( (char*)&items[i], sizeof(bool) ); @@ -616,9 +569,6 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode ) if( items[6] ) aFile << "[" << m_RColors->GetName() << "]"; - if( items[7] ) - m_ColorIndices->WriteCache( aFile, this ); - if( aFile.fail() ) return false; @@ -629,7 +579,7 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode ) bool SGFACESET::ReadCache( std::ifstream& aFile, SGNODE* parentNode ) { if( m_Coords || m_RCoords || m_CoordIndices - || m_Colors || m_RColors || m_ColorIndices + || m_Colors || m_RColors || m_Normals || m_RNormals ) { std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; @@ -637,7 +587,7 @@ bool SGFACESET::ReadCache( std::ifstream& aFile, SGNODE* parentNode ) return false; } - #define NITEMS 8 + #define NITEMS 7 bool items[NITEMS]; for( int i = 0; i < NITEMS; ++i ) @@ -838,28 +788,6 @@ bool SGFACESET::ReadCache( std::ifstream& aFile, SGNODE* parentNode ) 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() ) return false; @@ -969,62 +897,10 @@ bool SGFACESET::validate( void ) if( NULL != pColors ) { - if( NULL == m_ColorIndices ) - { -#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 + // we must have at least as many colors as vertices size_t nColor = 0; SGCOLOR* pColor = NULL; 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; diff --git a/3d-viewer/3d_cache/sg/sg_faceset.h b/3d-viewer/3d_cache/sg/sg_faceset.h index 4f288773a4..a016ac90dd 100644 --- a/3d-viewer/3d_cache/sg/sg_faceset.h +++ b/3d-viewer/3d_cache/sg/sg_faceset.h @@ -51,7 +51,6 @@ private: public: // owned objects SGCOLORS* m_Colors; - SGCOLORINDEX* m_ColorIndices; SGCOORDS* m_Coords; SGCOORDINDEX* m_CoordIndices; SGNORMALS* m_Normals; diff --git a/3d-viewer/3d_cache/sg/sg_shape.cpp b/3d-viewer/3d_cache/sg/sg_shape.cpp index 90fbfeaea1..f720ec8156 100644 --- a/3d-viewer/3d_cache/sg/sg_shape.cpp +++ b/3d-viewer/3d_cache/sg/sg_shape.cpp @@ -624,7 +624,6 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, } SGCOLORS* pc = pf->m_Colors; - SGCOLORINDEX* cidx = pf->m_ColorIndices; SGCOORDS* pv = pf->m_Coords; SGCOORDINDEX* vidx = pf->m_CoordIndices; SGNORMALS* pn = pf->m_Normals; @@ -643,6 +642,24 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, SGPOINT* pCoords = NULL; 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 size_t nvidx = 0; int* lv = NULL; @@ -673,17 +690,39 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, return true; } - // construct the final vertex list + // construct the final vertex/color list + SFVEC3F* lColors = NULL; SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ]; + double red, green, blue; int ti, ii; - for( size_t i = 0; i < vertices.size(); ++i ) + if( pc ) { - ti = vertices[i]; - glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 ); - pt = (*aTransform) * pt; + SFVEC3F* lColors = new SFVEC3F[vertices.size()]; + m.m_Color = lColors; + } - 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(); @@ -718,30 +757,6 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, } 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 ); return true; diff --git a/include/plugins/3dapi/ifsg_all.h b/include/plugins/3dapi/ifsg_all.h index b64f66b475..eeb0c91f1b 100644 --- a/include/plugins/3dapi/ifsg_all.h +++ b/include/plugins/3dapi/ifsg_all.h @@ -31,7 +31,6 @@ #include "plugins/3dapi/ifsg_colors.h" #include "plugins/3dapi/ifsg_coords.h" #include "plugins/3dapi/ifsg_faceset.h" -#include "plugins/3dapi/ifsg_colorindex.h" #include "plugins/3dapi/ifsg_coordindex.h" #include "plugins/3dapi/ifsg_normals.h" #include "plugins/3dapi/ifsg_shape.h" diff --git a/include/plugins/3dapi/ifsg_colors.h b/include/plugins/3dapi/ifsg_colors.h index b8fd5257ed..dd24af9560 100644 --- a/include/plugins/3dapi/ifsg_colors.h +++ b/include/plugins/3dapi/ifsg_colors.h @@ -50,7 +50,7 @@ public: bool NewNode( IFSG_NODE& aParent ); 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( const SGCOLOR& aColor ); }; diff --git a/plugins/3d/vrml/v1/vrml1_faceset.cpp b/plugins/3d/vrml/v1/vrml1_faceset.cpp index 3a6279d2f2..146eb9e2c5 100644 --- a/plugins/3d/vrml/v1/vrml1_faceset.cpp +++ b/plugins/3d/vrml/v1/vrml1_faceset.cpp @@ -27,6 +27,7 @@ #include "vrml1_base.h" #include "vrml1_faceset.h" #include "vrml1_coords.h" +#include "vrml1_material.h" #include "plugins/3dapi/ifsg_all.h" @@ -172,6 +173,34 @@ bool WRL1FACESET::Read( WRLPROC& proc, WRL1BASE* aTopNode ) 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 { #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 ) { - #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( NULL != aParent ) - { - 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; - } - } + if( NULL != aParent && !S3D::AddSGNodeRef( aParent, m_sgNode ) ) + return NULL; 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(); if( NULL == coord || vsize < 3 ) diff --git a/plugins/3d/vrml/v1/vrml1_faceset.h b/plugins/3d/vrml/v1/vrml1_faceset.h index 24e23f87f3..f983807621 100644 --- a/plugins/3d/vrml/v1/vrml1_faceset.h +++ b/plugins/3d/vrml/v1/vrml1_faceset.h @@ -44,6 +44,8 @@ class WRL1FACESET : public WRL1NODE private: std::vector< int > coordIndex; std::vector< int > matIndex; + std::vector< int > normIndex; + std::vector< int > texIndex; public: WRL1FACESET( NAMEREGISTER* aDictionary ); diff --git a/plugins/3d/vrml/v1/vrml1_material.cpp b/plugins/3d/vrml/v1/vrml1_material.cpp index cc8a6ddd73..c6bbb29e39 100644 --- a/plugins/3d/vrml/v1/vrml1_material.cpp +++ b/plugins/3d/vrml/v1/vrml1_material.cpp @@ -57,6 +57,13 @@ WRL1MATERIAL::~WRL1MATERIAL() std::cerr << " * [INFO] Destroying Material node\n"; #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; } @@ -84,6 +91,9 @@ void WRL1MATERIAL::setDefaults( void ) shininess.push_back( 0.2 ); transparency.push_back( 0.0 ); + colors[0] = NULL; + colors[1] = NULL; + return; } @@ -297,3 +307,209 @@ SGNODE* WRL1MATERIAL::TranslateToSG( SGNODE* aParent, bool calcNormals ) 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; +} diff --git a/plugins/3d/vrml/v1/vrml1_material.h b/plugins/3d/vrml/v1/vrml1_material.h index 56b48ef7ce..871212f3ec 100644 --- a/plugins/3d/vrml/v1/vrml1_material.h +++ b/plugins/3d/vrml/v1/vrml1_material.h @@ -30,10 +30,12 @@ #define VRML1_MATERIAL_H #include +#include #include "vrml1_node.h" class WRL1BASE; class SGNODE; +struct SGCOLOR; /** * Class WRL1MATERIAL @@ -48,7 +50,10 @@ private: std::vector< float > shininess; std::vector< float > transparency; + SGNODE* colors[2]; + void setDefaults( void ); + void checkRange( float& aValue ); public: WRL1MATERIAL( NAMEREGISTER* aDictionary ); @@ -61,7 +66,18 @@ public: bool AddChildNode( WRL1NODE* aNode ); 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 diff --git a/plugins/3d/vrml/v1/vrml1_node.cpp b/plugins/3d/vrml/v1/vrml1_node.cpp index 24f5d78188..41c19aa12a 100644 --- a/plugins/3d/vrml/v1/vrml1_node.cpp +++ b/plugins/3d/vrml/v1/vrml1_node.cpp @@ -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 ) { return m_error; diff --git a/plugins/3d/vrml/v1/vrml1_node.h b/plugins/3d/vrml/v1/vrml1_node.h index bb32ca749e..5672261a77 100644 --- a/plugins/3d/vrml/v1/vrml1_node.h +++ b/plugins/3d/vrml/v1/vrml1_node.h @@ -220,6 +220,8 @@ public: const char* GetNodeTypeName( WRL1NODES aNodeType ) const; + size_t GetNItems( void ) const; + /** * Function FindNode searches the tree of linked nodes and returns a * reference to the current node with the given name. The reference diff --git a/plugins/3d/vrml/v1/vrml1_separator.cpp b/plugins/3d/vrml/v1/vrml1_separator.cpp index a16a863bbf..27095d195e 100644 --- a/plugins/3d/vrml/v1/vrml1_separator.cpp +++ b/plugins/3d/vrml/v1/vrml1_separator.cpp @@ -140,20 +140,26 @@ SGNODE* WRL1SEPARATOR::TranslateToSG( SGNODE* aParent, bool calcNormals ) std::cerr << m_Items.size() << " items)\n"; #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; + } + + if( WRL1_BASE != m_Parent->GetNodeType() ) + m_current = *( m_Parent->GetCurrentSettings() ); + else + m_current.Init(); S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent ); if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM ) { - #ifdef DEBUG_VRML1 + #ifdef DEBUG_VRML2 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"; #endif @@ -162,80 +168,38 @@ SGNODE* WRL1SEPARATOR::TranslateToSG( SGNODE* aParent, bool calcNormals ) if( m_sgNode ) { - if( NULL != aParent ) - { - 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; - } - } + if( NULL == aParent ) + return NULL; + + if( !S3D::AddSGNodeRef( aParent, m_sgNode ) ) + return NULL; return m_sgNode; } IFSG_TRANSFORM txNode( aParent ); + bool hasContent = false; - std::list< WRL1NODE* >::iterator sC = m_Children.begin(); - std::list< WRL1NODE* >::iterator eC = m_Children.end(); - WRL1NODES type; + std::list< WRL1NODE* >::iterator sI = m_Items.begin(); + std::list< WRL1NODE* >::iterator eI = m_Items.end(); - // Include only the following in a Separator node: - // Shape - // Switch - // Separator - // Inline - bool test = false; // set to true if there are any subnodes for display + SGNODE* node = txNode.GetRawPtr(); - for( int i = 0; i < 2; ++i ) + while( sI != eI ) { - while( sC != eC ) - { - type = (*sC)->GetNodeType(); + if( NULL != (*sI)->TranslateToSG( node, calcNormals ) ) + hasContent = true; - switch( type ) - { - 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(); + ++sI; } - if( false == test ) + if( !hasContent ) { txNode.Destroy(); return NULL; } - txNode.SetScale( SGPOINT( scale.x, scale.y, scale.z ) ); - 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 = node; - m_sgNode = txNode.GetRawPtr(); - - return m_sgNode; - */ + return node; } diff --git a/plugins/3d/vrml/v1/vrml1_switch.cpp b/plugins/3d/vrml/v1/vrml1_switch.cpp index 42b19e386f..718b7027e8 100644 --- a/plugins/3d/vrml/v1/vrml1_switch.cpp +++ b/plugins/3d/vrml/v1/vrml1_switch.cpp @@ -189,7 +189,8 @@ SGNODE* WRL1SWITCH::TranslateToSG( SGNODE* aParent, bool calcNormals ) #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 ) std::cerr << " * [INFO] Translating Switch with " << m_Children.size(); 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 if( m_Items.empty() ) @@ -201,7 +202,12 @@ SGNODE* WRL1SWITCH::TranslateToSG( SGNODE* aParent, bool calcNormals ) std::list< WRL1NODE* >::iterator ip = m_Items.begin(); 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 ); } diff --git a/plugins/3d/vrml/v2/vrml2_color.cpp b/plugins/3d/vrml/v2/vrml2_color.cpp index 7714d8a2d8..dbe3c5532e 100644 --- a/plugins/3d/vrml/v2/vrml2_color.cpp +++ b/plugins/3d/vrml/v2/vrml2_color.cpp @@ -194,3 +194,30 @@ SGNODE* WRL2COLOR::TranslateToSG( SGNODE* aParent, bool calcNormals ) // any data manipulation must be performed by the parent node 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; +} diff --git a/plugins/3d/vrml/v2/vrml2_color.h b/plugins/3d/vrml/v2/vrml2_color.h index 6cb324db23..1d9af7da03 100644 --- a/plugins/3d/vrml/v2/vrml2_color.h +++ b/plugins/3d/vrml/v2/vrml2_color.h @@ -59,6 +59,18 @@ public: bool AddRefNode( WRL2NODE* aNode ); bool AddChildNode( WRL2NODE* aNode ); 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 diff --git a/plugins/3d/vrml/v2/vrml2_faceset.cpp b/plugins/3d/vrml/v2/vrml2_faceset.cpp index 7221e51142..e5f08615cc 100644 --- a/plugins/3d/vrml/v2/vrml2_faceset.cpp +++ b/plugins/3d/vrml/v2/vrml2_faceset.cpp @@ -27,6 +27,7 @@ #include "vrml2_base.h" #include "vrml2_faceset.h" #include "vrml2_coords.h" +#include "vrml2_color.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< SGVECTOR > lCNorm; // per-vertex normals 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 - // assuming convex polygons, create triangles for the SG node - for( idx = 3; idx < vsize; ) + if( NULL == color ) { - lCIdx.push_back( i1 ); - - if( ccw ) + // assuming convex polygons, create triangles for the SG node + for( idx = 3; idx < vsize; ) { - lCIdx.push_back( i2 ); - lCIdx.push_back( i3 ); - } - else - { - lCIdx.push_back( i3 ); - lCIdx.push_back( i2 ); - } + lCIdx.push_back( i1 ); - ++nfaces; - i2 = i3; - i3 = coordIndex[idx++]; - - while( ( i1 < 0 || i2 < 0 || i3 < 0 ) && ( idx < vsize ) ) - { - if( i3 < 0 ) + if( ccw ) { - faces.push_back( nfaces ); - nfaces = 0; + lCIdx.push_back( i2 ); + lCIdx.push_back( i3 ); + } + else + { + lCIdx.push_back( i3 ); + lCIdx.push_back( i2 ); } - i1 = i2; + ++nfaces; 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; + while( ( i1 < 0 || i2 < 0 || i3 < 0 ) && ( idx < vsize ) ) + { + if( i3 < 0 ) + { + 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 ); nmNode.SetNormalList( lCNorm.size(), &lCNorm[0] ); + if( !lColors.empty() ) + { + IFSG_COLORS nmColor( fsNode ); + nmColor.SetColorList( lColors.size(), &lColors[0] ); + } + m_sgNode = fsNode.GetRawPtr(); return m_sgNode; @@ -805,3 +907,12 @@ void WRL2FACESET::unlinkRefNode( const WRL2NODE* aNode ) WRL2NODE::unlinkRefNode( aNode ); return; } + + +bool WRL2FACESET::HasColors( void ) +{ + if( NULL == color ) + return false; + + return ((WRL2COLOR*) color)->HasColors(); +} diff --git a/plugins/3d/vrml/v2/vrml2_faceset.h b/plugins/3d/vrml/v2/vrml2_faceset.h index 368d3c0f7c..5397ce8b66 100644 --- a/plugins/3d/vrml/v2/vrml2_faceset.h +++ b/plugins/3d/vrml/v2/vrml2_faceset.h @@ -88,6 +88,12 @@ public: bool AddRefNode( WRL2NODE* aNode ); bool AddChildNode( WRL2NODE* aNode ); 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 diff --git a/plugins/3d/vrml/v2/vrml2_shape.cpp b/plugins/3d/vrml/v2/vrml2_shape.cpp index 7bf4749f5d..b574784ffe 100644 --- a/plugins/3d/vrml/v2/vrml2_shape.cpp +++ b/plugins/3d/vrml/v2/vrml2_shape.cpp @@ -27,6 +27,7 @@ #include "vrml2_base.h" #include "vrml2_shape.h" #include "plugins/3dapi/ifsg_all.h" +#include "vrml2_faceset.h" WRL2SHAPE::WRL2SHAPE() : WRL2NODE() @@ -318,9 +319,20 @@ bool WRL2SHAPE::Read( WRLPROC& proc, WRL2BASE* aTopNode ) SGNODE* WRL2SHAPE::TranslateToSG( SGNODE* aParent, bool calcNormals ) { - if( NULL == appearance || NULL == geometry ) + // XXX - TO BE IMPLEMENTED: + if( NULL == geometry ) 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 ); if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM ) @@ -356,10 +368,13 @@ SGNODE* WRL2SHAPE::TranslateToSG( SGNODE* aParent, bool calcNormals ) IFSG_SHAPE shNode( aParent ); SGNODE* pShape = shNode.GetRawPtr(); - SGNODE* pApp = appearance->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 ) { diff --git a/plugins/3d/vrml/wrltypes.h b/plugins/3d/vrml/wrltypes.h index 6e61eec640..df12f34cf4 100644 --- a/plugins/3d/vrml/wrltypes.h +++ b/plugins/3d/vrml/wrltypes.h @@ -87,14 +87,15 @@ enum WRL1NODES }; // VRML1 Material/Normal Binding values +// note: PART/FACE have the same meaning in the specification enum WRL1_BINDING { BIND_DEFAULT = 0, BIND_OVERALL, BIND_PER_PART, + BIND_PER_FACE = BIND_PER_PART, BIND_PER_PART_INDEXED, - BIND_PER_FACE, - BIND_PER_FACE_INDEXED, + BIND_PER_FACE_INDEXED = BIND_PER_PART_INDEXED, BIND_PER_VERTEX, BIND_PER_VERTEX_INDEXED, BIND_END