From d40ea8adcb4004197bdf2a0e4c3a8b2f2e48d74f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Apr 2015 09:43:27 +0200 Subject: [PATCH] 3D viewer: fix issues with transparencies in some models (material issues in VRML2 parser) Fix some issues in filling zones normals. Fix an issue with some models that have materials but didn't defined the diffuse color. Workaround for Bug #1443431. Implement some missing "code logic" for pervertexperface normals. Remove some not used functions. Calculate normals using double type. --- 3d-viewer/3d_canvas.cpp | 6 +- 3d-viewer/3d_class.cpp | 2 +- 3d-viewer/3d_draw.cpp | 47 +- 3d-viewer/3d_draw_basic_functions.cpp | 67 +- 3d-viewer/3d_draw_basic_functions.h | 8 +- 3d-viewer/3d_material.cpp | 19 +- 3d-viewer/3d_material.h | 1 + 3d-viewer/3d_mesh_model.cpp | 601 +++++++++++++----- 3d-viewer/3d_mesh_model.h | 3 +- 3d-viewer/modelparsers.h | 7 - 3d-viewer/vrml_v1_modelparser.cpp | 6 +- 3d-viewer/vrml_v2_modelparser.cpp | 90 ++- 3d-viewer/x3dmodelparser.cpp | 57 +- ...board_items_to_polygon_shape_transform.cpp | 1 - 14 files changed, 610 insertions(+), 305 deletions(-) diff --git a/3d-viewer/3d_canvas.cpp b/3d-viewer/3d_canvas.cpp index 6f3d57796b..cf1e667ee1 100644 --- a/3d-viewer/3d_canvas.cpp +++ b/3d-viewer/3d_canvas.cpp @@ -95,7 +95,7 @@ EDA_3D_CANVAS::EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList ) : m_ZBottom = 0.0; m_ZTop = 0.0; - m_lightPos = S3D_VERTEX(0.0f, 0.0f, 50.0f); + m_lightPos = S3D_VERTEX(0.0f, 0.0f, 30.0f); // Clear all gl list identifiers: for( int ii = GL_ID_BEGIN; ii < GL_ID_END; ii++ ) @@ -591,7 +591,7 @@ void EDA_3D_CANVAS::SetLights() light_color[3] = 1.0; // Light above the xy plane - light_color[0] = light_color[1] = light_color[2] = 0.2; + light_color[0] = light_color[1] = light_color[2] = 0.0; glLightfv( GL_LIGHT0, GL_AMBIENT, light_color ); light_color[0] = light_color[1] = light_color[2] = 1.0; @@ -605,6 +605,8 @@ void EDA_3D_CANVAS::SetLights() light_color[0] = light_color[1] = light_color[2] = 0.2; glLightModelfv( GL_LIGHT_MODEL_AMBIENT, light_color ); + glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE ); + glEnable( GL_LIGHT0 ); // White spot on Z axis ( top ) glEnable( GL_LIGHTING ); } diff --git a/3d-viewer/3d_class.cpp b/3d-viewer/3d_class.cpp index 159a74bb69..b0b29399ae 100644 --- a/3d-viewer/3d_class.cpp +++ b/3d-viewer/3d_class.cpp @@ -85,7 +85,7 @@ S3D_MASTER:: ~S3D_MASTER() { nextmat = m_Materials->Next(); delete m_Materials; - m_Materials = 0; + m_Materials = NULL; } } diff --git a/3d-viewer/3d_draw.cpp b/3d-viewer/3d_draw.cpp index e5d322f4b8..51e63a4a8a 100644 --- a/3d-viewer/3d_draw.cpp +++ b/3d-viewer/3d_draw.cpp @@ -446,6 +446,8 @@ void EDA_3D_CANVAS::Redraw() glEnable( GL_COLOR_MATERIAL ); SetOpenGlDefaultMaterial(); + //glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, FALSE ); + // Board Body GLint shininess_value = 32; @@ -497,6 +499,7 @@ void EDA_3D_CANVAS::Redraw() glCallList( m_glLists[GL_ID_AUX_LAYERS] ); } + //glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, TRUE ); // Draw Component Shadow @@ -583,6 +586,7 @@ void EDA_3D_CANVAS::Redraw() // non transparent objects if( isEnabled( FL_MODULE ) && m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] ) { + glEnable( GL_COLOR_MATERIAL ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glCallList( m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] ); @@ -925,6 +929,14 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, int thickness = GetPrm3DVisu().GetLayerObjectThicknessBIU( layer ); int zpos = GetPrm3DVisu().GetLayerZcoordBIU( layer ); + + float zNormal = 1.0f; // When using thickness it will draw first the top and then botton (with z inverted) + + // If we are not using thickness, then the znormal must face the layer direction + // because it will draw just one plane + if( !thickness ) + zNormal = Get3DLayer_Z_Orientation( layer ); + if( realistic_mode ) { @@ -941,17 +953,17 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, // If holes are removed from copper zones, bufferPolys contains all polygons // to draw (tracks+zones+texts). - glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) ); Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos, thickness, - GetPrm3DVisu().m_BiuTo3Dunits, useTextures ); + GetPrm3DVisu().m_BiuTo3Dunits, useTextures, + zNormal ); // If holes are not removed from copper zones (for calculation time reasons, // the zone polygons are stored in bufferZonesPolys and have to be drawn now: if( bufferZonesPolys.GetCornersCount() ) { - glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) ); Draw3D_SolidHorizontalPolyPolygons( bufferZonesPolys, zpos, thickness, - GetPrm3DVisu().m_BiuTo3Dunits, useTextures ); + GetPrm3DVisu().m_BiuTo3Dunits, useTextures, + zNormal ); } throughHolesListBuilt = true; @@ -1016,7 +1028,6 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, zpos += (copper_thickness + epsilon) / 2.0f; board_thickness -= copper_thickness + epsilon; - glNormal3f( 0.0f, 0.0f, Get3DLayer_Z_Orientation( F_Cu ) ); KI_POLYGON_SET currLayerPolyset; KI_POLYGON_SET polysetHoles; @@ -1035,7 +1046,8 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, if( bufferPcbOutlines.GetCornersCount() ) { Draw3D_SolidHorizontalPolyPolygons( bufferPcbOutlines, zpos + board_thickness / 2.0, - board_thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures ); + board_thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures, + 1.0f ); } glEndList(); @@ -1256,10 +1268,18 @@ void EDA_3D_CANVAS::buildTechLayers3DView( REPORTER* aErrorMessages, REPORTER* a bufferPolys.RemoveAllContours(); bufferPolys.ImportFrom( currLayerPolyset ); + float zNormal = 1.0f; // When using thickness it will draw first the top and then botton (with z inverted) + + // If we are not using thickness, then the znormal must face the layer direction + // because it will draw just one plane + if( !thickness ) + zNormal = Get3DLayer_Z_Orientation( layer ); + + setGLTechLayersColor( layer ); - glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) ); Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos, - thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures ); + thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures, + zNormal ); } } @@ -1361,10 +1381,17 @@ void EDA_3D_CANVAS::buildBoard3DAuxLayers( REPORTER* aErrorMessages, REPORTER* a bufferPolys.RemoveAllContours(); bufferPolys.ImportFrom( currLayerPolyset ); + float zNormal = 1.0f; // When using thickness it will draw first the top and then botton (with z inverted) + + // If we are not using thickness, then the znormal must face the layer direction + // because it will draw just one plane + if( !thickness ) + zNormal = Get3DLayer_Z_Orientation( layer ); + setGLTechLayersColor( layer ); - glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) ); Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos, - thickness, GetPrm3DVisu().m_BiuTo3Dunits, false ); + thickness, GetPrm3DVisu().m_BiuTo3Dunits, false, + zNormal ); } } diff --git a/3d-viewer/3d_draw_basic_functions.cpp b/3d-viewer/3d_draw_basic_functions.cpp index d396bba20b..f17bfa2a83 100644 --- a/3d-viewer/3d_draw_basic_functions.cpp +++ b/3d-viewer/3d_draw_basic_functions.cpp @@ -54,17 +54,6 @@ static void CALLBACK tessEndCB(); static void CALLBACK tessErrorCB( GLenum errorCode ); static void CALLBACK tessCPolyPt2Vertex( const GLvoid* data ); -// 2 helper functions to set the current normal vector for gle items -static inline void SetNormalZpos() -{ - glNormal3f( 0.0, 0.0, 1.0 ); -} - -static inline void SetNormalZneg() -{ - glNormal3f( 0.0, 0.0, -1.0 ); -} - void TransfertToGLlist( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUnits ); /* Draw3D_VerticalPolygonalCylinder is a helper function. @@ -160,7 +149,8 @@ void SetGLTexture( GLuint text_id, float scale ) */ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList, int aZpos, int aThickness, double aBiuTo3DUnits, - bool aUseTextures ) + bool aUseTextures, + float aNormal_Z_Orientation ) { // for Tess callback functions: s_biuTo3Dunits = aBiuTo3DUnits; @@ -173,16 +163,17 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList, gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )tessErrorCB ); gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )tessCPolyPt2Vertex ); - GLdouble v_data[3]; - double zpos = ( aZpos + (aThickness / 2.0) ) * aBiuTo3DUnits; + GLdouble v_data[3]; + double zpos = ( aZpos + (aThickness / 2.0) ) * aBiuTo3DUnits; s_currentZpos = zpos; // for Tess callback functions - v_data[2] = aZpos + (aThickness / 2.0); + v_data[2] = zpos; // Set normal toward positive Z axis, for a solid object on the top side - if( aThickness ) - SetNormalZpos(); - // gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); + //gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE ); + //gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD ); + + glNormal3f( 0.0, 0.0, aNormal_Z_Orientation ); // Draw solid areas contained in this list CPOLYGONS_LIST polylist = aPolysList; // temporary copy for gluTessVertex @@ -202,11 +193,6 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList, startContour = 0; } - // https://www.opengl.org/sdk/docs/man2/xhtml/gluTessNormal.xml - if( !aThickness ) - gluTessNormal( tess, 0.0, 0.0, 0.0 ); - - v_data[0] = polylist.GetX( ii ) * aBiuTo3DUnits; v_data[1] = -polylist.GetY( ii ) * aBiuTo3DUnits; // gluTessVertex store pointers on data, not data, so do not store @@ -231,9 +217,8 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList, zpos = ( aZpos - (aThickness / 2.0) ) * aBiuTo3DUnits; s_currentZpos = zpos; // for Tess callback functions v_data[2] = zpos; - // Set normal toward negative Z axis, for a solid object on bottom side - if( aThickness ) - SetNormalZneg(); + + glNormal3f( 0.0, 0.0, -aNormal_Z_Orientation ); } if( startContour == 0 ) @@ -259,12 +244,14 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList, */ void Draw3D_SolidHorizontalPolygonWithHoles( const CPOLYGONS_LIST& aPolysList, int aZpos, int aThickness, - double aBiuTo3DUnits, bool aUseTextures ) + double aBiuTo3DUnits, bool aUseTextures, + float aNormal_Z_Orientation ) { CPOLYGONS_LIST polygon; ConvertPolysListWithHolesToOnePolygon( aPolysList, polygon ); - Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, aThickness, aBiuTo3DUnits, aUseTextures ); + Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, aThickness, aBiuTo3DUnits, aUseTextures, + aNormal_Z_Orientation ); } @@ -307,23 +294,21 @@ void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius, if( aThickness ) { // draw top (front) and bottom (back) horizontal sides (rings) - SetNormalZpos(); outer_cornerBuffer.Append( inner_cornerBuffer ); CPOLYGONS_LIST polygon; ConvertPolysListWithHolesToOnePolygon( outer_cornerBuffer, polygon ); // draw top (front) horizontal ring - Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits, false ); + Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits, false, + 1.0f ); if( aHeight ) { // draw bottom (back) horizontal ring - SetNormalZneg(); - Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits, false ); + Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits, false, + -1.0f ); } } - - SetNormalZpos(); } @@ -372,18 +357,16 @@ void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos, ConvertPolysListWithHolesToOnePolygon( outer_cornerBuffer, polygon ); // draw top (front) horizontal side (ring) - SetNormalZpos(); - Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits, false ); + Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits, false, + 1.0f ); if( aHeight ) { // draw bottom (back) horizontal side (ring) - SetNormalZneg(); - Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits, false ); + Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits, false, + -1.0f ); } } - - SetNormalZpos(); } @@ -401,7 +384,7 @@ void Draw3D_SolidSegment( const wxPoint& aStart, const wxPoint& aEnd, TransformRoundedEndsSegmentToPolygon( cornerBuffer, aStart, aEnd, slice, aWidth ); - Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false ); + Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false, 1.0f ); } @@ -415,7 +398,7 @@ void Draw3D_ArcSegment( const wxPoint& aCenterPos, const wxPoint& aStartPoint, TransformArcToPolygon( cornerBuffer, aCenterPos, aStartPoint, aArcAngle, slice, aWidth ); - Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false ); + Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false, 1.0f ); } diff --git a/3d-viewer/3d_draw_basic_functions.h b/3d-viewer/3d_draw_basic_functions.h index 0743b91612..1a90c4d6b5 100644 --- a/3d-viewer/3d_draw_basic_functions.h +++ b/3d-viewer/3d_draw_basic_functions.h @@ -37,6 +37,7 @@ * @param aThickness = thickness in board internal units * @param aBiuTo3DUnits = board internal units to 3D units scaling value * @param aUseTextures = true to use textxures for the polygons + * @param aNormal_Z_Orientation = the normal Z orientation to apply * If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos. * If aThickness > 0, a solid object is drawn. * The top side is located at aZpos + aThickness / 2 @@ -44,7 +45,8 @@ */ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList, int aZpos, int aThickness, double aBiuTo3DUnits, - bool aUseTextures ); + bool aUseTextures, + float aNormal_Z_Orientation ); /** draw the solid polygon found in aPolysList * The first polygonj is the main polygon, others are holes @@ -53,6 +55,7 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList, * @param aThickness = thickness in board internal units * @param aBiuTo3DUnits = board internal units to 3D units scaling value * @param aUseTextures = true to use textxures for the polygons + * @param aNormal_Z_Orientation = the normal Z orientation to apply * If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos. * If aThickness > 0, a solid object is drawn. * The top side is located at aZpos + aThickness / 2 @@ -60,7 +63,8 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList, */ void Draw3D_SolidHorizontalPolygonWithHoles( const CPOLYGONS_LIST& aPolysList, int aZpos, int aThickness, double aBiuTo3DUnits, - bool aUseTextures ); + bool aUseTextures, + float aNormal_Z_Orientation ); /** draw a thick segment using 3D primitives, in a XY plane * @param aStart = YX position of start point in board units diff --git a/3d-viewer/3d_material.cpp b/3d-viewer/3d_material.cpp index e2c1b58d09..0ea341cf5a 100644 --- a/3d-viewer/3d_material.cpp +++ b/3d-viewer/3d_material.cpp @@ -50,6 +50,7 @@ S3D_MATERIAL::S3D_MATERIAL( S3D_MASTER* father, const wxString& name ) : m_SpecularColor.clear(); m_Shininess.clear(); m_Transparency.clear(); + m_ColorPerVertex = false; } @@ -81,17 +82,29 @@ bool S3D_MATERIAL::SetOpenGLMaterial( unsigned int aMaterialIndex, bool aUseMate { transparency_value = m_Transparency[aMaterialIndex]; } + else + { + if( m_Transparency.size() > 0 ) + transparency_value = m_Transparency[0]; + } if( m_DiffuseColor.size() > aMaterialIndex ) { glm::vec3 color = m_DiffuseColor[aMaterialIndex]; - glColor4f( color.x, color.y, color.z, 1.0 - transparency_value ); + glColor4f( color.x, color.y, color.z, 1.0f - transparency_value ); + } + else + { + if( m_DiffuseColor.size() == 0 ) + { + glColor4f( 0.8f, 0.8f, 0.8f, 1.0f ); + } } - if( m_Shininess.size() > aMaterialIndex ) + if( m_Shininess.size() > 0 ) { - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, m_Shininess[aMaterialIndex] ); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, m_Shininess[0] ); } // emissive diff --git a/3d-viewer/3d_material.h b/3d-viewer/3d_material.h index 251db38479..bee9e85253 100644 --- a/3d-viewer/3d_material.h +++ b/3d-viewer/3d_material.h @@ -48,6 +48,7 @@ public: std::vector< glm::vec3 > m_SpecularColor; std::vector< float > m_Shininess; std::vector< float > m_Transparency; + bool m_ColorPerVertex; public: S3D_MATERIAL( S3D_MASTER* father, const wxString& name ); diff --git a/3d-viewer/3d_mesh_model.cpp b/3d-viewer/3d_mesh_model.cpp index 8bd02fe26f..04077f5727 100644 --- a/3d-viewer/3d_mesh_model.cpp +++ b/3d-viewer/3d_mesh_model.cpp @@ -116,24 +116,9 @@ void S3D_MESH::calcBBox( ) bool firstBBox = true; - bool useMaterial = g_Parm_3D_Visu.GetFlag( FL_RENDER_MATERIAL ); - - // Do not add complete transparent materials - if( useMaterial && (m_Materials != 0) && ( m_MaterialIndex.size() == 0 ) ) - if( m_Materials->m_Transparency.size() > 0 ) - if( m_Materials->m_Transparency[0] >= 1.0f ) - return; - - // Calc boudingbox for all coords for( unsigned int idx = 0; idx < m_CoordIndex.size(); idx++ ) { - // Do not add complete transparent materials - if( useMaterial && (m_Materials != 0) && ( m_MaterialIndex.size() > idx ) ) - if( (int)m_Materials->m_Transparency.size() > m_MaterialIndex[idx] ) - if( m_Materials->m_Transparency[m_MaterialIndex[idx]] >= 1.0f ) - continue; - for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) if( firstBBox ) { @@ -194,21 +179,56 @@ void S3D_MESH::openGL_Render( bool aIsRenderingJustNonTransparentObjects, { return; } +/* + // DEBUG INFO + printf("aIsRenderingJustNonTransparentObjects %d aIsRenderingJustTransparentObjects %d\n", aIsRenderingJustNonTransparentObjects, aIsRenderingJustTransparentObjects); - if( m_Materials && ( m_MaterialIndex.size() == 0 ) ) + printf("m_CoordIndex.size() %lu\n", m_CoordIndex.size() ); + printf("m_MaterialIndexPerFace.size() %lu\n", m_MaterialIndexPerFace.size() ); + printf("m_MaterialIndexPerVertex.size() %lu\n", m_MaterialIndexPerVertex.size() ); + printf("m_PerVertexNormalsNormalized.size() %lu\n", m_PerVertexNormalsNormalized.size() ); + printf("m_PerFaceVertexNormals.size() %lu\n", m_PerFaceVertexNormals.size() ); + + printf("smoothShapes %d\n", smoothShapes ); + + if( m_Materials ) { - bool isTransparent = m_Materials->SetOpenGLMaterial( 0, useMaterial ); + printf(" m_Name %s\n", static_cast(m_Materials->m_Name.c_str()) ); + printf(" m_ColorPerVertex %d\n", m_Materials->m_ColorPerVertex ); + printf(" m_Transparency.size() %lu\n", m_Materials->m_Transparency.size() ); + printf(" m_DiffuseColor.size() %lu\n", m_Materials->m_DiffuseColor.size() ); + printf(" m_Shininess.size() %lu\n", m_Materials->m_Shininess.size() ); + printf(" m_EmissiveColor.size() %lu\n", m_Materials->m_EmissiveColor.size() ); + printf(" m_SpecularColor.size() %lu\n", m_Materials->m_SpecularColor.size() ); + printf(" m_AmbientColor.size() %lu\n", m_Materials->m_AmbientColor.size() ); + } + printf("m_Materials %p\n", ( void * )m_Materials ); +*/ - if( isTransparent && aIsRenderingJustNonTransparentObjects ) - return; + float lastTransparency_value = 0.0f; - if( !isTransparent && aIsRenderingJustTransparentObjects ) - return; + if( m_Materials ) + { + if ( m_Materials->m_ColorPerVertex == false ) + { + bool isTransparent = m_Materials->SetOpenGLMaterial( 0, useMaterial ); - if( useMaterial ) - if( m_Materials->m_Transparency.size() > 0 ) - if( m_Materials->m_Transparency[0] >= 1.0f ) - return; + if( isTransparent && aIsRenderingJustNonTransparentObjects ) + return; + + if( !isTransparent && aIsRenderingJustTransparentObjects ) + return; + + // Skip total transparent models + if( useMaterial ) + if( m_Materials->m_Transparency.size() > 0 ) + { + lastTransparency_value = m_Materials->m_Transparency[0]; + + if( lastTransparency_value >= 1.0f ) + return; + } + } } glPushMatrix(); @@ -228,59 +248,145 @@ void S3D_MESH::openGL_Render( bool aIsRenderingJustNonTransparentObjects, calcPerPointNormals(); } +/* +#if defined(DEBUG) + // Debug Normals + glColor4f( 1.0, 0.0, 1.0, 0.7 ); + for( unsigned int idx = 0; idx < m_CoordIndex.size(); idx++ ) + { + if( m_PerFaceNormalsNormalized.size() > 0 ) + { + S3D_VERTEX normal = m_PerFaceNormalsNormalized[idx]; + //glNormal3fv( &normal.x ); + + glm::vec3 point = m_Point[m_CoordIndex[idx][0]]; + for( unsigned int ii = 1; ii < m_CoordIndex[idx].size(); ii++ ) + { + point += m_Point[m_CoordIndex[idx][ii]]; + } + + point /= m_CoordIndex[idx].size(); + + glBegin( GL_LINES ); + glVertex3fv( &point.x ); + point += normal * 0.01f; + glVertex3fv( &point.x ); + glEnd(); + } + } + + // Restore material + if( m_Materials ) + m_Materials->SetOpenGLMaterial( 0, useMaterial ); +#endif +*/ + +/* +#if defined(DEBUG) + if( smoothShapes ) + { + // Debug Per Vertex Normals + glColor4f( 0.0, 1.0, 1.0, 0.7 ); + for( unsigned int idx = 0; idx < m_CoordIndex.size(); idx++ ) + { + if( (m_PerVertexNormalsNormalized.size() > 0) && + g_Parm_3D_Visu.GetFlag( FL_RENDER_USE_MODEL_NORMALS ) ) + { + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + glm::vec3 normal = m_PerVertexNormalsNormalized[m_NormalIndex[idx][ii]]; + //glNormal3fv( &normal.x ); + + glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; + glBegin( GL_LINES ); + glVertex3fv( &point.x ); + point += normal * 1.00f; + glVertex3fv( &point.x ); + glEnd(); + } + } + else + { + std::vector< glm::vec3 > normals_list; + normals_list = m_PerFaceVertexNormals[idx]; + + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + glm::vec3 normal = normals_list[ii]; + printf("normal(%f, %f, %f), ", normal.x, normal.y, normal.z ); + + //glNormal3fv( &normal.x ); + + glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; + glBegin( GL_LINES ); + glVertex3fv( &point.x ); + point += normal * 1.00f; + glVertex3fv( &point.x ); + glEnd(); + } + printf("\n"); + } + } + + // Restore material + if( m_Materials ) + m_Materials->SetOpenGLMaterial( 0, useMaterial ); + } +#endif +*/ for( unsigned int idx = 0; idx < m_CoordIndex.size(); idx++ ) { - if( m_Materials && ( m_MaterialIndex.size() != 0 ) ) + if( m_Materials ) { - if ( m_MaterialIndex.size() > idx ) + // http://accad.osu.edu/~pgerstma/class/vnv/resources/info/AnnotatedVrmlRef/ch3-323.htm + // "If colorPerVertex is FALSE, colours are applied to each face, as follows:" + if( ( m_Materials->m_ColorPerVertex == false ) && + ( m_Materials->m_DiffuseColor.size() > 1 ) ) { - bool isTransparent = m_Materials->SetOpenGLMaterial( m_MaterialIndex[idx], useMaterial ); + bool isTransparent; + // "If the colorIndex field is not empty, then one colour is + // used for each face of the IndexedFaceSet. There must be + // at least as many indices in the colorIndex field as + // there are faces in the IndexedFaceSet." + if ( m_MaterialIndexPerFace.size() == m_CoordIndex.size() ) + { + isTransparent = m_Materials->SetOpenGLMaterial( m_MaterialIndexPerFace[idx], useMaterial ); + + // Skip total transparent faces + if( useMaterial ) + if( (int)m_Materials->m_Transparency.size() > m_MaterialIndexPerFace[idx] ) + { + if( m_Materials->m_Transparency[m_MaterialIndexPerFace[idx]] >= 1.0f ) + continue; + } + } + else + { + // "If the colorIndex field is empty, then the colours in the + // Color node are applied to each face of the IndexedFaceSet + // in order. There must be at least as many colours in the + // Color node as there are faces." + isTransparent = m_Materials->SetOpenGLMaterial( idx, useMaterial ); + + // Skip total transparent faces + if( useMaterial ) + if( m_Materials->m_Transparency.size() > idx ) + { + if( m_Materials->m_Transparency[idx] >= 1.0f ) + continue; + } + } + if( isTransparent && aIsRenderingJustNonTransparentObjects ) continue; if( !isTransparent && aIsRenderingJustTransparentObjects ) continue; - - if( useMaterial ) - if( (int)m_Materials->m_Transparency.size() > m_MaterialIndex[idx] ) - if( m_Materials->m_Transparency[m_MaterialIndex[idx]] >= 1.0f ) - continue; - } - else - { - // This is only need on debug, because above we are marking the bad elements - DBG( m_Materials->SetOpenGLMaterial( 0, useMaterial ) ); } } -/* -#if defined(DEBUG) - // Debug Normals - glColor4f( 1.0, 0.0, 1.0, 1.0 ); - for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) - { - // Flat - if( m_PerFaceNormalsNormalized.size() > 0 ) - { - S3D_VERTEX normal = m_PerFaceNormalsNormalized[idx]; - glNormal3fv( &normal.x ); - - for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) - { - glBegin( GL_LINES ); - glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; - glVertex3fv( &point.x ); - point += normal; - glVertex3fv( &point.x ); - glEnd(); - } - } - } -#endif -*/ - switch( m_CoordIndex[idx].size() ) { case 3: @@ -297,48 +403,159 @@ void S3D_MESH::openGL_Render( bool aIsRenderingJustNonTransparentObjects, if( smoothShapes ) { - if( (m_PerVertexNormalsNormalized.size() > 0) && - g_Parm_3D_Visu.GetFlag( FL_RENDER_USE_MODEL_NORMALS ) ) + if( m_Materials ) { - for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + // for VRML2: + // http://accad.osu.edu/~pgerstma/class/vnv/resources/info/AnnotatedVrmlRef/ch3-323.htm + // "If colorPerVertex is TRUE, colours are applied to each vertex, as follows: + if( ( m_Materials->m_ColorPerVertex == true ) && + ( m_Materials->m_DiffuseColor.size() > 1 ) ) { - glm::vec3 normal = m_PerVertexNormalsNormalized[m_NormalIndex[idx][ii]]; - glNormal3fv( &normal.x ); -/* -#if defined(DEBUG) - // Flag error vertices - if ((normal.x == 0.0) && (normal.y == 0.0) && (normal.z == 0.0)) + // "If the colorIndex field is not empty, then colours + // are applied to each vertex of the IndexedFaceSet in + // exactly the same manner that the coordIndex field is + // used to choose coordinates for each vertex from the + // Coordinate node. The colorIndex field must contain at + // least as many indices as the coordIndex field, and + // must contain end-of-face markers (-1) in exactly the + // same places as the coordIndex field. If the greatest + // index in the colorIndex field is N, then there must + // be N+1 colours in the Color node." + if ( m_MaterialIndexPerVertex.size() != 0 ) { - glColor4f( 1.0, 0.0, 1.0, 1.0 ); + if( (m_PerVertexNormalsNormalized.size() > 0) && + g_Parm_3D_Visu.GetFlag( FL_RENDER_USE_MODEL_NORMALS ) ) + { + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + S3D_VERTEX color = m_Materials->m_DiffuseColor[m_MaterialIndexPerVertex[idx][ii]]; + glColor4f( color.x, color.y, color.z, 1.0f - lastTransparency_value ); + + glm::vec3 normal = m_PerVertexNormalsNormalized[m_NormalIndex[idx][ii]]; + glNormal3fv( &normal.x ); + + glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; + glVertex3fv( &point.x ); + } + } + else + { + std::vector< glm::vec3 > normals_list; + normals_list = m_PerFaceVertexNormals[idx]; + + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + S3D_VERTEX color = m_Materials->m_DiffuseColor[m_MaterialIndexPerVertex[idx][ii]]; + glColor4f( color.x, color.y, color.z, 1.0f - lastTransparency_value ); + + glm::vec3 normal = normals_list[ii]; + glNormal3fv( &normal.x ); + + glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; + glVertex3fv( &point.x ); + } + } + } + else + { + // "If the colorIndex field is empty, then the + // coordIndex field is used to choose colours from + // the Color node. If the greatest index in the + // coordIndex field is N, then there must be N+1 + // colours in the Color node." + + + if( (m_PerVertexNormalsNormalized.size() > 0) && + g_Parm_3D_Visu.GetFlag( FL_RENDER_USE_MODEL_NORMALS ) ) + { + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + S3D_VERTEX color = m_Materials->m_DiffuseColor[m_CoordIndex[idx][ii]]; + glColor4f( color.x, color.y, color.z, 1.0f - lastTransparency_value ); + + glm::vec3 normal = m_PerVertexNormalsNormalized[m_NormalIndex[idx][ii]]; + glNormal3fv( &normal.x ); + + glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; + glVertex3fv( &point.x ); + } + } + else + { + std::vector< glm::vec3 > normals_list; + normals_list = m_PerFaceVertexNormals[idx]; + + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + S3D_VERTEX color = m_Materials->m_DiffuseColor[m_CoordIndex[idx][ii]]; + glColor4f( color.x, color.y, color.z, 1.0f - lastTransparency_value ); + + glm::vec3 normal = normals_list[ii]; + glNormal3fv( &normal.x ); + + glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; + glVertex3fv( &point.x ); + } + } + } + } + else + { + if( (m_PerVertexNormalsNormalized.size() > 0) && + g_Parm_3D_Visu.GetFlag( FL_RENDER_USE_MODEL_NORMALS ) ) + { + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + glm::vec3 normal = m_PerVertexNormalsNormalized[m_NormalIndex[idx][ii]]; + glNormal3fv( &normal.x ); + + glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; + glVertex3fv( &point.x ); + } + } + else + { + std::vector< glm::vec3 > normals_list; + normals_list = m_PerFaceVertexNormals[idx]; + + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + glm::vec3 normal = normals_list[ii]; + glNormal3fv( &normal.x ); + + glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; + glVertex3fv( &point.x ); + } } -#endif -*/ - glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; - glVertex3fv( &point.x ); } } else { - std::vector< glm::vec3 > normals_list; - normals_list = m_PerFaceVertexNormals[idx]; - - for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + if( (m_PerVertexNormalsNormalized.size() > 0) && + g_Parm_3D_Visu.GetFlag( FL_RENDER_USE_MODEL_NORMALS ) ) { - glm::vec3 normal = normals_list[ii]; - glNormal3fv( &normal.x ); - -/* -#if defined(DEBUG) - // Flag error vertices - if ((normal.x == 0.0) && (normal.y == 0.0) && (normal.z == 0.0)) + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) { - glColor4f( 1.0, 0.0, 1.0, 1.0 ); - } -#endif -*/ + glm::vec3 normal = m_PerVertexNormalsNormalized[m_NormalIndex[idx][ii]]; + glNormal3fv( &normal.x ); - glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; - glVertex3fv( &point.x ); + glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; + glVertex3fv( &point.x ); + } + } + else + { + std::vector< glm::vec3 > normals_list; + normals_list = m_PerFaceVertexNormals[idx]; + + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + glm::vec3 normal = normals_list[ii]; + glNormal3fv( &normal.x ); + + glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; + glVertex3fv( &point.x ); + } } } } @@ -348,29 +565,78 @@ void S3D_MESH::openGL_Render( bool aIsRenderingJustNonTransparentObjects, if( m_PerFaceNormalsNormalized.size() > 0 ) { S3D_VERTEX normal = m_PerFaceNormalsNormalized[idx]; -/* -#if defined(DEBUG) - // Flag error vertices - if( (normal.x == 0.0) && (normal.y == 0.0) && (normal.z == 0.0) ) - { - DBG( printf("%u\n", idx) ); - glColor4f( 1.0, 0.0, 1.0, 1.0 ); - } -#endif -*/ glNormal3fv( &normal.x ); - for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + if( m_Materials ) { - glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; - glVertex3fv( &point.x ); + // for VRML2: + // http://accad.osu.edu/~pgerstma/class/vnv/resources/info/AnnotatedVrmlRef/ch3-323.htm + // "If colorPerVertex is TRUE, colours are applied to each vertex, as follows: + if( ( m_Materials->m_ColorPerVertex == true ) && + ( m_Materials->m_DiffuseColor.size() > 1 ) ) + { + // "If the colorIndex field is not empty, then colours + // are applied to each vertex of the IndexedFaceSet in + // exactly the same manner that the coordIndex field is + // used to choose coordinates for each vertex from the + // Coordinate node. The colorIndex field must contain at + // least as many indices as the coordIndex field, and + // must contain end-of-face markers (-1) in exactly the + // same places as the coordIndex field. If the greatest + // index in the colorIndex field is N, then there must + // be N+1 colours in the Color node." + if ( m_MaterialIndexPerVertex.size() != 0 ) + { + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + S3D_VERTEX color = m_Materials->m_DiffuseColor[m_MaterialIndexPerVertex[idx][ii]]; + glColor4f( color.x, color.y, color.z, 1.0f - lastTransparency_value ); + + S3D_VERTEX point = m_Point[m_CoordIndex[idx][ii]]; + glVertex3fv( &point.x ); + } + } + else + { + // "If the colorIndex field is empty, then the + // coordIndex field is used to choose colours from + // the Color node. If the greatest index in the + // coordIndex field is N, then there must be N+1 + // colours in the Color node." + + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + S3D_VERTEX color = m_Materials->m_DiffuseColor[m_CoordIndex[idx][ii]]; + glColor4f( color.x, color.y, color.z, 1.0f - lastTransparency_value ); + + S3D_VERTEX point = m_Point[m_CoordIndex[idx][ii]]; + glVertex3fv( &point.x ); + } + } + } + else + { + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + S3D_VERTEX point = m_Point[m_CoordIndex[idx][ii]]; + glVertex3fv( &point.x ); + } + } + } + else + { + for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) + { + S3D_VERTEX point = m_Point[m_CoordIndex[idx][ii]]; + glVertex3fv( &point.x ); + } } } else { for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) { - glm::vec3 point = m_Point[m_CoordIndex[idx][ii]]; + S3D_VERTEX point = m_Point[m_CoordIndex[idx][ii]]; glVertex3fv( &point.x ); } } @@ -474,27 +740,13 @@ void S3D_MESH::calcPointNormalized() biggerPoint = v; } - biggerPoint = 1.0 / biggerPoint; - for( unsigned int i = 0; i < m_Point.size(); i++ ) { - m_PointNormalized[i] = m_Point[i] * biggerPoint; + m_PointNormalized[i] = m_Point[i] / biggerPoint; } } -bool IsClockwise( glm::vec3 v0, glm::vec3 v1, glm::vec3 v2 ) -{ - double sum = 0.0; - - sum += (v1.x - v0.x) * (v1.y + v0.y); - sum += (v2.x - v1.x) * (v2.y + v1.y); - sum += (v0.x - v2.x) * (v0.y + v2.y); - - return sum > FLT_EPSILON; -} - - void S3D_MESH::calcPerFaceNormals() { //DBG( printf( "calcPerFaceNormals" ) ); @@ -512,7 +764,8 @@ void S3D_MESH::calcPerFaceNormals() haveAlreadyNormals_from_model_file = true; // !TODO: this is a workarround for some VRML2 modules files (ex: from we-online.de website) - // are using (incorrectly) the normals with m_CoordIndex as per face normal. This maybe be addressed by the parser in the future. + // are using (incorrectly) the normals with m_CoordIndex as per face normal. + // This maybe be addressed by the parser in the future. if( ( m_PerFaceNormalsNormalized.size() == m_Point.size() ) && ( m_PerFaceNormalsNormalized.size() != m_CoordIndex.size() ) ) { @@ -542,11 +795,7 @@ void S3D_MESH::calcPerFaceNormals() for( unsigned int idx = 0; idx < m_CoordIndex.size(); idx++ ) { - glm::vec3 cross_prod; - - cross_prod.x = 0.0f; - cross_prod.y = 0.0f; - cross_prod.z = 0.0f; + glm::dvec3 cross_prod = glm::dvec3( 0.0, 0.0, 0.0 ); // Newell's Method // http://www.opengl.org/wiki/Calculating_a_Surface_Normal @@ -555,40 +804,41 @@ void S3D_MESH::calcPerFaceNormals() for( unsigned int i = 0; i < m_CoordIndex[idx].size(); i++ ) { - glm::vec3 u = m_PointNormalized[m_CoordIndex[idx][i]]; - glm::vec3 v = m_PointNormalized[m_CoordIndex[idx][(i + 1) % m_CoordIndex[idx].size()]]; + + glm::dvec3 u = glm::dvec3( m_PointNormalized[m_CoordIndex[idx][i]] ); + glm::dvec3 v = glm::dvec3( m_PointNormalized[m_CoordIndex[idx][(i + 1) % m_CoordIndex[idx].size()]] ); cross_prod.x += (u.y - v.y) * (u.z + v.z); cross_prod.y += (u.z - v.z) * (u.x + v.x); cross_prod.z += (u.x - v.x) * (u.y + v.y); - - // This method works same way - /* - cross_prod.x += (u.y * v.z) - (u.z * v.y); - cross_prod.y += (u.z * v.x) - (u.x * v.z); - cross_prod.z += (u.x * v.y) - (u.y * v.x);*/ } - float area = glm::dot( cross_prod, cross_prod ); + double area = glm::dot( cross_prod, cross_prod ); + area = fabs( area ); - m_PerFaceNormalsRaw_X_PerFaceSquaredArea[idx] = cross_prod * area; + m_PerFaceNormalsRaw_X_PerFaceSquaredArea[idx] = glm::vec3( cross_prod * area ); + + //printf("cross_prod(%g, %g, %g), area:%g m_PerFaceNormalsRaw_X_PerFaceSquaredArea(%f, %f, %f)\n", cross_prod.x, cross_prod.y, cross_prod.z, area, + //m_PerFaceNormalsRaw_X_PerFaceSquaredArea[idx].x, + //m_PerFaceNormalsRaw_X_PerFaceSquaredArea[idx].y, + //m_PerFaceNormalsRaw_X_PerFaceSquaredArea[idx].z); if( haveAlreadyNormals_from_model_file == false ) { if( g_Parm_3D_Visu.GetFlag( FL_RENDER_USE_MODEL_NORMALS ) && (m_PerVertexNormalsNormalized.size() > 0) ) { - glm::vec3 normalSum; + glm::dvec3 normalSum; for( unsigned int ii = 0; ii < m_CoordIndex[idx].size(); ii++ ) { - normalSum += m_PerVertexNormalsNormalized[m_NormalIndex[idx][ii]]; + normalSum += glm::dvec3( m_PerVertexNormalsNormalized[m_NormalIndex[idx][ii]] ); } - float l = glm::length( normalSum ); + double l = glm::length( normalSum ); - if( l > FLT_EPSILON ) // avoid division by zero + if( l > DBL_EPSILON ) // avoid division by zero { normalSum = normalSum / l; } @@ -596,83 +846,86 @@ void S3D_MESH::calcPerFaceNormals() { if( ( normalSum.x > normalSum.y ) && ( normalSum.x > normalSum.z ) ) { - normalSum.x = 0.0f; - normalSum.y = 1.0f; - normalSum.z = 0.0f; + normalSum.x = 0.0; + normalSum.y = 1.0; + normalSum.z = 0.0; } else if( ( normalSum.y > normalSum.x ) && ( normalSum.y > normalSum.z ) ) { - normalSum.x = 0.0f; - normalSum.y = 1.0f; - normalSum.z = 0.0f; + normalSum.x = 0.0; + normalSum.y = 1.0; + normalSum.z = 0.0; } else if( ( normalSum.z > normalSum.x ) && ( normalSum.z > normalSum.y ) ) { - normalSum.x = 0.0f; - normalSum.y = 0.0f; - normalSum.z = 1.0f; + normalSum.x = 0.0; + normalSum.y = 0.0; + normalSum.z = 1.0; } else { - normalSum.x = 0.0f; - normalSum.y = 0.0f; - normalSum.z = 0.0f; + normalSum.x = 0.0; + normalSum.y = 0.0; + normalSum.z = 0.0; } } - m_PerFaceNormalsNormalized[idx] = normalSum; + m_PerFaceNormalsNormalized[idx] = glm::vec3( normalSum ); } else { // normalize vertex normal - float l = glm::length( cross_prod ); + double l = glm::length( cross_prod ); - if( l > FLT_EPSILON ) // avoid division by zero + if( l > DBL_EPSILON ) // avoid division by zero { cross_prod = cross_prod / l; } else { + /* for( unsigned int i = 0; i < m_CoordIndex[idx].size(); i++ ) { - glm::vec3 v = m_PointNormalized[m_CoordIndex[idx][i]]; + glm::vec3 v = m_Point[m_CoordIndex[idx][i]]; DBG( printf( "v[%u](%f, %f, %f)", i, v.x, v.y, v.z ) ); } - DBG( printf( "Cannot calc normal idx: %u cross(%f, %f, %f) l:%f m_CoordIndex[idx].size: %u\n", + DBG( printf( "Cannot calc normal idx: %u cross(%g, %g, %g) l:%g m_CoordIndex[idx].size: %u\n", idx, cross_prod.x, cross_prod.y, cross_prod.z, l, (unsigned int)m_CoordIndex[idx].size()) ); + */ if( ( cross_prod.x > cross_prod.y ) && ( cross_prod.x > cross_prod.z ) ) { - cross_prod.x = 0.0f; - cross_prod.y = 1.0f; - cross_prod.z = 0.0f; + cross_prod.x = 0.0; + cross_prod.y = 1.0; + cross_prod.z = 0.0; } else if( ( cross_prod.y > cross_prod.x ) && ( cross_prod.y > cross_prod.z ) ) { - cross_prod.x = 0.0f; - cross_prod.y = 1.0f; - cross_prod.z = 0.0f; + cross_prod.x = 0.0; + cross_prod.y = 1.0; + cross_prod.z = 0.0; } else if( ( cross_prod.z > cross_prod.x ) && ( cross_prod.z > cross_prod.y ) ) { - cross_prod.x = 0.0f; - cross_prod.y = 0.0f; - cross_prod.z = 1.0f; + cross_prod.x = 0.0; + cross_prod.y = 0.0; + cross_prod.z = 1.0; } else { - cross_prod.x = 0.0f; - cross_prod.y = 0.0f; - cross_prod.z = 0.0f; + cross_prod.x = 0.0; + cross_prod.y = 0.0; + cross_prod.z = 0.0; } } - m_PerFaceNormalsNormalized[idx] = cross_prod; + m_PerFaceNormalsNormalized[idx] = glm::vec3( cross_prod ); + //printf("normal(%g, %g, %g)\n", m_PerFaceNormalsNormalized[idx].x, m_PerFaceNormalsNormalized[idx].y, m_PerFaceNormalsNormalized[idx].z ); } } } diff --git a/3d-viewer/3d_mesh_model.h b/3d-viewer/3d_mesh_model.h index 7223e17752..85777f02bb 100644 --- a/3d-viewer/3d_mesh_model.h +++ b/3d-viewer/3d_mesh_model.h @@ -66,7 +66,8 @@ public: std::vector< S3D_VERTEX > m_PerFaceColor; std::vector< S3D_VERTEX > m_PerFaceNormalsNormalized; std::vector< S3D_VERTEX > m_PerVertexNormalsNormalized; - std::vector< int > m_MaterialIndex; + std::vector< int > m_MaterialIndexPerFace; + std::vector< std::vector > m_MaterialIndexPerVertex; S3D_MESH_PTRS childs; S3D_VERTEX m_translation; diff --git a/3d-viewer/modelparsers.h b/3d-viewer/modelparsers.h index 8e591882bc..1324924591 100644 --- a/3d-viewer/modelparsers.h +++ b/3d-viewer/modelparsers.h @@ -119,13 +119,6 @@ public: */ static void GetNodeProperties( wxXmlNode* aNode, PROPERTY_MAP& aProps ); - /** - * Return string representing x3d file in vrml2 format - * Function Load must be called before this function, otherwise empty - * data set is returned. - */ - wxString VRML2_representation(); - private: wxString m_Filename; S3D_MESH_PTR m_model; diff --git a/3d-viewer/vrml_v1_modelparser.cpp b/3d-viewer/vrml_v1_modelparser.cpp index 4879691379..4f784afecf 100644 --- a/3d-viewer/vrml_v1_modelparser.cpp +++ b/3d-viewer/vrml_v1_modelparser.cpp @@ -422,16 +422,16 @@ int VRML1_MODEL_PARSER::readIndexedFaceSet_materialIndex() { // DBG( printf( " readIndexedFaceSet_materialIndex\n" ) ); - m_model->m_MaterialIndex.clear(); + m_model->m_MaterialIndexPerFace.clear(); int index; while( fscanf( m_file, "%d,", &index ) ) { - m_model->m_MaterialIndex.push_back( index ); + m_model->m_MaterialIndexPerFace.push_back( index ); } - // DBG( printf( " m_MaterialIndex.size: %ld\n", m_model->m_MaterialIndex.size() ) ); + // DBG( printf( " m_MaterialIndexPerFace.size: %ld\n", m_model->m_MaterialIndexPerFace.size() ) ); return 0; } diff --git a/3d-viewer/vrml_v2_modelparser.cpp b/3d-viewer/vrml_v2_modelparser.cpp index cac3cf7609..cc70d9be94 100644 --- a/3d-viewer/vrml_v2_modelparser.cpp +++ b/3d-viewer/vrml_v2_modelparser.cpp @@ -1103,23 +1103,34 @@ int VRML2_MODEL_PARSER::read_appearance() wxString mat_name; mat_name = FROM_UTF8( text ); - bool found = false; + S3D_MATERIAL* found_material = NULL; for( material = m_Master->m_Materials; material; material = material->Next() ) { if( material->m_Name == mat_name ) { - m_model->m_Materials = material; + found_material = material; // We dont exit here, since it seems that VRML can have // multiple material defined, so, it will copy the latest one that was defined. - found = true; } } debug_exit(); - if( found ) + if( found_material ) + { + // Create a new material instead of assign a pointer because + // the indexfaceset can set color pervertex and that will be stored in the material. + m_model->m_Materials = new S3D_MATERIAL( m_Master, found_material->m_Name ); + m_model->m_Materials->m_AmbientColor = found_material->m_AmbientColor; + m_model->m_Materials->m_DiffuseColor = found_material->m_DiffuseColor; + m_model->m_Materials->m_EmissiveColor = found_material->m_EmissiveColor; + m_model->m_Materials->m_SpecularColor = found_material->m_SpecularColor; + m_model->m_Materials->m_Shininess = found_material->m_Shininess; + m_model->m_Materials->m_Transparency = found_material->m_Transparency; + m_model->m_Materials->m_ColorPerVertex = false; return 0; + } wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_appearance error: material not found" ) ); return -1; @@ -1228,17 +1239,37 @@ int VRML2_MODEL_PARSER::read_material() wxString mat_name; mat_name = FROM_UTF8( text ); + S3D_MATERIAL* found_material = NULL; + for( material = m_Master->m_Materials; material; material = material->Next() ) { if( material->m_Name == mat_name ) { - m_model->m_Materials = material; - debug_exit(); - return 0; + found_material = material; + // We dont exit here, since it seems that VRML can have + // multiple material defined, so, it will copy the latest one that was defined. } } + debug_exit(); + + if( found_material ) + { + // Create a new material instead of assign a pointer because + // the indexfaceset can set color pervertex and that will be stored in the material. + m_model->m_Materials = new S3D_MATERIAL( m_Master, found_material->m_Name ); + m_model->m_Materials->m_AmbientColor = found_material->m_AmbientColor; + m_model->m_Materials->m_DiffuseColor = found_material->m_DiffuseColor; + m_model->m_Materials->m_EmissiveColor = found_material->m_EmissiveColor; + m_model->m_Materials->m_SpecularColor = found_material->m_SpecularColor; + m_model->m_Materials->m_Shininess = found_material->m_Shininess; + m_model->m_Materials->m_Transparency = found_material->m_Transparency; + m_model->m_Materials->m_ColorPerVertex = false; + return 0; + } + wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_material error: material not found" ) ); + return -1; } } } @@ -1365,6 +1396,7 @@ int VRML2_MODEL_PARSER::read_IndexedFaceSet() { if( strcmp( text, "TRUE" ) == 0 ) { + wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedFaceSet m_normalPerVertex TRUE" ) ); m_normalPerVertex = true; } } @@ -1373,12 +1405,15 @@ int VRML2_MODEL_PARSER::read_IndexedFaceSet() { GetNextTag( m_file, text, sizeof(text) ); - if( strcmp( text, "TRUE" ) ) + if( strcmp( text, "TRUE" ) == 0 ) { + wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedFaceSet colorPerVertex TRUE" ) ); colorPerVertex = true; + m_model->m_Materials->m_ColorPerVertex = true; } else { + wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedFaceSet colorPerVertex FALSE" ) ); colorPerVertex = false; } } @@ -1456,37 +1491,51 @@ int VRML2_MODEL_PARSER::read_colorIndex() wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_colorIndex" ) ); debug_enter(); - m_model->m_MaterialIndex.clear(); + m_model->m_MaterialIndexPerFace.clear(); + m_model->m_MaterialIndexPerVertex.clear(); + if( colorPerVertex == true ) { int index; - int first_index; - while( fscanf( m_file, "%d, ", &index ) ) + if( m_model->m_CoordIndex.size() > 0 ) + m_model->m_MaterialIndexPerVertex.reserve( m_model->m_CoordIndex.size() ); + + std::vector materialIndexPerVertex; + materialIndexPerVertex.reserve( 3 ); // Start at least with 3 + + while( fscanf( m_file, "%d, ", &index ) == 1 ) { if( index == -1 ) { - // it only implemented color per face, so it will store as the first in the list - m_model->m_MaterialIndex.push_back( first_index ); + m_model->m_MaterialIndexPerVertex.push_back( materialIndexPerVertex ); + materialIndexPerVertex.clear(); + materialIndexPerVertex.reserve( 3 ); } else { - first_index = index; + materialIndexPerVertex.push_back( index ); } } + + wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_colorIndex m_MaterialIndexPerVertex.size: %lu" ), m_model->m_MaterialIndexPerVertex.size() ); } else { int index; + if( m_model->m_CoordIndex.size() > 0 ) + m_model->m_MaterialIndexPerFace.reserve( m_model->m_CoordIndex.size() ); + while( fscanf( m_file, "%d,", &index ) ) { - m_model->m_MaterialIndex.push_back( index ); + m_model->m_MaterialIndexPerFace.push_back( index ); } + + wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_colorIndex m_MaterialIndexPerFace.size: %lu" ), m_model->m_MaterialIndexPerFace.size() ); } - //wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_colorIndex m_MaterialIndex.size: %u" ), (unsigned int)m_model->m_MaterialIndex.size() ); debug_exit(); return 0; } @@ -1534,21 +1583,21 @@ int VRML2_MODEL_PARSER::read_coordIndex() glm::ivec3 coord; - int dummy; // should be -1 + int coordIdx; // should be -1 std::vector coord_list; coord_list.clear(); - while( fscanf( m_file, "%d, ", &dummy ) == 1 ) + while( fscanf( m_file, "%d, ", &coordIdx ) == 1 ) { - if( dummy == -1 ) + if( coordIdx == -1 ) { m_model->m_CoordIndex.push_back( coord_list ); coord_list.clear(); } else { - coord_list.push_back( dummy ); + coord_list.push_back( coordIdx ); } } @@ -1582,6 +1631,7 @@ int VRML2_MODEL_PARSER::read_Color() if( strcmp( text, "color" ) == 0 ) { + m_model->m_Materials->m_DiffuseColor.clear(); ParseVertexList( m_file, m_model->m_Materials->m_DiffuseColor ); } } diff --git a/3d-viewer/x3dmodelparser.cpp b/3d-viewer/x3dmodelparser.cpp index 82bc60c1cd..6b7394f67e 100644 --- a/3d-viewer/x3dmodelparser.cpp +++ b/3d-viewer/x3dmodelparser.cpp @@ -97,49 +97,27 @@ bool X3D_MODEL_PARSER::Load( const wxString& aFilename ) m_model.reset( new S3D_MESH() ); childs.push_back( m_model ); - readTransform( *node_it ); + wxXmlNode* node = *node_it; + wxXmlAttribute* prop = node->GetAttributes(); + + wxLogTrace( traceX3DParser, wxT( "Transform: %s %s" ), prop->GetName(), prop->GetValue() ); + + readTransform( node ); + + } return true; } -wxString X3D_MODEL_PARSER::VRML2_representation() -{ - wxString output; - - for( unsigned i = 0; i < vrml_points.size(); i++ ) - { - output += - wxT( "Shape {\n" - " appearance Appearance {\n" - " material Material {\n" ) + - vrml_materials[i] + - wxT( " }\n" - " }\n" - " geometry IndexedFaceSet {\n" - " solid TRUE\n" - " coord Coordinate {\n" - " point [\n" ) + - vrml_points[i] + - wxT( " ]\n" - " }\n" - " coordIndex [\n" ) + - vrml_coord_indexes[i] + - wxT( " ]\n" - " }\n" - "},\n" ); - } - - return output; -} - - void X3D_MODEL_PARSER::GetChildsByName( wxXmlNode* aParent, const wxString aName, std::vector& aResult ) { - // Breadth-first search (BFS) + // (-Breadth-first search (BFS)-) + // **NOTE** This function was changed to get only the first depth of ocorrences + // so it will be an workarround for the Bug #1443431 std::queue found; found.push( aParent ); @@ -153,11 +131,9 @@ void X3D_MODEL_PARSER::GetChildsByName( wxXmlNode* aParent, child = child->GetNext() ) { if( child->GetName() == aName ) - { aResult.push_back( child ); - } - - found.push( child ); + else // **NOTE** This function was changed here to get only the first depth of ocorrences + found.push( child ); } found.pop(); @@ -198,6 +174,9 @@ void X3D_MODEL_PARSER::readTransform( wxXmlNode* aTransformNode ) PROPERTY_MAP properties; GetNodeProperties( aTransformNode, properties ); + + + GetChildsByName( aTransformNode, wxT( "IndexedFaceSet" ), childnodes ); for( NODE_LIST::iterator node = childnodes.begin(); @@ -430,7 +409,7 @@ void X3D_MODEL_PARSER::readIndexedFaceSet( wxXmlNode* aFaceNode, double angle = 0.0; wxStringTokenizer tokens( aTransformProps[ wxT( "rotation" ) ] ); - double x, y, z; + double x = 0.0, y = 0.0, z = 0.0; if( !( tokens.GetNextToken().ToDouble( &x ) && tokens.GetNextToken().ToDouble( &y ) @@ -551,7 +530,7 @@ void X3D_MODEL_PARSER::readIndexedFaceSet( wxXmlNode* aFaceNode, for( unsigned id = 0; id < color_points.size() / 3; id++ ) { - m_model->m_MaterialIndex.push_back( id ); + m_model->m_MaterialIndexPerFace.push_back( id ); int color_triplet_indx = id * 3; glm::vec3 colorface( color_points[ color_triplet_indx + 0 ], diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index db62471743..a326945325 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -285,7 +285,6 @@ void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet( double aCorrectionFactor ) { unsigned cornerscount = GetFilledPolysList().GetCornersCount(); - CPOLYGONS_LIST polygonslist; if( cornerscount == 0 ) return;