From 86042d86a6fa11f8406f83e253a2cf2f9ec41561 Mon Sep 17 00:00:00 2001 From: Cirilo Bernardo Date: Fri, 11 Dec 2015 17:37:42 +1100 Subject: [PATCH] Added partial render ability to IDF plugin --- 3d-viewer/3d_cache/3d_cache.cpp | 21 ++-- plugins/3d/idf/s3d_plugin_idf.cpp | 95 +++++++++----- plugins/3d/tetra/s3d_plugin_tetra.cpp | 8 +- utils/idftools/vrml_layer.cpp | 170 ++++++++++++++++++++++++++ utils/idftools/vrml_layer.h | 14 +++ 5 files changed, 266 insertions(+), 42 deletions(-) diff --git a/3d-viewer/3d_cache/3d_cache.cpp b/3d-viewer/3d_cache/3d_cache.cpp index d42027fea3..e46d2bd14a 100644 --- a/3d-viewer/3d_cache/3d_cache.cpp +++ b/3d-viewer/3d_cache/3d_cache.cpp @@ -21,6 +21,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#define GLM_FORCE_RADIANS + #include #include #include @@ -598,21 +600,24 @@ S3DMODEL* S3D_CACHE::Prepare( S3D_INFO const* aModelEntry, return NULL; // create a single transform entity to apply to the models - glm::dmat4 t0 = glm::translate( glm::dvec3( 25.4 * aModelEntry->offset.x, 25.4 * aModelEntry->offset.y, - 25.4 * aModelEntry->offset.z ) ); + glm::dmat4 t0 = glm::translate( glm::dvec3( 25.4 * aModelEntry->offset.x, + 25.4 * aModelEntry->offset.y, 25.4 * aModelEntry->offset.z ) ); - glm::dmat4 rX = glm::rotate( aModelEntry->rotation.x, glm::dvec3( 1.0, 0.0, 0.0 ) ); - glm::dmat4 rY = glm::rotate( -aModelEntry->rotation.y, glm::dvec3( 0.0, 1.0, 0.0 ) ); - glm::dmat4 rZ = glm::rotate( aModelEntry->rotation.z, glm::dvec3( 0.0, 0.0, 1.0 ) ); + glm::dmat4 rX = glm::rotate( glm::radians( aModelEntry->rotation.x ), + glm::dvec3( 1.0, 0.0, 0.0 ) ); + glm::dmat4 rY = glm::rotate( glm::radians( -aModelEntry->rotation.y ), + glm::dvec3( 0.0, 1.0, 0.0 ) ); + glm::dmat4 rZ = glm::rotate( glm::radians( aModelEntry->rotation.z ), + glm::dvec3( 0.0, 0.0, 1.0 ) ); glm::dmat4 s0 = glm::scale( glm::dvec3( aModelEntry->scale.x, aModelEntry->scale.y, aModelEntry->scale.z ) ); glm::dmat4 m0 = rZ * rY * rX * s0 * t0; - rX = glm::rotate( aRotation.x, glm::dvec3( 1.0, 0.0, 0.0 ) ); - rY = glm::rotate( aRotation.y, glm::dvec3( 0.0, 1.0, 0.0 ) ); - rZ = glm::rotate( aRotation.z, glm::dvec3( 0.0, 0.0, 1.0 ) ); + rX = glm::rotate( glm::radians( aRotation.x ), glm::dvec3( 1.0, 0.0, 0.0 ) ); + rY = glm::rotate( glm::radians( aRotation.y ), glm::dvec3( 0.0, 1.0, 0.0 ) ); + rZ = glm::rotate( glm::radians( aRotation.z ), glm::dvec3( 0.0, 0.0, 1.0 ) ); glm::dmat4 t1 = glm::translate( glm::dvec3( aOffset.x, aOffset.y, aOffset.z ) ); diff --git a/plugins/3d/idf/s3d_plugin_idf.cpp b/plugins/3d/idf/s3d_plugin_idf.cpp index 3e62209b3d..75b658fe8a 100644 --- a/plugins/3d/idf/s3d_plugin_idf.cpp +++ b/plugins/3d/idf/s3d_plugin_idf.cpp @@ -98,7 +98,7 @@ int S3D_PLUGIN_IDF::GetNFilters( void ) const const wxString S3D_PLUGIN_IDF::GetFileFilter( int aIndex ) const { - if( aIndex < 0 || aIndex >= m_filters.size() ) + if( aIndex < 0 || aIndex >= (int)m_filters.size() ) return wxEmptyString; return m_filters[aIndex]; @@ -115,56 +115,91 @@ bool S3D_PLUGIN_IDF::CanRender( void ) const SCENEGRAPH* S3D_PLUGIN_IDF::Load( const wxString& aFileName ) { // load and render the file - #warning TO BE IMPLEMENTED IDF3_BOARD brd( IDF3::CAD_ELEC ); IDF3_COMP_OUTLINE* outline = brd.GetComponentOutline( aFileName ); if( NULL == outline ) - return NULL; - - // render the component outline - const std::map< std::string, IDF3_COMPONENT* >*const comp = brd.GetComponents(); - size_t asize = comp->size(); - - if( 1 != asize ) { #ifdef DEBUG std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << " * [INFO] unexpected number of components: " << asize << "\n"; + std::cerr << " * [INFO] no outline for file '"; + std::cerr << aFileName.ToUTF8() << "'\n"; #endif return NULL; } - const std::list< IDF3_COMP_OUTLINE_DATA* >* - ip = comp[0].begin()->second->GetOutlinesData(); - - asize = ip->size(); - - if( 1 != asize ) - { - #ifdef DEBUG - std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << " * [INFO] unexpected number of outlines: " << asize << "\n"; - #endif - return NULL; - } - - IDF3_COMP_OUTLINE_DATA* dp = *( ip->begin() ); - IDF3_COMP_OUTLINE* pout = (IDF3_COMP_OUTLINE*)( dp->GetOutline() ); VRML_LAYER vpcb; - if( !PopulateVRML( vpcb, pout->GetOutlines() ) ) + if( !PopulateVRML( vpcb, outline->GetOutlines() ) ) { #ifdef DEBUG std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << " * [INFO] no valid outline data\n"; + std::cerr << " * [INFO] no valid outline data in '"; + std::cerr << aFileName.ToUTF8() << "'\n"; #endif return NULL; } - // XXX - TO BE IMPLEMENTED + vpcb.Tesselate( NULL ); + std::vector< double > vertices; + std::vector< int > indices; + double thick = outline->GetThickness(); - return NULL; + if( !vpcb.Get3DTriangles( vertices, indices, thick, 0.0 ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] no vertex data in '"; + std::cerr << aFileName.ToUTF8() << "'\n"; + #endif + return NULL; + } + + std::cerr << "XXX - Got " << vertices.size() / 3 << " vertices and " << indices.size() << " indices\n"; + std::vector< SGPOINT > vlist; + size_t nvert = vertices.size() / 3; + size_t j = 0; + + for( size_t i = 0; i < nvert; ++i, j+= 3 ) + vlist.push_back( SGPOINT( vertices[j], vertices[j+1], vertices[j+2] ) ); + + // create the intermediate scenegraph + IFSG_TRANSFORM* tx0 = new IFSG_TRANSFORM( true ); + IFSG_SHAPE* shape = new IFSG_SHAPE( *tx0 ); + IFSG_FACESET* face = new IFSG_FACESET( *shape ); + IFSG_COORDS* cp = new IFSG_COORDS( *face ); + cp->SetCoordsList( nvert, &vlist[0] ); + IFSG_COORDINDEX* coordIdx = new IFSG_COORDINDEX( *face ); + coordIdx->SetIndices( indices.size(), &indices[0] ); + + // XXX - TO BE IMPLEMENTED : add correct normals and colors + std::vector< SGVECTOR > norms; + + for( size_t i = 0; i < nvert; ++i ) + norms.push_back( SGVECTOR( 0.0, 0.0, 1.0 ) ); + + IFSG_NORMALS* np = new IFSG_NORMALS( *face ); + np->SetNormalList( nvert, &norms[0] ); + + // magenta + IFSG_APPEARANCE* material = new IFSG_APPEARANCE( *shape); + material->SetSpecular( 1.0, 0.0, 1.0 ); + material->SetDiffuse( 0.9, 0.0, 0.9 ); + material->SetAmbient( 0.9 ); + material->SetShininess( 0.3 ); + + SCENEGRAPH* data = (SCENEGRAPH*)tx0->GetRawPtr(); + + // delete the API wrappers + delete shape; + delete face; + delete coordIdx; + delete material; + delete cp; + delete np; + delete tx0; + + return data; } diff --git a/plugins/3d/tetra/s3d_plugin_tetra.cpp b/plugins/3d/tetra/s3d_plugin_tetra.cpp index de21917c7d..e22cfda48a 100644 --- a/plugins/3d/tetra/s3d_plugin_tetra.cpp +++ b/plugins/3d/tetra/s3d_plugin_tetra.cpp @@ -155,10 +155,10 @@ SCENEGRAPH* S3D_PLUGIN_TETRA::Load( const wxString& aFileName ) // the vertex normals in this case are the normalized // vertex points SGVECTOR norm[4]; - norm[0] = SGVECTOR( -1.0, 0.0, SQ2 ); - norm[1] = SGVECTOR( 1.0, 0.0, SQ2 ); - norm[2] = SGVECTOR( 0.0, -1.0, -SQ2 ); - norm[3] = SGVECTOR( 0.0, 1.0, -SQ2 ); + norm[0] = SGVECTOR( -1.0, 0.0, -SQ2 ); + norm[1] = SGVECTOR( 1.0, 0.0, -SQ2 ); + norm[2] = SGVECTOR( 0.0, -1.0, SQ2 ); + norm[3] = SGVECTOR( 0.0, 1.0, SQ2 ); IFSG_NORMALS* np = new IFSG_NORMALS( *face ); np->SetNormalList( 4, norm ); diff --git a/utils/idftools/vrml_layer.cpp b/utils/idftools/vrml_layer.cpp index 5974371660..d31dcffc5b 100644 --- a/utils/idftools/vrml_layer.cpp +++ b/utils/idftools/vrml_layer.cpp @@ -1786,3 +1786,173 @@ void VRML_LAYER::SetVertexOffsets( double aXoffset, double aYoffset ) offsetY = aYoffset; return; } + + +bool VRML_LAYER::Get3DTriangles( std::vector< double >& aVertexList, + std::vector< int > &aIndexList, double aTopZ, double aBotZ ) +{ + aVertexList.clear(); + aIndexList.clear(); + + if( ordmap.size() < 3 || outline.empty() ) + return false; + + if( aTopZ <= aBotZ ) + { + double tmp = aBotZ; + aBotZ = aTopZ; + aTopZ = tmp; + } + + VERTEX_3D* vp = getVertexByIndex( ordmap[0], pholes ); + + if( !vp ) + return false; + + size_t i, j, k; + size_t vsize = ordmap.size(); + j = 0; + k = vsize; + + // top vertices + for( i = 0; i < vsize; ++i ) + { + vp = getVertexByIndex( ordmap[i], pholes ); + + if( !vp ) + { + aVertexList.clear(); + return false; + } + + aVertexList.push_back( vp->x ); + aVertexList.push_back( vp->y ); + aVertexList.push_back( aTopZ ); + } + + // bottom vertices + for( i = 0; i < vsize; ++i ) + { + vp = getVertexByIndex( ordmap[i], pholes ); + + aVertexList.push_back( vp->x ); + aVertexList.push_back( vp->y ); + aVertexList.push_back( aBotZ ); + } + + // create the index lists .. it is difficult to estimate the list size + // a priori so instead we use a vector to help + + bool holes_only = triplets.empty(); + + if( !holes_only ) + { + // go through the triplet list and write out the indices based on order + std::list< TRIPLET_3D >::const_iterator tbeg = triplets.begin(); + std::list< TRIPLET_3D >::const_iterator tend = triplets.end(); + + while( tbeg != tend ) + { + // top vertices + aIndexList.push_back( (int) tbeg->i1 ); + aIndexList.push_back( (int) tbeg->i2 ); + aIndexList.push_back( (int) tbeg->i3 ); + + // bottom vertices + aIndexList.push_back( (int) ( tbeg->i2 + vsize ) ); + aIndexList.push_back( (int) ( tbeg->i1 + vsize ) ); + aIndexList.push_back( (int) ( tbeg->i3 + vsize ) ); + + ++tbeg; + } + } + + // compile indices for the walls joining top to bottom + int lastPoint; + int curPoint; + int curContour = 0; + + std::list< std::list< int >* >::const_iterator obeg = outline.begin(); + std::list< std::list< int >* >::const_iterator oend = outline.end(); + std::list< int >* cp; + std::list< int >::const_iterator cbeg; + std::list< int >::const_iterator cend; + + i = 2; + while( obeg != oend ) + { + cp = *obeg; + + if( cp->size() < 3 ) + { + ++obeg; + ++curContour; + continue; + } + + cbeg = cp->begin(); + cend = cp->end(); + lastPoint = *(cbeg++); + + while( cbeg != cend ) + { + curPoint = *(cbeg++); + + if( !holes_only ) + { + aIndexList.push_back( curPoint ); + aIndexList.push_back( lastPoint ); + aIndexList.push_back( (int)( curPoint + vsize ) ); + + aIndexList.push_back( (int)( curPoint + vsize ) ); + aIndexList.push_back( lastPoint ); + aIndexList.push_back( (int)( lastPoint + vsize ) ); + } + else + { + aIndexList.push_back( curPoint ); + aIndexList.push_back( (int)( curPoint + vsize ) ); + aIndexList.push_back( lastPoint ); + + aIndexList.push_back( (int)( curPoint + vsize ) ); + aIndexList.push_back( (int)( lastPoint + vsize ) ); + aIndexList.push_back( lastPoint ); + } + + lastPoint = curPoint; + } + + // check if the loop needs to be closed + cbeg = cp->begin(); + cend = --cp->end(); + + curPoint = *(cbeg); + lastPoint = *(cend); + + if( !holes_only ) + { + aIndexList.push_back( curPoint ); + aIndexList.push_back( lastPoint ); + aIndexList.push_back( (int)( curPoint + vsize ) ); + + aIndexList.push_back( (int)( curPoint + vsize ) ); + aIndexList.push_back( lastPoint ); + aIndexList.push_back( (int)( lastPoint + vsize ) ); + } + else + { + aIndexList.push_back( curPoint ); + aIndexList.push_back( (int)( curPoint + vsize ) ); + aIndexList.push_back( lastPoint ); + + aIndexList.push_back( (int)( curPoint + vsize ) ); + aIndexList.push_back( (int)( lastPoint + vsize ) ); + aIndexList.push_back( lastPoint ); + } + + ++obeg; + ++curContour; + } + + return true; +} diff --git a/utils/idftools/vrml_layer.h b/utils/idftools/vrml_layer.h index 92b5891b39..17a7d7d9fe 100644 --- a/utils/idftools/vrml_layer.h +++ b/utils/idftools/vrml_layer.h @@ -456,6 +456,20 @@ public: const std::string& GetError( void ); void SetVertexOffsets( double aXoffset, double aYoffset ); + + /** + * Function Get3DTriangles + * Allocates and populates the 3D vertex and index lists with + * triangular vertices which may be used for rendering. + * + * @param aVertexList will store the vertices + * @param aIndexList will store the indices + * @param aTopZ is the top plane of the model + * @param aBotZ is the bottom plane of the model + */ + bool Get3DTriangles( std::vector< double >& aVertexList, + std::vector< int > &aIndexList, double aTopZ, double aBotZ ); + }; #endif // VRML_LAYER_H