Commit d819a380 authored by Sven D's avatar Sven D Committed by Wayne Stambaugh

Fix VRML V2 parser bug. (fixes lp:1417217)

* Add support for VRML DEF coordinate key word.
* Coding policy fixes by Blair Bonnett <blair.bonnett@gmail.com>
* Debugging output clean up.
parent 1e2af7fe
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2014 Mario Luzeiro <mrluzeiro@gmail.com> * Copyright (C) 2014 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -46,8 +46,8 @@ S3D_MESH::S3D_MESH() ...@@ -46,8 +46,8 @@ S3D_MESH::S3D_MESH()
m_translation = glm::vec3( 0.0f, 0.0f, 0.0f ); m_translation = glm::vec3( 0.0f, 0.0f, 0.0f );
m_rotation = glm::vec4( 0.0f, 0.0f, 0.0f, 0.0f ); m_rotation = glm::vec4( 0.0f, 0.0f, 0.0f, 0.0f );
m_scale = glm::vec3( 1.0f, 1.0f, 1.0f ); m_scale = glm::vec3( 1.0f, 1.0f, 1.0f );
m_scaleOrientation = glm::vec4( 0.0f, 0.0f, 1.0f, 0.0f ); // not used m_scaleOrientation = glm::vec4( 0.0f, 0.0f, 1.0f, 0.0f ); // not used
m_center = glm::vec3( 0.0f, 0.0f, 0.0f ); // not used m_center = glm::vec3( 0.0f, 0.0f, 0.0f ); // not used
} }
...@@ -55,10 +55,11 @@ S3D_MESH::~S3D_MESH() ...@@ -55,10 +55,11 @@ S3D_MESH::~S3D_MESH()
{ {
for( unsigned int idx = 0; idx < childs.size(); idx++ ) for( unsigned int idx = 0; idx < childs.size(); idx++ )
{ {
delete childs[idx]; delete childs[idx];
} }
} }
void S3D_MESH::openGL_RenderAllChilds() void S3D_MESH::openGL_RenderAllChilds()
{ {
//DBG( printf( "openGL_RenderAllChilds") ); //DBG( printf( "openGL_RenderAllChilds") );
...@@ -82,7 +83,6 @@ void S3D_MESH::openGL_RenderAllChilds() ...@@ -82,7 +83,6 @@ void S3D_MESH::openGL_RenderAllChilds()
SetOpenGlDefaultMaterial(); SetOpenGlDefaultMaterial();
glPopMatrix(); glPopMatrix();
} }
...@@ -94,15 +94,10 @@ void S3D_MESH::openGL_Render() ...@@ -94,15 +94,10 @@ void S3D_MESH::openGL_Render()
&& g_Parm_3D_Visu.GetFlag( FL_RENDER_SMOOTH ); && g_Parm_3D_Visu.GetFlag( FL_RENDER_SMOOTH );
if( m_Materials ) if( m_Materials )
{
m_Materials->SetOpenGLMaterial( 0, useMaterial ); m_Materials->SetOpenGLMaterial( 0, useMaterial );
}
if( m_CoordIndex.size() == 0)
{
if( m_CoordIndex.size() == 0 )
return; return;
}
glPushMatrix(); glPushMatrix();
glTranslatef( m_translation.x, m_translation.y, m_translation.z ); glTranslatef( m_translation.x, m_translation.y, m_translation.z );
...@@ -117,9 +112,7 @@ void S3D_MESH::openGL_Render() ...@@ -117,9 +112,7 @@ void S3D_MESH::openGL_Render()
if( m_PerVertexNormalsNormalized.size() == 0 ) if( m_PerVertexNormalsNormalized.size() == 0 )
{ {
if( smoothShapes ) if( smoothShapes )
{
calcPerPointNormals(); calcPerPointNormals();
}
} }
for( unsigned int idx = 0; idx < m_CoordIndex.size(); idx++ ) for( unsigned int idx = 0; idx < m_CoordIndex.size(); idx++ )
...@@ -127,17 +120,21 @@ void S3D_MESH::openGL_Render() ...@@ -127,17 +120,21 @@ void S3D_MESH::openGL_Render()
if( m_MaterialIndex.size() > 1 ) if( m_MaterialIndex.size() > 1 )
{ {
if( m_Materials ) if( m_Materials )
{
m_Materials->SetOpenGLMaterial( m_MaterialIndex[idx], useMaterial ); m_Materials->SetOpenGLMaterial( m_MaterialIndex[idx], useMaterial );
}
} }
switch( m_CoordIndex[idx].size() ) switch( m_CoordIndex[idx].size() )
{ {
case 3: glBegin( GL_TRIANGLES );break; case 3:
case 4: glBegin( GL_QUADS ); break; glBegin( GL_TRIANGLES );
default: glBegin( GL_POLYGON ); break; break;
case 4:
glBegin( GL_QUADS );
break;
default:
glBegin( GL_POLYGON );
break;
} }
...@@ -187,34 +184,36 @@ void S3D_MESH::openGL_Render() ...@@ -187,34 +184,36 @@ void S3D_MESH::openGL_Render()
} }
void S3D_MESH::calcPointNormalized () void S3D_MESH::calcPointNormalized()
{ {
//DBG( printf( "calcPointNormalized\n" ) ); //DBG( printf( "calcPointNormalized\n" ) );
if( isPointNormalizedComputed == true ) if( isPointNormalizedComputed == true )
{
return; return;
}
isPointNormalizedComputed = true; isPointNormalizedComputed = true;
if( m_PerVertexNormalsNormalized.size() > 0 ) if( m_PerVertexNormalsNormalized.size() > 0 )
{
return; return;
}
m_PointNormalized.clear(); m_PointNormalized.clear();
float biggerPoint = 0.0f; float biggerPoint = 0.0f;
for( unsigned int i = 0; i< m_Point.size(); i++ ) for( unsigned int i = 0; i< m_Point.size(); i++ )
{ {
if( fabs( m_Point[i].x ) > biggerPoint) biggerPoint = fabs( m_Point[i].x ); if( fabs( m_Point[i].x ) > biggerPoint )
if( fabs( m_Point[i].y ) > biggerPoint) biggerPoint = fabs( m_Point[i].y ); biggerPoint = fabs( m_Point[i].x );
if( fabs( m_Point[i].z ) > biggerPoint) biggerPoint = fabs( m_Point[i].z );
if( fabs( m_Point[i].y ) > biggerPoint )
biggerPoint = fabs( m_Point[i].y );
if( fabs( m_Point[i].z ) > biggerPoint )
biggerPoint = fabs( m_Point[i].z );
} }
biggerPoint = 1.0 / biggerPoint; biggerPoint = 1.0 / biggerPoint;
for( unsigned int i= 0; i< m_Point.size(); i++ ) for( unsigned int i = 0; i < m_Point.size(); i++ )
{ {
glm::vec3 p; glm::vec3 p;
p = m_Point[i] * biggerPoint; p = m_Point[i] * biggerPoint;
...@@ -237,30 +236,22 @@ bool IsClockwise( glm::vec3 v0, glm::vec3 v1, glm::vec3 v2 ) ...@@ -237,30 +236,22 @@ bool IsClockwise( glm::vec3 v0, glm::vec3 v1, glm::vec3 v2 )
} }
void S3D_MESH::calcPerFaceNormals () void S3D_MESH::calcPerFaceNormals()
{ {
//DBG( printf( "calcPerFaceNormals" ) ); //DBG( printf( "calcPerFaceNormals" ) );
if( isPerFaceNormalsComputed == true ) if( isPerFaceNormalsComputed == true )
{
return; return;
}
isPerFaceNormalsComputed = true;
isPerFaceNormalsComputed = true;
if( m_PerVertexNormalsNormalized.size() > 0 ) if( m_PerVertexNormalsNormalized.size() > 0 )
{
return; return;
}
bool haveAlreadyNormals_from_model_file = false; bool haveAlreadyNormals_from_model_file = false;
if( m_PerFaceNormalsNormalized.size() > 0 ) if( m_PerFaceNormalsNormalized.size() > 0 )
{
haveAlreadyNormals_from_model_file = true; haveAlreadyNormals_from_model_file = true;
}
m_PerFaceNormalsRaw.clear(); m_PerFaceNormalsRaw.clear();
m_PerFaceSquaredArea.clear(); m_PerFaceSquaredArea.clear();
...@@ -268,9 +259,15 @@ void S3D_MESH::calcPerFaceNormals () ...@@ -268,9 +259,15 @@ void S3D_MESH::calcPerFaceNormals ()
//DBG( printf("m_CoordIndex.size %u\n", m_CoordIndex.size()) ); //DBG( printf("m_CoordIndex.size %u\n", m_CoordIndex.size()) );
//DBG( printf("m_PointNormalized.size %u\n", m_PointNormalized.size()) ); //DBG( printf("m_PointNormalized.size %u\n", m_PointNormalized.size()) );
for( unsigned int idx = 0; idx < m_CoordIndex.size(); idx++ ) // There are no points defined for the coordIndex
if( m_PointNormalized.size() == 0 )
{ {
m_CoordIndex.clear();
return;
}
for( unsigned int idx = 0; idx < m_CoordIndex.size(); idx++ )
{
// User normalized and multiply to get better resolution // User normalized and multiply to get better resolution
glm::vec3 v0 = m_PointNormalized[m_CoordIndex[idx][0]]; glm::vec3 v0 = m_PointNormalized[m_CoordIndex[idx][0]];
glm::vec3 v1 = m_PointNormalized[m_CoordIndex[idx][1]]; glm::vec3 v1 = m_PointNormalized[m_CoordIndex[idx][1]];
...@@ -300,14 +297,10 @@ void S3D_MESH::calcPerFaceNormals () ...@@ -300,14 +297,10 @@ void S3D_MESH::calcPerFaceNormals ()
float area = glm::dot( cross_prod, cross_prod ); float area = glm::dot( cross_prod, cross_prod );
if( cross_prod[2] < 0.0 ) if( cross_prod[2] < 0.0 )
{
area = -area; area = -area;
}
if( area < FLT_EPSILON ) if( area < FLT_EPSILON )
{
area = FLT_EPSILON * 2.0f; area = FLT_EPSILON * 2.0f;
}
m_PerFaceSquaredArea.push_back( area ); m_PerFaceSquaredArea.push_back( area );
...@@ -315,52 +308,55 @@ void S3D_MESH::calcPerFaceNormals () ...@@ -315,52 +308,55 @@ void S3D_MESH::calcPerFaceNormals ()
if( haveAlreadyNormals_from_model_file == false ) if( haveAlreadyNormals_from_model_file == false )
{ {
// normalize vertex normal // normalize vertex normal
float l = glm::length( cross_prod ); float l = glm::length( cross_prod );
if( l > FLT_EPSILON ) // avoid division by zero if( l > FLT_EPSILON ) // avoid division by zero
{ {
cross_prod = cross_prod / l; cross_prod = cross_prod / l;
} }
else else
{ {
// Cannot calc normal // Cannot calc normal
if( ( cross_prod.x > cross_prod.y ) && ( cross_prod.x > cross_prod.z ) ) if( ( cross_prod.x > cross_prod.y ) && ( cross_prod.x > cross_prod.z ) )
{ {
cross_prod.x = 1.0; cross_prod.y = 0.0; cross_prod.z = 0.0; cross_prod.x = 1.0;
} else if( ( cross_prod.y > cross_prod.x ) && ( cross_prod.y > cross_prod.z )) cross_prod.y = 0.0;
cross_prod.z = 0.0;
}
else if( ( cross_prod.y > cross_prod.x ) && ( cross_prod.y > cross_prod.z ) )
{ {
cross_prod.x = 0.0; cross_prod.y = 1.0; cross_prod.z = 0.0; cross_prod.x = 0.0;
} else cross_prod.y = 1.0;
cross_prod.z = 0.0;
}
else
{ {
cross_prod.x = 0.0; cross_prod.y = 1.0; cross_prod.z = 0.0; cross_prod.x = 0.0;
cross_prod.y = 0.0;
cross_prod.z = 1.0;
} }
} }
m_PerFaceNormalsNormalized.push_back( cross_prod ); m_PerFaceNormalsNormalized.push_back( cross_prod );
} }
} }
} }
// http://www.bytehazard.com/code/vertnorm.html // http://www.bytehazard.com/code/vertnorm.html
// http://www.emeyex.com/site/tuts/VertexNormals.pdf // http://www.emeyex.com/site/tuts/VertexNormals.pdf
void S3D_MESH::calcPerPointNormals () void S3D_MESH::calcPerPointNormals()
{ {
//DBG( printf( "calcPerPointNormals" ) ); //DBG( printf( "calcPerPointNormals" ) );
if( isPerPointNormalsComputed == true ) if( isPerPointNormalsComputed == true )
{
return; return;
}
isPerPointNormalsComputed = true; isPerPointNormalsComputed = true;
if( m_PerVertexNormalsNormalized.size() > 0 ) if( m_PerVertexNormalsNormalized.size() > 0 )
{
return; return;
}
m_PerFaceVertexNormals.clear(); m_PerFaceVertexNormals.clear();
...@@ -371,6 +367,7 @@ void S3D_MESH::calcPerPointNormals () ...@@ -371,6 +367,7 @@ void S3D_MESH::calcPerPointNormals ()
#ifdef USE_OPENMP #ifdef USE_OPENMP
#pragma omp parallel for #pragma omp parallel for
#endif /* USE_OPENMP */ #endif /* USE_OPENMP */
for( unsigned int each_face_A_idx = 0; each_face_A_idx < m_CoordIndex.size(); each_face_A_idx++ ) for( unsigned int each_face_A_idx = 0; each_face_A_idx < m_CoordIndex.size(); each_face_A_idx++ )
{ {
// n = face A facet normal // n = face A facet normal
...@@ -390,15 +387,16 @@ void S3D_MESH::calcPerPointNormals () ...@@ -390,15 +387,16 @@ void S3D_MESH::calcPerPointNormals ()
for( unsigned int each_face_B_idx = 0; each_face_B_idx < m_CoordIndex.size(); each_face_B_idx++ ) for( unsigned int each_face_B_idx = 0; each_face_B_idx < m_CoordIndex.size(); each_face_B_idx++ )
{ {
//if A != B { // ignore self //if A != B { // ignore self
if ( each_face_A_idx != each_face_B_idx) if( each_face_A_idx != each_face_B_idx )
{ {
if( (m_CoordIndex[each_face_B_idx][0] == vertexIndex) || if( (m_CoordIndex[each_face_B_idx][0] == vertexIndex)
(m_CoordIndex[each_face_B_idx][1] == vertexIndex) || || (m_CoordIndex[each_face_B_idx][1] == vertexIndex)
(m_CoordIndex[each_face_B_idx][2] == vertexIndex) ) || (m_CoordIndex[each_face_B_idx][2] == vertexIndex) )
{ {
glm::vec3 vector_face_B = m_PerFaceNormalsNormalized[each_face_B_idx]; glm::vec3 vector_face_B = m_PerFaceNormalsNormalized[each_face_B_idx];
float dot_prod = glm::dot(vector_face_A, vector_face_B); float dot_prod = glm::dot( vector_face_A, vector_face_B );
if( dot_prod > 0.05f ) if( dot_prod > 0.05f )
{ {
face_A_normals[each_vert_A_idx] += m_PerFaceNormalsRaw[each_face_B_idx] * (m_PerFaceSquaredArea[each_face_B_idx] * dot_prod); face_A_normals[each_vert_A_idx] += m_PerFaceNormalsRaw[each_face_B_idx] * (m_PerFaceSquaredArea[each_face_B_idx] * dot_prod);
...@@ -411,10 +409,7 @@ void S3D_MESH::calcPerPointNormals () ...@@ -411,10 +409,7 @@ void S3D_MESH::calcPerPointNormals ()
float l = glm::length( face_A_normals[each_vert_A_idx] ); float l = glm::length( face_A_normals[each_vert_A_idx] );
if( l > FLT_EPSILON ) // avoid division by zero if( l > FLT_EPSILON ) // avoid division by zero
{
face_A_normals[each_vert_A_idx] /= l; face_A_normals[each_vert_A_idx] /= l;
}
} }
} }
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013 Tuomas Vaherkoski <tuomasvaherkoski@gmail.com> * Copyright (C) 2013 Tuomas Vaherkoski <tuomasvaherkoski@gmail.com>
* Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -45,7 +45,7 @@ class X3D_MODEL_PARSER; ...@@ -45,7 +45,7 @@ class X3D_MODEL_PARSER;
class S3D_MODEL_PARSER class S3D_MODEL_PARSER
{ {
public: public:
S3D_MODEL_PARSER(S3D_MASTER* aMaster) : S3D_MODEL_PARSER( S3D_MASTER* aMaster ) :
master( aMaster ) master( aMaster )
{} {}
...@@ -96,7 +96,7 @@ public: ...@@ -96,7 +96,7 @@ public:
void Load( const wxString& aFilename, double aVrmlunits_to_3Dunits ); void Load( const wxString& aFilename, double aVrmlunits_to_3Dunits );
typedef std::map< wxString, wxString > PROPERTY_MAP; typedef std::map< wxString, wxString > PROPERTY_MAP;
typedef std::vector< wxXmlNode* > NODE_LIST; typedef std::vector< wxXmlNode* > NODE_LIST;
/** /**
* Function GetChildsByName * Function GetChildsByName
...@@ -125,9 +125,9 @@ public: ...@@ -125,9 +125,9 @@ public:
wxString VRML2_representation(); wxString VRML2_representation();
private: private:
wxString m_Filename; wxString m_Filename;
S3D_MESH *m_model; S3D_MESH* m_model;
std::vector<S3D_MESH *> childs; std::vector< S3D_MESH* > childs;
std::vector< wxString > vrml_materials; std::vector< wxString > vrml_materials;
std::vector< wxString > vrml_points; std::vector< wxString > vrml_points;
...@@ -142,6 +142,7 @@ private: ...@@ -142,6 +142,7 @@ private:
}; };
typedef std::map< std::string, std::vector< glm::vec3 > > VRML2_COORDINATE_MAP;
/** /**
* class VRML2_MODEL_PARSER * class VRML2_MODEL_PARSER
...@@ -165,25 +166,30 @@ public: ...@@ -165,25 +166,30 @@ public:
private: private:
int read_Transform(); int read_Transform();
int read_DEF(); int read_DEF();
int read_DEF_Coordinate();
int read_Shape(); int read_Shape();
int read_Appearance(); int read_Appearance();
int read_material(); int read_material();
int read_Material(); int read_Material();
int read_IndexedFaceSet(); int read_IndexedFaceSet();
int read_IndexedLineSet();
int read_Coordinate(); int read_Coordinate();
int read_CoordinateDef();
int read_Normal(); int read_Normal();
int read_NormalIndex(); int read_NormalIndex();
int read_Color(); int read_Color();
int read_coordIndex(); int read_coordIndex();
int read_colorIndex(); int read_colorIndex();
int read_USE();
bool m_normalPerVertex;
bool colorPerVertex; bool m_normalPerVertex;
S3D_MESH *m_model; bool colorPerVertex;
std::vector<S3D_MESH *> childs; S3D_MESH* m_model;
FILE *m_file; std::vector< S3D_MESH* > childs;
S3D_MATERIAL *m_Materials; FILE* m_file;
wxString m_Filename; S3D_MATERIAL* m_Materials;
wxString m_Filename;
VRML2_COORDINATE_MAP m_defCoordinateMap;
}; };
...@@ -224,13 +230,13 @@ private: ...@@ -224,13 +230,13 @@ private:
int readIndexedFaceSet_coordIndex(); int readIndexedFaceSet_coordIndex();
int readIndexedFaceSet_materialIndex(); int readIndexedFaceSet_materialIndex();
bool m_normalPerVertex; bool m_normalPerVertex;
bool colorPerVertex; bool colorPerVertex;
S3D_MESH *m_model; S3D_MESH* m_model;
std::vector<S3D_MESH *> childs; std::vector< S3D_MESH* > childs;
S3D_MATERIAL *m_Materials; S3D_MATERIAL* m_Materials;
FILE *m_file; FILE* m_file;
wxString m_Filename; wxString m_Filename;
}; };
/** /**
...@@ -246,8 +252,8 @@ public: ...@@ -246,8 +252,8 @@ public:
void Load( const wxString& aFilename, double aVrmlunits_to_3Dunits ); void Load( const wxString& aFilename, double aVrmlunits_to_3Dunits );
private: private:
VRML1_MODEL_PARSER *vrml1_parser; VRML1_MODEL_PARSER* vrml1_parser;
VRML2_MODEL_PARSER *vrml2_parser; VRML2_MODEL_PARSER* vrml2_parser;
}; };
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment