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;