From fad73f0e85ff9866d97d3106ff896d134172fbbc Mon Sep 17 00:00:00 2001 From: Cirilo Bernardo Date: Sat, 2 Jan 2016 12:21:02 +1100 Subject: [PATCH] VRML2 3D plugin is now functional --- 3d-viewer/3d_cache/sg/ifsg_api.cpp | 27 ++++ 3d-viewer/3d_cache/sg/sg_faceset.cpp | 3 +- include/plugins/3dapi/ifsg_api.h | 5 + plugins/3d/idf/s3d_plugin_idf.cpp | 3 +- plugins/3d/vrml/v2/vrml2_appearance.cpp | 50 +++++- plugins/3d/vrml/v2/vrml2_appearance.h | 2 +- plugins/3d/vrml/v2/vrml2_base.cpp | 14 +- plugins/3d/vrml/v2/vrml2_base.h | 2 +- plugins/3d/vrml/v2/vrml2_color.cpp | 2 +- plugins/3d/vrml/v2/vrml2_color.h | 2 +- plugins/3d/vrml/v2/vrml2_coords.cpp | 19 ++- plugins/3d/vrml/v2/vrml2_coords.h | 4 +- plugins/3d/vrml/v2/vrml2_faceset.cpp | 198 +++++++++++++++++++++++- plugins/3d/vrml/v2/vrml2_faceset.h | 2 +- plugins/3d/vrml/v2/vrml2_material.cpp | 39 ++++- plugins/3d/vrml/v2/vrml2_material.h | 2 +- plugins/3d/vrml/v2/vrml2_node.cpp | 2 +- plugins/3d/vrml/v2/vrml2_node.h | 4 +- plugins/3d/vrml/v2/vrml2_norms.cpp | 4 +- plugins/3d/vrml/v2/vrml2_norms.h | 2 +- plugins/3d/vrml/v2/vrml2_shape.cpp | 61 +++++++- plugins/3d/vrml/v2/vrml2_shape.h | 2 +- plugins/3d/vrml/v2/vrml2_transform.cpp | 78 +++++++++- plugins/3d/vrml/v2/vrml2_transform.h | 2 +- plugins/3d/vrml/vrml.cpp | 15 +- 25 files changed, 501 insertions(+), 43 deletions(-) diff --git a/3d-viewer/3d_cache/sg/ifsg_api.cpp b/3d-viewer/3d_cache/sg/ifsg_api.cpp index 7e620892ad..bd5b6125b7 100644 --- a/3d-viewer/3d_cache/sg/ifsg_api.cpp +++ b/3d-viewer/3d_cache/sg/ifsg_api.cpp @@ -459,3 +459,30 @@ SGVECTOR S3D::CalcTriNorm( const SGPOINT& p1, const SGPOINT& p2, const SGPOINT& return SGVECTOR( tri.x, tri.y, tri.z ); } + + +S3D::SGTYPES S3D::GetSGNodeType( SGNODE* aNode ) +{ + if( NULL == aNode ) + return SGTYPE_END; + + return aNode->GetNodeType(); +} + + +SGNODE* S3D::GetSGNodeParent( SGNODE* aNode ) +{ + if( NULL == aNode ) + return NULL; + + return aNode->GetParent(); +} + + +bool S3D::AddSGNodeRef( SGNODE* aParent, SGNODE* aChild ) +{ + if( NULL == aParent || NULL == aChild ) + return false; + + return aParent->AddRefNode( aChild ); +} diff --git a/3d-viewer/3d_cache/sg/sg_faceset.cpp b/3d-viewer/3d_cache/sg/sg_faceset.cpp index e7c391828b..fdb533db7f 100644 --- a/3d-viewer/3d_cache/sg/sg_faceset.cpp +++ b/3d-viewer/3d_cache/sg/sg_faceset.cpp @@ -953,7 +953,8 @@ bool SGFACESET::validate( void ) { #ifdef DEBUG std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << " * [INFO] bad model; number of normals does not match number of vertices\n"; + std::cerr << " * [INFO] bad model; number of normals (" << nNorms; + std::cerr << ") does not match number of vertices (" << nCoords << ")\n"; #endif validated = true; valid = false; diff --git a/include/plugins/3dapi/ifsg_api.h b/include/plugins/3dapi/ifsg_api.h index f06bac3192..23aa3d9004 100644 --- a/include/plugins/3dapi/ifsg_api.h +++ b/include/plugins/3dapi/ifsg_api.h @@ -42,6 +42,11 @@ struct S3D_POINT; namespace S3D { + // functions to extract information from SGNODE pointers + SGLIB_API S3D::SGTYPES GetSGNodeType( SGNODE* aNode ); + SGLIB_API SGNODE* GetSGNodeParent( SGNODE* aNode ); + SGLIB_API bool AddSGNodeRef( SGNODE* aParent, SGNODE* aChild ); + /** * Function CalcTriNorm * returns the normal vector of a triangle described by vertices p1, p2, p3 diff --git a/plugins/3d/idf/s3d_plugin_idf.cpp b/plugins/3d/idf/s3d_plugin_idf.cpp index ecb6a633de..157fbac95f 100644 --- a/plugins/3d/idf/s3d_plugin_idf.cpp +++ b/plugins/3d/idf/s3d_plugin_idf.cpp @@ -299,7 +299,8 @@ SCENEGRAPH* Load( char const* aFileName ) if( data ) { wxFileName fn( aFileName ); - wxString output = fn.GetName(); + wxString output = wxT( "z" ); + output.append( fn.GetName() ); output.append( wxT(".wrl") ); S3D::WriteVRML( output, true, (SGNODE*)(data), true, true ); } diff --git a/plugins/3d/vrml/v2/vrml2_appearance.cpp b/plugins/3d/vrml/v2/vrml2_appearance.cpp index 17aa2f13af..426494da19 100644 --- a/plugins/3d/vrml/v2/vrml2_appearance.cpp +++ b/plugins/3d/vrml/v2/vrml2_appearance.cpp @@ -26,6 +26,7 @@ #include "vrml2_base.h" #include "vrml2_appearance.h" +#include "plugins/3dapi/ifsg_all.h" WRL2APPEARANCE::WRL2APPEARANCE() : WRL2NODE() @@ -348,8 +349,51 @@ bool WRL2APPEARANCE::Read( WRLPROC& proc, WRL2BASE* aTopNode ) } -SGNODE* WRL2APPEARANCE::TranslateToSG( SGNODE* aParent ) +SGNODE* WRL2APPEARANCE::TranslateToSG( SGNODE* aParent, bool calcNormals ) { - // XXX - TO IMPLEMENT - return NULL; + if( NULL == material && NULL == texture ) + return NULL; + + S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent ); + + if( NULL != aParent && ptype != S3D::SGTYPE_SHAPE ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] Appearance does not have a Shape parent (parent ID: "; + std::cerr << ptype << ")\n"; + #endif + + return NULL; + } + + if( m_sgNode ) + { + if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode ) + && !S3D::AddSGNodeRef( aParent, m_sgNode ) ) + { + return NULL; + } + + return m_sgNode; + } + + if( NULL != texture ) + { + // use a default gray appearance + IFSG_APPEARANCE matNode( aParent ); + matNode.SetEmissive( 0.0, 0.0, 0.0 ); + matNode.SetSpecular( 0.65, 0.65, 0.65 ); + matNode.SetDiffuse( 0.65, 0.65, 0.65 ); + matNode.SetAmbient( 0.99 ); + matNode.SetShininess( 0.2 ); + matNode.SetTransparency( 0.0 ); + m_sgNode = matNode.GetRawPtr(); + + return m_sgNode; + } + + m_sgNode = material->TranslateToSG( aParent, calcNormals ); + + return m_sgNode; } diff --git a/plugins/3d/vrml/v2/vrml2_appearance.h b/plugins/3d/vrml/v2/vrml2_appearance.h index 6c49f2c0b1..6d904a710f 100644 --- a/plugins/3d/vrml/v2/vrml2_appearance.h +++ b/plugins/3d/vrml/v2/vrml2_appearance.h @@ -64,7 +64,7 @@ public: bool Read( WRLPROC& proc, WRL2BASE* aTopNode ); bool AddRefNode( WRL2NODE* aNode ); bool AddChildNode( WRL2NODE* aNode ); - SGNODE* TranslateToSG( SGNODE* aParent ); + SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ); }; #endif // VRML2_APPEARANCE_H diff --git a/plugins/3d/vrml/v2/vrml2_base.cpp b/plugins/3d/vrml/v2/vrml2_base.cpp index 5819eedc02..eb9e7e1fde 100644 --- a/plugins/3d/vrml/v2/vrml2_base.cpp +++ b/plugins/3d/vrml/v2/vrml2_base.cpp @@ -765,13 +765,13 @@ bool WRL2BASE::readColor( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) } -SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent ) +SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent, bool calcNormals ) { if( m_Children.empty() ) return NULL; - if( m_topNode ) - return m_topNode; + if( m_sgNode ) + return m_sgNode; IFSG_TRANSFORM topNode( aParent ); @@ -793,7 +793,7 @@ SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent ) do { IFSG_TRANSFORM wrapper( topNode.GetRawPtr() ); - SGNODE* pshape = (*sC)->TranslateToSG( wrapper.GetRawPtr() ); + SGNODE* pshape = (*sC)->TranslateToSG( wrapper.GetRawPtr(), calcNormals ); if( NULL != pshape ) test = true; @@ -806,7 +806,7 @@ SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent ) case WRL2_TRANSFORM: - if( NULL != (*sC)->TranslateToSG( topNode.GetRawPtr() ) ) + if( NULL != (*sC)->TranslateToSG( topNode.GetRawPtr(), calcNormals ) ) test = true; break; @@ -824,7 +824,7 @@ SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent ) return NULL; } - m_topNode = topNode.GetRawPtr(); + m_sgNode = topNode.GetRawPtr(); - return m_topNode; + return m_sgNode; } diff --git a/plugins/3d/vrml/v2/vrml2_base.h b/plugins/3d/vrml/v2/vrml2_base.h index 9cf9e65fe8..94982d10d7 100644 --- a/plugins/3d/vrml/v2/vrml2_base.h +++ b/plugins/3d/vrml/v2/vrml2_base.h @@ -91,7 +91,7 @@ public: // functions inherited from WRL2NODE bool Read( WRLPROC& proc, WRL2BASE* aTopNode ); bool SetParent( WRL2NODE* aParent ); - SGNODE* TranslateToSG( SGNODE* aParent ); + SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ); }; #endif // VRML2_BASE_H diff --git a/plugins/3d/vrml/v2/vrml2_color.cpp b/plugins/3d/vrml/v2/vrml2_color.cpp index 2595e333f5..d27abe51c2 100644 --- a/plugins/3d/vrml/v2/vrml2_color.cpp +++ b/plugins/3d/vrml/v2/vrml2_color.cpp @@ -189,7 +189,7 @@ bool WRL2COLOR::Read( WRLPROC& proc, WRL2BASE* aTopNode ) } -SGNODE* WRL2COLOR::TranslateToSG( SGNODE* aParent ) +SGNODE* WRL2COLOR::TranslateToSG( SGNODE* aParent, bool calcNormals ) { // XXX - TO IMPLEMENT return NULL; diff --git a/plugins/3d/vrml/v2/vrml2_color.h b/plugins/3d/vrml/v2/vrml2_color.h index b4554938d0..6cb324db23 100644 --- a/plugins/3d/vrml/v2/vrml2_color.h +++ b/plugins/3d/vrml/v2/vrml2_color.h @@ -58,7 +58,7 @@ public: bool Read( WRLPROC& proc, WRL2BASE* aTopNode ); bool AddRefNode( WRL2NODE* aNode ); bool AddChildNode( WRL2NODE* aNode ); - SGNODE* TranslateToSG( SGNODE* aParent ); + SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ); }; #endif // VRML2_COLOR_H diff --git a/plugins/3d/vrml/v2/vrml2_coords.cpp b/plugins/3d/vrml/v2/vrml2_coords.cpp index b41a1d84b3..923a4b80c8 100644 --- a/plugins/3d/vrml/v2/vrml2_coords.cpp +++ b/plugins/3d/vrml/v2/vrml2_coords.cpp @@ -189,8 +189,23 @@ bool WRL2COORDS::Read( WRLPROC& proc, WRL2BASE* aTopNode ) } -SGNODE* WRL2COORDS::TranslateToSG( SGNODE* aParent ) +void WRL2COORDS::GetCoords( WRLVEC3F*& aCoordList, size_t& aListSize ) { - // XXX - TO IMPLEMENT + if( points.size() < 3 ) + { + aCoordList = NULL; + aListSize = 0; + return; + } + + aCoordList = &points[0]; + aListSize = points.size(); + return; +} + + +SGNODE* WRL2COORDS::TranslateToSG( SGNODE* aParent, bool calcNormals ) +{ + // any data manipulation must be performed by the parent node return NULL; } diff --git a/plugins/3d/vrml/v2/vrml2_coords.h b/plugins/3d/vrml/v2/vrml2_coords.h index 0f6d3aaa3b..ba6f1bdecd 100644 --- a/plugins/3d/vrml/v2/vrml2_coords.h +++ b/plugins/3d/vrml/v2/vrml2_coords.h @@ -58,7 +58,9 @@ public: bool Read( WRLPROC& proc, WRL2BASE* aTopNode ); bool AddRefNode( WRL2NODE* aNode ); bool AddChildNode( WRL2NODE* aNode ); - SGNODE* TranslateToSG( SGNODE* aParent ); + SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ); + + void GetCoords( WRLVEC3F*& aCoordList, size_t& aListSize ); }; #endif // VRML2_COORDS_H diff --git a/plugins/3d/vrml/v2/vrml2_faceset.cpp b/plugins/3d/vrml/v2/vrml2_faceset.cpp index ef3fa8e479..eeaab8a160 100644 --- a/plugins/3d/vrml/v2/vrml2_faceset.cpp +++ b/plugins/3d/vrml/v2/vrml2_faceset.cpp @@ -26,7 +26,8 @@ #include "vrml2_base.h" #include "vrml2_faceset.h" - +#include "vrml2_coords.h" +#include "plugins/3dapi/ifsg_all.h" WRL2FACESET::WRL2FACESET() : WRL2NODE() @@ -560,8 +561,197 @@ bool WRL2FACESET::Read( WRLPROC& proc, WRL2BASE* aTopNode ) } -SGNODE* WRL2FACESET::TranslateToSG( SGNODE* aParent ) +SGNODE* WRL2FACESET::TranslateToSG( SGNODE* aParent, bool calcNormals ) { - // XXX - TO IMPLEMENT - return NULL; + S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent ); + + if( NULL != aParent && ptype != S3D::SGTYPE_SHAPE ) + { + #ifdef DEBUG + 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 && aParent != S3D::GetSGNodeParent( m_sgNode ) + && !S3D::AddSGNodeRef( aParent, m_sgNode ) ) + { + return NULL; + } + + return m_sgNode; + } + + size_t vsize = coordIndex.size(); + + if( NULL == coord || vsize < 3 ) + return NULL; + + // create the index list and make sure we have >3 points + size_t idx; + int i1 = coordIndex[0]; + int i2 = coordIndex[1]; + int i3 = coordIndex[2]; + + WRLVEC3F* pcoords; + size_t coordsize; + ((WRL2COORDS*) coord)->GetCoords( pcoords, coordsize ); + + if( coordsize < 3 ) + return NULL; + + // check that all indices are valid + for( idx = 0; idx < vsize; ++idx ) + { + if( coordIndex[idx] < 0 ) + continue; + + if( coordIndex[idx] >= (int)coordsize ) + return NULL; + } + + // if the indices are defective just give up + if( i1 < 0 || i2 < 0 || i3 < 0 + || i1 == i2 || i1 == i3 || i2 == i3 ) + return NULL; + + std::vector< SGPOINT > lCPts; // coordinate points for SG node + 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 + 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; ) + { + lCIdx.push_back( i1 ); + + 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++]; + + 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; + } + } + + if( lCIdx.empty() ) + return NULL; + + if( calcNormals || NULL == normal ) + { + // create a vertex list for per-face per-vertex normals + std::vector< int >::iterator sI = lCIdx.begin(); + std::vector< int >::iterator eI = lCIdx.end(); + + while( sI != eI ) + { + lCPts.push_back( SGPOINT( pcoords[*sI].x, pcoords[*sI].y, pcoords[*sI].z ) ); + ++sI; + } + + for( size_t i = 0; i < lCPts.size(); i += 3 ) + { + SGVECTOR sv = S3D::CalcTriNorm( lCPts[i], lCPts[i+1], lCPts[i+2] ); + lCNorm.push_back( sv ); + lCNorm.push_back( sv ); + lCNorm.push_back( sv ); + } + + } + else + { + // XXX - TO IMPLEMENT + return NULL; + /* + // use the vertex list as is + if( normalPerVertex ) + { + // normalPerVertex = TRUE + // rules: + // + if normalIndex is not EMPTY, it is used to select a normal for each vertex + // + if normalIndex is EMPTY, the normal list is used in order per vertex + + if( normalIndex.empty() ) + { + for( size_t i = 0; i < coordsize; ++i ) + { + lCPts.push_back( SGPOINT( pcoords[i].x, pcoords[i].y, pcoords[i].z ) ); + + // XXX - TO IMPLEMENT + } + } + else + { + // XXX - TO IMPLEMENT: index the normals + } + } + else + { + // normalPerVertex = FALSE + // rules: + // + if normalIndex is not EMPTY, it is used to select a normal for each face + // + if normalIndex is EMPTY, the normal list is used in order per face + + } + //*/ + } + + // XXX - TO IMPLEMENT: Per-vertex colors + + IFSG_FACESET fsNode( aParent ); + IFSG_COORDS cpNode( fsNode ); + cpNode.SetCoordsList( lCPts.size(), &lCPts[0] ); + IFSG_COORDINDEX ciNode( fsNode ); + + if( calcNormals || NULL == normal ) + { + for( int i = 0; i < (int)lCPts.size(); ++i ) + ciNode.AddIndex( i ); + } + else + { + ciNode.SetIndices( lCIdx.size(), &lCIdx[0] ); + } + + IFSG_NORMALS nmNode( fsNode ); + nmNode.SetNormalList( lCNorm.size(), &lCNorm[0] ); + + std::cerr << "XXX: [face] NPts : " << lCPts.size() << "\n"; + std::cerr << "XXX: [face] NNorm: " << lCNorm.size() << "\n"; + std::cerr << "XXX: [face] NIdx : " << lCIdx.size() << "\n"; + + m_sgNode = fsNode.GetRawPtr(); + + return m_sgNode; } diff --git a/plugins/3d/vrml/v2/vrml2_faceset.h b/plugins/3d/vrml/v2/vrml2_faceset.h index d020e47843..f55ebb5848 100644 --- a/plugins/3d/vrml/v2/vrml2_faceset.h +++ b/plugins/3d/vrml/v2/vrml2_faceset.h @@ -82,7 +82,7 @@ public: bool Read( WRLPROC& proc, WRL2BASE* aTopNode ); bool AddRefNode( WRL2NODE* aNode ); bool AddChildNode( WRL2NODE* aNode ); - SGNODE* TranslateToSG( SGNODE* aParent ); + SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ); }; #endif // VRML2_FACESET_H diff --git a/plugins/3d/vrml/v2/vrml2_material.cpp b/plugins/3d/vrml/v2/vrml2_material.cpp index c48aa3d14c..be91cc5001 100644 --- a/plugins/3d/vrml/v2/vrml2_material.cpp +++ b/plugins/3d/vrml/v2/vrml2_material.cpp @@ -26,6 +26,7 @@ #include "vrml2_base.h" #include "vrml2_material.h" +#include "plugins/3dapi/ifsg_all.h" WRL2MATERIAL::WRL2MATERIAL() : WRL2NODE() @@ -287,8 +288,40 @@ bool WRL2MATERIAL::Read( WRLPROC& proc, WRL2BASE* aTopNode ) } -SGNODE* WRL2MATERIAL::TranslateToSG( SGNODE* aParent ) +SGNODE* WRL2MATERIAL::TranslateToSG( SGNODE* aParent, bool calcNormals ) { - // XXX - TO IMPLEMENT - return NULL; + S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent ); + + if( NULL != aParent && ptype != S3D::SGTYPE_SHAPE ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] Material does not have a Shape parent (parent ID: "; + std::cerr << ptype << ")\n"; + #endif + + return NULL; + } + + if( m_sgNode ) + { + if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode ) + && !S3D::AddSGNodeRef( aParent, m_sgNode ) ) + { + return NULL; + } + + return m_sgNode; + } + + IFSG_APPEARANCE matNode( aParent ); + matNode.SetEmissive( emissiveColor.x, emissiveColor.y, emissiveColor.z ); + matNode.SetSpecular( specularColor.x, specularColor.y, specularColor.z ); + matNode.SetDiffuse( diffuseColor.x, diffuseColor.y, diffuseColor.z ); + matNode.SetAmbient( ambientIntensity ); + matNode.SetShininess( shininess ); + matNode.SetTransparency( transparency ); + m_sgNode = matNode.GetRawPtr(); + + return m_sgNode; } diff --git a/plugins/3d/vrml/v2/vrml2_material.h b/plugins/3d/vrml/v2/vrml2_material.h index c3daa1f953..1d84d0b0b1 100644 --- a/plugins/3d/vrml/v2/vrml2_material.h +++ b/plugins/3d/vrml/v2/vrml2_material.h @@ -63,7 +63,7 @@ public: bool Read( WRLPROC& proc, WRL2BASE* aTopNode ); bool AddRefNode( WRL2NODE* aNode ); bool AddChildNode( WRL2NODE* aNode ); - SGNODE* TranslateToSG( SGNODE* aParent ); + SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ); }; #endif // VRML2_MATERIAL_H diff --git a/plugins/3d/vrml/v2/vrml2_node.cpp b/plugins/3d/vrml/v2/vrml2_node.cpp index 8cef1b4e0c..14ce5185a0 100644 --- a/plugins/3d/vrml/v2/vrml2_node.cpp +++ b/plugins/3d/vrml/v2/vrml2_node.cpp @@ -42,7 +42,7 @@ static NODEMAP nodenames; WRL2NODE::WRL2NODE() { - m_topNode = NULL; + m_sgNode = NULL; m_Parent = NULL; m_Type = WRL2_END; diff --git a/plugins/3d/vrml/v2/vrml2_node.h b/plugins/3d/vrml/v2/vrml2_node.h index a39e856b4e..ec993e1893 100644 --- a/plugins/3d/vrml/v2/vrml2_node.h +++ b/plugins/3d/vrml/v2/vrml2_node.h @@ -67,7 +67,7 @@ protected: std::list< WRL2NODE* > m_Refs; // nodes referenced by this node std::string m_error; - SGNODE* m_topNode; // the SGNODE representation of the display data + SGNODE* m_sgNode; // the SGNODE representation of the display data public: @@ -185,7 +185,7 @@ public: * @param aParent is a pointer to the parent SG node * @return is non-NULL on success */ - virtual SGNODE* TranslateToSG( SGNODE* aParent ) = 0; + virtual SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ) = 0; }; #endif // VRML2_NODE_H diff --git a/plugins/3d/vrml/v2/vrml2_norms.cpp b/plugins/3d/vrml/v2/vrml2_norms.cpp index 8845d75749..04c2c5f272 100644 --- a/plugins/3d/vrml/v2/vrml2_norms.cpp +++ b/plugins/3d/vrml/v2/vrml2_norms.cpp @@ -189,8 +189,8 @@ bool WRL2NORMS::Read( WRLPROC& proc, WRL2BASE* aTopNode ) } -SGNODE* WRL2NORMS::TranslateToSG( SGNODE* aParent ) +SGNODE* WRL2NORMS::TranslateToSG( SGNODE* aParent, bool calcNormals ) { - // XXX - TO IMPLEMENT + // any data manipulation must be performed by the parent node return NULL; } diff --git a/plugins/3d/vrml/v2/vrml2_norms.h b/plugins/3d/vrml/v2/vrml2_norms.h index 7eb5a5ff34..929f2ee48a 100644 --- a/plugins/3d/vrml/v2/vrml2_norms.h +++ b/plugins/3d/vrml/v2/vrml2_norms.h @@ -58,7 +58,7 @@ public: bool Read( WRLPROC& proc, WRL2BASE* aTopNode ); bool AddRefNode( WRL2NODE* aNode ); bool AddChildNode( WRL2NODE* aNode ); - SGNODE* TranslateToSG( SGNODE* aParent ); + SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ); }; #endif // VRML2_NORMS_H diff --git a/plugins/3d/vrml/v2/vrml2_shape.cpp b/plugins/3d/vrml/v2/vrml2_shape.cpp index ec32310f9d..ac697f353c 100644 --- a/plugins/3d/vrml/v2/vrml2_shape.cpp +++ b/plugins/3d/vrml/v2/vrml2_shape.cpp @@ -26,6 +26,7 @@ #include "vrml2_base.h" #include "vrml2_shape.h" +#include "plugins/3dapi/ifsg_all.h" WRL2SHAPE::WRL2SHAPE() : WRL2NODE() @@ -311,8 +312,62 @@ bool WRL2SHAPE::Read( WRLPROC& proc, WRL2BASE* aTopNode ) } -SGNODE* WRL2SHAPE::TranslateToSG( SGNODE* aParent ) +SGNODE* WRL2SHAPE::TranslateToSG( SGNODE* aParent, bool calcNormals ) { - // XXX - TO IMPLEMENT - return NULL; + if( NULL == appearance && NULL == geometry ) + return NULL; + + S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent ); + + if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] Shape does not have a Transform parent (parent ID: "; + std::cerr << ptype << ")\n"; + #endif + + return NULL; + } + + if( m_sgNode ) + { + if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode ) + && !S3D::AddSGNodeRef( aParent, m_sgNode ) ) + { + return NULL; + } + + return m_sgNode; + } + + IFSG_SHAPE shNode( aParent ); + + SGNODE* pShape = shNode.GetRawPtr(); + SGNODE* pApp = appearance->TranslateToSG( pShape, calcNormals ); + SGNODE* pGeom = geometry->TranslateToSG( pShape, calcNormals ); + + if( NULL == pApp || NULL == pGeom ) + { + if( pGeom ) + { + IFSG_FACESET tmp( false ); + tmp.Attach( pGeom ); + tmp.Destroy(); + } + + if( pApp ) + { + IFSG_APPEARANCE tmp( false ); + tmp.Attach( pApp ); + tmp.Destroy(); + } + + shNode.Destroy(); + return NULL; + } + + m_sgNode = shNode.GetRawPtr(); + + return m_sgNode; } diff --git a/plugins/3d/vrml/v2/vrml2_shape.h b/plugins/3d/vrml/v2/vrml2_shape.h index 18406411a9..41f51bcdd4 100644 --- a/plugins/3d/vrml/v2/vrml2_shape.h +++ b/plugins/3d/vrml/v2/vrml2_shape.h @@ -63,7 +63,7 @@ public: bool Read( WRLPROC& proc, WRL2BASE* aTopNode ); bool AddRefNode( WRL2NODE* aNode ); bool AddChildNode( WRL2NODE* aNode ); - SGNODE* TranslateToSG( SGNODE* aParent ); + SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ); }; #endif // VRML2_SHAPE_H diff --git a/plugins/3d/vrml/v2/vrml2_transform.cpp b/plugins/3d/vrml/v2/vrml2_transform.cpp index 20b073263b..60270b994b 100644 --- a/plugins/3d/vrml/v2/vrml2_transform.cpp +++ b/plugins/3d/vrml/v2/vrml2_transform.cpp @@ -25,6 +25,7 @@ #include "vrml2_base.h" #include "vrml2_transform.h" +#include "plugins/3dapi/ifsg_all.h" WRL2TRANSFORM::WRL2TRANSFORM() : WRL2NODE() @@ -335,8 +336,79 @@ bool WRL2TRANSFORM::readChildren( WRLPROC& proc, WRL2BASE* aTopNode ) } -SGNODE* WRL2TRANSFORM::TranslateToSG( SGNODE* aParent ) +SGNODE* WRL2TRANSFORM::TranslateToSG( SGNODE* aParent, bool calcNormals ) { - // XXX - TO IMPLEMENT - return NULL; + if( m_Children.empty() && m_Refs.empty() ) + return NULL; + + S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent ); + + if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] Transform does not have a Transform parent (parent ID: "; + std::cerr << ptype << ")\n"; + #endif + + return NULL; + } + + if( m_sgNode ) + { + if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode ) + && !S3D::AddSGNodeRef( aParent, m_sgNode ) ) + { + return NULL; + } + + return m_sgNode; + } + + IFSG_TRANSFORM txNode( aParent ); + + std::list< WRL2NODE* >::iterator sC = m_Children.begin(); + std::list< WRL2NODE* >::iterator eC = m_Children.end(); + WRL2NODES type; + + // Include only Shape and Transform nodes in a Transform node + bool test = false; // set to true if there are any subnodes for display + + while( sC != eC ) + { + type = (*sC)->GetNodeType(); + + switch( type ) + { + case WRL2_SHAPE: + case WRL2_TRANSFORM: + + if( NULL != (*sC)->TranslateToSG( txNode.GetRawPtr(), calcNormals ) ) + test = true; + + break; + + default: + break; + } + + ++ sC; + } + + if( false == test ) + { + 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 = txNode.GetRawPtr(); + + return m_sgNode; } diff --git a/plugins/3d/vrml/v2/vrml2_transform.h b/plugins/3d/vrml/v2/vrml2_transform.h index 857064eafc..ade1fd94f1 100644 --- a/plugins/3d/vrml/v2/vrml2_transform.h +++ b/plugins/3d/vrml/v2/vrml2_transform.h @@ -63,7 +63,7 @@ public: // functions inherited from WRL2NODE bool Read( WRLPROC& proc, WRL2BASE* aTopNode ); bool AddRefNode( WRL2NODE* aNode ); - SGNODE* TranslateToSG( SGNODE* aParent ); + SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ); }; #endif // VRML2_TRANSFORM_H diff --git a/plugins/3d/vrml/vrml.cpp b/plugins/3d/vrml/vrml.cpp index 246e6ef467..477288a1ef 100644 --- a/plugins/3d/vrml/vrml.cpp +++ b/plugins/3d/vrml/vrml.cpp @@ -209,11 +209,24 @@ SCENEGRAPH* Load( char const* aFileName ) std::cout << " * [INFO] load completed\n"; #endif - scene = (SCENEGRAPH*)bp->TranslateToSG( NULL ); + // XXX - for now we recalculate all normals per-vertex per-facet + scene = (SCENEGRAPH*)bp->TranslateToSG( NULL, true ); } delete bp; } + // DEBUG: WRITE OUT VRML2 FILE TO CONFIRM STRUCTURE + #ifdef DEBUG + if( scene ) + { + wxFileName fn( wxString::FromUTF8Unchecked( aFileName ) ); + wxString output = wxT( "_" ); + output.append( fn.GetName() ); + output.append( wxT(".wrl") ); + S3D::WriteVRML( output, true, (SGNODE*)(scene), true, true ); + } + #endif + return scene; }