Commit 8db15e72 authored by unknown's avatar unknown Committed by jean-pierre charras

3D-viewer: Fixes and enhancements (add 3D bounding box for components). Add...

3D-viewer: Fixes and enhancements (add 3D bounding box for components). Add comments in header files. Fix some coding style issues.
parents 33acfae7 eee901ff
...@@ -105,9 +105,9 @@ void TransfertToGLlist( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUni ...@@ -105,9 +105,9 @@ void TransfertToGLlist( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUni
ay = aVertices[1].y - aVertices[0].y; ay = aVertices[1].y - aVertices[0].y;
az = aVertices[1].z - aVertices[0].z; az = aVertices[1].z - aVertices[0].z;
bx = aVertices[aVertices.size() - 1].x - aVertices[0].x; bx = aVertices[2].x - aVertices[0].x;
by = aVertices[aVertices.size() - 1].y - aVertices[0].y; by = aVertices[2].y - aVertices[0].y;
bz = aVertices[aVertices.size() - 1].z - aVertices[0].z; bz = aVertices[2].z - aVertices[0].z;
nx = ay * bz - az * by; nx = ay * bz - az * by;
ny = az * bx - ax * bz; ny = az * bx - ax * bz;
......
...@@ -94,6 +94,8 @@ EDA_3D_CANVAS::EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList ) : ...@@ -94,6 +94,8 @@ EDA_3D_CANVAS::EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList ) :
m_ZBottom = 0.0; m_ZBottom = 0.0;
m_ZTop = 0.0; m_ZTop = 0.0;
m_lightPos = S3D_VERTEX(0.0f, 0.0f, 50.0f);
// Clear all gl list identifiers: // Clear all gl list identifiers:
for( int ii = GL_ID_BEGIN; ii < GL_ID_END; ii++ ) for( int ii = GL_ID_BEGIN; ii < GL_ID_END; ii++ )
m_glLists[ii] = 0; m_glLists[ii] = 0;
...@@ -110,6 +112,12 @@ EDA_3D_CANVAS::~EDA_3D_CANVAS() ...@@ -110,6 +112,12 @@ EDA_3D_CANVAS::~EDA_3D_CANVAS()
ClearLists(); ClearLists();
m_init = false; m_init = false;
delete m_glRC; delete m_glRC;
// Free the list of parsers list
for( unsigned int i = 0; i < m_model_parsers_list.size(); i++ )
if( m_model_parsers_list[i] )
delete m_model_parsers_list[i];
} }
...@@ -132,6 +140,17 @@ void EDA_3D_CANVAS::ClearLists( int aGlList ) ...@@ -132,6 +140,17 @@ void EDA_3D_CANVAS::ClearLists( int aGlList )
m_glLists[ii] = 0; m_glLists[ii] = 0;
} }
if( m_text_fake_shadow_front >= 0 )
glDeleteTextures( 1, &m_text_fake_shadow_front );
if( m_text_fake_shadow_back >= 0 )
glDeleteTextures( 1, &m_text_fake_shadow_back );
if( m_text_fake_shadow_board >= 0 )
glDeleteTextures( 1, &m_text_fake_shadow_board );
m_shadow_init = false;
} }
...@@ -564,12 +583,12 @@ void EDA_3D_CANVAS::InitGL() ...@@ -564,12 +583,12 @@ void EDA_3D_CANVAS::InitGL()
void EDA_3D_CANVAS::SetLights() void EDA_3D_CANVAS::SetLights()
{ {
// activate light. the source is above the xy plane, at source_pos // activate light. the source is above the xy plane, at source_pos
GLfloat source_pos[4] = { 0.0, 0.0, 1000.0, 0.0 }; GLfloat source_pos[4] = { m_lightPos.x, m_lightPos.y, m_lightPos.z, 0.0f };
GLfloat light_color[4]; // color of lights (RGBA values) GLfloat light_color[4]; // color of lights (RGBA values)
light_color[3] = 1.0; light_color[3] = 1.0;
// Light above the xy plane // Light above the xy plane
light_color[0] = light_color[1] = light_color[2] = 0.1; light_color[0] = light_color[1] = light_color[2] = 0.2;
glLightfv( GL_LIGHT0, GL_AMBIENT, light_color ); glLightfv( GL_LIGHT0, GL_AMBIENT, light_color );
light_color[0] = light_color[1] = light_color[2] = 1.0; light_color[0] = light_color[1] = light_color[2] = 1.0;
...@@ -580,7 +599,7 @@ void EDA_3D_CANVAS::SetLights() ...@@ -580,7 +599,7 @@ void EDA_3D_CANVAS::SetLights()
glLightfv( GL_LIGHT0, GL_POSITION, source_pos ); glLightfv( GL_LIGHT0, GL_POSITION, source_pos );
light_color[0] = light_color[1] = light_color[2] = 0.1; light_color[0] = light_color[1] = light_color[2] = 0.2;
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, light_color ); glLightModelfv( GL_LIGHT_MODEL_AMBIENT, light_color );
glEnable( GL_LIGHT0 ); // White spot on Z axis ( top ) glEnable( GL_LIGHT0 ); // White spot on Z axis ( top )
......
...@@ -43,7 +43,9 @@ ...@@ -43,7 +43,9 @@
#endif #endif
#include <3d_struct.h> #include <3d_struct.h>
#include <modelparsers.h>
#include <class_module.h> #include <class_module.h>
#include <CBBox.h>
class BOARD_DESIGN_SETTINGS; class BOARD_DESIGN_SETTINGS;
class EDA_3D_FRAME; class EDA_3D_FRAME;
...@@ -78,16 +80,15 @@ class EDA_3D_CANVAS : public wxGLCanvas ...@@ -78,16 +80,15 @@ class EDA_3D_CANVAS : public wxGLCanvas
{ {
private: private:
bool m_init; bool m_init;
bool m_reportWarnings; // true to report all wranings when build the 3D scene bool m_reportWarnings; ///< true to report all wranings when build the 3D scene false to report errors only
// false to report errors only GLuint m_glLists[GL_ID_END]; ///< GL lists
GLuint m_glLists[GL_ID_END]; // GL lists
wxGLContext* m_glRC; wxGLContext* m_glRC;
wxRealPoint m_draw3dOffset; // offset to draw the 3D mesh. wxRealPoint m_draw3dOffset; ///< offset to draw the 3D mesh.
double m_ZBottom; // position of the back layer double m_ZBottom; ///< position of the back layer
double m_ZTop; // position of the front layer double m_ZTop; ///< position of the front layer
GLuint m_text_pcb; // an index to the texture generated for pcb texts GLuint m_text_pcb; ///< an index to the texture generated for pcb texts
GLuint m_text_silk; // an index to the texture generated for silk layers GLuint m_text_silk; ///< an index to the texture generated for silk layers
// Index to the textures generated for shadows // Index to the textures generated for shadows
bool m_shadow_init; bool m_shadow_init;
...@@ -95,9 +96,21 @@ private: ...@@ -95,9 +96,21 @@ private:
GLuint m_text_fake_shadow_back; GLuint m_text_fake_shadow_back;
GLuint m_text_fake_shadow_board; GLuint m_text_fake_shadow_board;
void Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture, CBBOX m_boardAABBox; ///< Axis Align Bounding Box of the board
CBBOX m_fastAABBox; ///< Axis Align Bounding Box that contain the other bounding boxes
CBBOX m_fastAABBox_Shadow; ///< A bit scalled version of the m_fastAABBox
S3D_VERTEX m_lightPos;
/// Stores the list of parsers for each new file name (dont repeat files already loaded)
std::vector<S3D_MODEL_PARSER *> m_model_parsers_list;
std::vector<wxString> m_model_filename_list;
void create_and_render_shadow_buffer( GLuint *aDst_gl_texture,
GLuint aTexture_size, bool aDraw_body, int aBlurPasses ); GLuint aTexture_size, bool aDraw_body, int aBlurPasses );
void calcBBox();
public: public:
EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList = 0 ); EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList = 0 );
~EDA_3D_CANVAS(); ~EDA_3D_CANVAS();
...@@ -187,33 +200,33 @@ private: ...@@ -187,33 +200,33 @@ private:
wxPoint getBoardCenter() const; wxPoint getBoardCenter() const;
/** /**
* Helper function SetGLTechLayersColor * Helper function setGLTechLayersColor
* Initialize the color to draw the non copper layers * Initialize the color to draw the non copper layers
* in realistic mode and normal mode. * in realistic mode and normal mode.
*/ */
void setGLTechLayersColor( LAYER_NUM aLayer ); void setGLTechLayersColor( LAYER_NUM aLayer );
/** /**
* Helper function SetGLCopperColor * Helper function setGLCopperColor
* Initialize the copper color to draw the board * Initialize the copper color to draw the board
* in realistic mode (a golden yellow color ) * in realistic mode (a golden yellow color )
*/ */
void setGLCopperColor(); void setGLCopperColor();
/** /**
* Helper function SetGLEpoxyColor * Helper function setGLEpoxyColor
* Initialize the color to draw the epoxy body board in realistic mode. * Initialize the color to draw the epoxy body board in realistic mode.
*/ */
void setGLEpoxyColor( float aTransparency = 1.0 ); void setGLEpoxyColor( float aTransparency = 1.0 );
/** /**
* Helper function SetGLSolderMaskColor * Helper function setGLSolderMaskColor
* Initialize the color to draw the solder mask layers in realistic mode. * Initialize the color to draw the solder mask layers in realistic mode.
*/ */
void setGLSolderMaskColor( float aTransparency = 1.0 ); void setGLSolderMaskColor( float aTransparency = 1.0 );
/** /**
* Function BuildBoard3DView * Function buildBoard3DView
* Called by CreateDrawGL_List() * Called by CreateDrawGL_List()
* Populates the OpenGL GL_ID_BOARD draw list with board items only on copper layers. * Populates the OpenGL GL_ID_BOARD draw list with board items only on copper layers.
* 3D footprint shapes, tech layers and aux layers are not on this list * 3D footprint shapes, tech layers and aux layers are not on this list
...@@ -224,27 +237,27 @@ private: ...@@ -224,27 +237,27 @@ private:
* created by the build process (can be NULL) * created by the build process (can be NULL)
* @param aShowWarnings = true to show all messages, false to show errors only * @param aShowWarnings = true to show all messages, false to show errors only
*/ */
void BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, void buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
wxString* aErrorMessages, bool aShowWarnings ); wxString* aErrorMessages, bool aShowWarnings );
/** /**
* Function BuildTechLayers3DView * Function buildTechLayers3DView
* Called by CreateDrawGL_List() * Called by CreateDrawGL_List()
* Populates the OpenGL GL_ID_TECH_LAYERS draw list with items on tech layers * Populates the OpenGL GL_ID_TECH_LAYERS draw list with items on tech layers
* @param aErrorMessages = a wxString to add error and warning messages * @param aErrorMessages = a wxString to add error and warning messages
* created by the build process (can be NULL) * created by the build process (can be NULL)
* @param aShowWarnings = true to show all messages, false to show errors only * @param aShowWarnings = true to show all messages, false to show errors only
*/ */
void BuildTechLayers3DView( wxString* aErrorMessages, bool aShowWarnings ); void buildTechLayers3DView( wxString* aErrorMessages, bool aShowWarnings );
/** /**
* Function BuildShadowList * Function buildShadowList
* Called by CreateDrawGL_List() * Called by CreateDrawGL_List()
*/ */
void BuildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint aBoardList ); void buildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint aBoardList );
/** /**
* Function BuildFootprintShape3DList * Function buildFootprintShape3DList
* Called by CreateDrawGL_List() * Called by CreateDrawGL_List()
* Fills the OpenGL GL_ID_3DSHAPES_SOLID and GL_ID_3DSHAPES_TRANSP * Fills the OpenGL GL_ID_3DSHAPES_SOLID and GL_ID_3DSHAPES_TRANSP
* draw lists with 3D footprint shapes * draw lists with 3D footprint shapes
...@@ -252,19 +265,18 @@ private: ...@@ -252,19 +265,18 @@ private:
* @param aTransparentList is the gl list for non transparent items, * @param aTransparentList is the gl list for non transparent items,
* which need to be drawn after all other items * which need to be drawn after all other items
*/ */
void BuildFootprintShape3DList( GLuint aOpaqueList, void buildFootprintShape3DList( GLuint aOpaqueList,
GLuint aTransparentList, GLuint aTransparentList );
bool aSideToLoad );
/** /**
* Function BuildBoard3DAuxLayers * Function buildBoard3DAuxLayers
* Called by CreateDrawGL_List() * Called by CreateDrawGL_List()
* Fills the OpenGL GL_ID_AUX_LAYERS draw list * Fills the OpenGL GL_ID_AUX_LAYERS draw list
* with items on aux layers only * with items on aux layers only
*/ */
void BuildBoard3DAuxLayers(); void buildBoard3DAuxLayers();
void Draw3DGrid( double aGriSizeMM ); void draw3DGrid( double aGriSizeMM );
void Draw3DAxis(); void draw3DAxis();
/** /**
* Helper function BuildPadShapeThickOutlineAsPolygon: * Helper function BuildPadShapeThickOutlineAsPolygon:
...@@ -272,7 +284,7 @@ private: ...@@ -272,7 +284,7 @@ private:
* with a line thickness = aWidth * with a line thickness = aWidth
* Used only to draw pads outlines on silkscreen layers. * Used only to draw pads outlines on silkscreen layers.
*/ */
void BuildPadShapeThickOutlineAsPolygon( const D_PAD* aPad, void buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
CPOLYGONS_LIST& aCornerBuffer, CPOLYGONS_LIST& aCornerBuffer,
int aWidth, int aWidth,
int aCircleToSegmentsCount, int aCircleToSegmentsCount,
...@@ -280,54 +292,48 @@ private: ...@@ -280,54 +292,48 @@ private:
/** /**
* Helper function Draw3DViaHole: * Helper function draw3DViaHole:
* Draw the via hole: * Draw the via hole:
* Build a vertical hole (a cylinder) between the first and the last via layers * Build a vertical hole (a cylinder) between the first and the last via layers
*/ */
void Draw3DViaHole( const VIA * aVia ); void draw3DViaHole( const VIA * aVia );
/** /**
* Helper function Draw3DPadHole: * Helper function draw3DPadHole:
* Draw the pad hole: * Draw the pad hole:
* Build a vertical hole (round or oblong) between the front and back layers * Build a vertical hole (round or oblong) between the front and back layers
*/ */
void Draw3DPadHole( const D_PAD * aPad ); void draw3DPadHole( const D_PAD * aPad );
/** /**
* function Render3DComponentShape * function render3DComponentShape
* insert mesh in gl list * insert mesh in gl list
* @param module * @param module
* @param aIsRenderingJustNonTransparentObjects = true to load non transparent objects * @param aIsRenderingJustNonTransparentObjects = true to load non transparent objects
* @param aIsRenderingJustTransparentObjects = true to load non transparent objects * @param aIsRenderingJustTransparentObjects = true to load non transparent objects
* @param aSideToLoad = false will load not fliped, true will load fliped objects
* in openGL, transparent objects should be drawn *after* non transparent objects * in openGL, transparent objects should be drawn *after* non transparent objects
*/ */
void Render3DComponentShape( MODULE* module, void render3DComponentShape( MODULE* module,
bool aIsRenderingJustNonTransparentObjects, bool aIsRenderingJustNonTransparentObjects,
bool aIsRenderingJustTransparentObjects, bool aIsRenderingJustTransparentObjects );
bool aSideToLoad );
/** /**
* function Read3DComponentShape * function read3DComponentShape
* read the 3D component shape(s) of the footprint (physical shape). * read the 3D component shape(s) of the footprint (physical shape).
* @param module * @param module
* @param model_parsers_list = list of each new model loaded
* @param model_filename_list = list of each new filename model loaded
* @return true if load was succeeded, false otherwise * @return true if load was succeeded, false otherwise
*/ */
bool Read3DComponentShape( MODULE* module, bool read3DComponentShape( MODULE* module );
std::vector<S3D_MODEL_PARSER *>& model_parsers_list,
std::vector<wxString>& model_filename_list );
/** /**
* function GenerateFakeShadowsTextures * function generateFakeShadowsTextures
* creates shadows of the board an footprints * creates shadows of the board an footprints
* for aesthetical purpose * for aesthetical purpose
* @param aErrorMessages = a wxString to add error and warning messages * @param aErrorMessages = a wxString to add error and warning messages
* created by the build process (can be NULL) * created by the build process (can be NULL)
* @param aShowWarnings = true to show all messages, false to show errors only * @param aShowWarnings = true to show all messages, false to show errors only
*/ */
void GenerateFakeShadowsTextures( wxString* aErrorMessages, bool aShowWarnings ); void generateFakeShadowsTextures( wxString* aErrorMessages, bool aShowWarnings );
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
......
/**
* @file 3d_class.cpp
*/
/* /*
* 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.
* *
...@@ -25,6 +21,9 @@ ...@@ -25,6 +21,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
/**
* @file 3d_class.cpp
*/
#include <fctsys.h> #include <fctsys.h>
...@@ -79,12 +78,14 @@ S3D_MASTER:: ~S3D_MASTER() ...@@ -79,12 +78,14 @@ S3D_MASTER:: ~S3D_MASTER()
{ {
next = m_3D_Drawings->Next(); next = m_3D_Drawings->Next();
delete m_3D_Drawings; delete m_3D_Drawings;
m_3D_Drawings = 0;
} }
for( ; m_Materials != NULL; m_Materials = nextmat ) for( ; m_Materials != NULL; m_Materials = nextmat )
{ {
nextmat = m_Materials->Next(); nextmat = m_Materials->Next();
delete m_Materials; delete m_Materials;
m_Materials = 0;
} }
} }
...@@ -115,19 +116,59 @@ void S3D_MASTER::SetShape3DName( const wxString& aShapeName ) ...@@ -115,19 +116,59 @@ void S3D_MASTER::SetShape3DName( const wxString& aShapeName )
return; return;
wxFileName fn = m_Shape3DName; wxFileName fn = m_Shape3DName;
wxString ext = fn.GetExt(); m_Shape3DNameExtension = fn.GetExt();
if( ext == wxT( "wrl" ) || ext == wxT( "x3d" ) ) if( m_Shape3DNameExtension == wxT( "wrl" ) ||
m_Shape3DNameExtension == wxT( "x3d" ) )
m_ShapeType = FILE3D_VRML; m_ShapeType = FILE3D_VRML;
else if( ext == wxT( "idf" ) ) else if( m_Shape3DNameExtension == wxT( "idf" ) )
m_ShapeType = FILE3D_IDF; m_ShapeType = FILE3D_IDF;
else else
m_ShapeType = FILE3D_UNKNOWN; m_ShapeType = FILE3D_UNKNOWN;
// Expand any environment variables embedded in footprint's m_Shape3DName field.
// To ensure compatibility with most of footprint's m_Shape3DName field,
// if the m_Shape3DName is not an absolute path the default path
// given by the environment variable KISYS3DMOD will be used
if( m_Shape3DName.StartsWith( wxT("${") ) )
m_Shape3DFullFilename = wxExpandEnvVars( m_Shape3DName );
else
m_Shape3DFullFilename = m_Shape3DName;
wxFileName fnFull( m_Shape3DFullFilename );
if( !( fnFull.IsAbsolute() || m_Shape3DFullFilename.StartsWith( wxT(".") ) ) )
{
wxString default_path;
wxGetEnv( KISYS3DMOD, &default_path );
if( !( default_path.IsEmpty() ) )
{
if( !default_path.EndsWith( wxT("/") ) && !default_path.EndsWith( wxT("\\") ) )
default_path += wxT("/");
m_Shape3DFullFilename = default_path + m_Shape3DFullFilename;
}
}
return; return;
} }
const wxString S3D_MASTER::GetShape3DFullFilename()
{
return m_Shape3DFullFilename;
}
const wxString S3D_MASTER::GetShape3DExtension()
{
return m_Shape3DNameExtension;
}
STRUCT_3D_SHAPE::STRUCT_3D_SHAPE( EDA_ITEM* aParent ) : STRUCT_3D_SHAPE::STRUCT_3D_SHAPE( EDA_ITEM* aParent ) :
EDA_ITEM( aParent, NOT_USED ) EDA_ITEM( aParent, NOT_USED )
{ {
......
/* /*
* 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-2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 1992-2015 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
...@@ -23,6 +24,7 @@ ...@@ -23,6 +24,7 @@
/** /**
* @file 3d_draw.cpp * @file 3d_draw.cpp
*
*/ */
#include <fctsys.h> #include <fctsys.h>
...@@ -42,7 +44,8 @@ ...@@ -42,7 +44,8 @@
#include <class_pcb_text.h> #include <class_pcb_text.h>
#include <colors_selection.h> #include <colors_selection.h>
#include <convert_basic_shapes_to_polygon.h> #include <convert_basic_shapes_to_polygon.h>
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
#include <gal/opengl/opengl_compositor.h>
#ifdef __WINDOWS__ #ifdef __WINDOWS__
#include <GL/glew.h> // must be included before gl.h #include <GL/glew.h> // must be included before gl.h
#endif #endif
...@@ -65,11 +68,9 @@ ...@@ -65,11 +68,9 @@
static GLfloat Get3DLayer_Z_Orientation( LAYER_NUM aLayer ); static GLfloat Get3DLayer_Z_Orientation( LAYER_NUM aLayer );
void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture, void EDA_3D_CANVAS::create_and_render_shadow_buffer( GLuint *aDst_gl_texture,
GLuint aTexture_size, bool aDraw_body, int aBlurPasses ) GLuint aTexture_size, bool aDraw_body, int aBlurPasses )
{ {
unsigned char *depthbufferRGBA = (unsigned char*) malloc( aTexture_size * aTexture_size * 4 );
glDisable( GL_TEXTURE_2D ); glDisable( GL_TEXTURE_2D );
glViewport( 0, 0, aTexture_size, aTexture_size); glViewport( 0, 0, aTexture_size, aTexture_size);
...@@ -77,10 +78,7 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture, ...@@ -77,10 +78,7 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture,
glClearColor( 1.0f, 1.0f, 1.0f, 1.0f ); glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// move the board in order to draw it with its center at 0,0 3D coordinates // Render body and shapes
glTranslatef( -GetPrm3DVisu().m_BoardPos.x * GetPrm3DVisu().m_BiuTo3Dunits,
-GetPrm3DVisu().m_BoardPos.y * GetPrm3DVisu().m_BiuTo3Dunits,
0.0F );
if( aDraw_body && m_glLists[GL_ID_BODY] ) if( aDraw_body && m_glLists[GL_ID_BODY] )
glCallList( m_glLists[GL_ID_BODY] ); glCallList( m_glLists[GL_ID_BODY] );
...@@ -88,9 +86,10 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture, ...@@ -88,9 +86,10 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture,
if( m_glLists[GL_ID_3DSHAPES_SOLID_FRONT] ) if( m_glLists[GL_ID_3DSHAPES_SOLID_FRONT] )
glCallList( m_glLists[GL_ID_3DSHAPES_SOLID_FRONT] ); glCallList( m_glLists[GL_ID_3DSHAPES_SOLID_FRONT] );
glFinish(); // Create and Initialize the float depth buffer
float *depthbufferFloat = (float*) malloc( aTexture_size * aTexture_size * sizeof(float) ); float *depthbufferFloat = (float*) malloc( aTexture_size * aTexture_size * sizeof(float) );
for( unsigned int i = 0; i < (aTexture_size * aTexture_size); i++ ) for( unsigned int i = 0; i < (aTexture_size * aTexture_size); i++ )
depthbufferFloat[i] = 1.0f; depthbufferFloat[i] = 1.0f;
...@@ -101,6 +100,7 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture, ...@@ -101,6 +100,7 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture,
aTexture_size, aTexture_size, aTexture_size, aTexture_size,
GL_DEPTH_COMPONENT, GL_FLOAT, depthbufferFloat ); GL_DEPTH_COMPONENT, GL_FLOAT, depthbufferFloat );
CheckGLError( __FILE__, __LINE__ );
glEnable( GL_TEXTURE_2D ); glEnable( GL_TEXTURE_2D );
glGenTextures( 1, aDst_gl_texture ); glGenTextures( 1, aDst_gl_texture );
...@@ -109,43 +109,36 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture, ...@@ -109,43 +109,36 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture,
CIMAGE imgDepthBuffer( aTexture_size, aTexture_size ); CIMAGE imgDepthBuffer( aTexture_size, aTexture_size );
CIMAGE imgDepthBufferAux( aTexture_size, aTexture_size ); CIMAGE imgDepthBufferAux( aTexture_size, aTexture_size );
imgDepthBuffer.setPixelsFromNormalizedFloat( depthbufferFloat ); imgDepthBuffer.SetPixelsFromNormalizedFloat( depthbufferFloat );
free( depthbufferFloat ); free( depthbufferFloat );
wxString filename; // Debug texture image
//wxString filename;
//filename.Printf( "imgDepthBuffer_%04d", *aDst_gl_texture ); //filename.Printf( "imgDepthBuffer_%04d", *aDst_gl_texture );
//imgDepthBuffer.saveAsPNG( filename ); //imgDepthBuffer.SaveAsPNG( filename );
while (aBlurPasses > 0) while( aBlurPasses > 0 )
{ {
aBlurPasses--; aBlurPasses--;
imgDepthBufferAux.efxFilter( &imgDepthBuffer, 1.0, FILTER_BLUR); imgDepthBufferAux.EfxFilter( &imgDepthBuffer, FILTER_GAUSSIAN_BLUR );
imgDepthBuffer.efxFilter( &imgDepthBufferAux, 1.0, FILTER_BLUR); imgDepthBuffer.EfxFilter( &imgDepthBufferAux, FILTER_GAUSSIAN_BLUR );
} }
//filename.Printf( "imgDepthBuffer_blur_%04d", *aDst_gl_texture );
//imgDepthBuffer.saveAsPNG( filename );
imgDepthBuffer.copyFull( &imgDepthBuffer, &imgDepthBuffer, COPY_MUL ); // Debug texture image
//imgDepthBuffer.copyFull( &imgDepthBuffer, &imgDepthBuffer, COPY_MUL ); //filename.Printf( "imgDepthBuffer_blur%04d", *aDst_gl_texture );
//filename.Printf( "imgDepthBuffer_mul_%04d", *aDst_gl_texture ); //imgDepthBuffer.SaveAsPNG( filename );
//imgDepthBuffer.saveAsPNG( filename );
//imgDepthBufferAux.efxFilter( &imgDepthBuffer, 1.0, FILTER_BLUR); unsigned char *depthbufferRGBA = (unsigned char*) malloc( aTexture_size * aTexture_size * 4 );
//imgDepthBuffer.efxFilter( &imgDepthBufferAux, 1.0, FILTER_BLUR); unsigned char *pPixels = imgDepthBuffer.GetBuffer();
//filename.Printf( "imgDepthBuffer_mulblur_%04d", *aDst_gl_texture );
//imgDepthBuffer.saveAsPNG( filename );
imgDepthBuffer.invert();
//filename.Printf( "imgDepthBuffer_invert_%04d", *aDst_gl_texture );
//imgDepthBuffer.saveAsPNG( filename );
for(unsigned int i = 0; i < (aTexture_size * aTexture_size); i++) // Convert it to a RGBA buffer
for( unsigned int i = 0; i < (aTexture_size * aTexture_size); i++ )
{ {
depthbufferRGBA[i * 4 + 0] = 0; depthbufferRGBA[i * 4 + 0] = 0;
depthbufferRGBA[i * 4 + 1] = 0; depthbufferRGBA[i * 4 + 1] = 0;
depthbufferRGBA[i * 4 + 2] = 0; depthbufferRGBA[i * 4 + 2] = 0;
depthbufferRGBA[i * 4 + 3] = imgDepthBuffer.m_pixels[i]; depthbufferRGBA[i * 4 + 3] = 255 - pPixels[i]; // Store in alpha channel the inversion of the image
} }
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
...@@ -156,11 +149,14 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture, ...@@ -156,11 +149,14 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture,
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, aTexture_size, aTexture_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, depthbufferRGBA ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, aTexture_size, aTexture_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, depthbufferRGBA );
free( depthbufferRGBA ); free( depthbufferRGBA );
CheckGLError( __FILE__, __LINE__ );
} }
#define SHADOW_BOARD_SCALE 1.5f /// Scale factor to make a bigger BBox in order to blur the texture and dont have artifacts in the edges
#define SHADOW_BOUNDING_BOX_SCALE 1.25f
void EDA_3D_CANVAS::GenerateFakeShadowsTextures( wxString* aErrorMessages, bool aShowWarnings ) void EDA_3D_CANVAS::generateFakeShadowsTextures( wxString* aErrorMessages, bool aShowWarnings )
{ {
if( m_shadow_init == true ) if( m_shadow_init == true )
{ {
...@@ -170,6 +166,8 @@ void EDA_3D_CANVAS::GenerateFakeShadowsTextures( wxString* aErrorMessages, bool ...@@ -170,6 +166,8 @@ void EDA_3D_CANVAS::GenerateFakeShadowsTextures( wxString* aErrorMessages, bool
// Init info 3d parameters and create gl lists: // Init info 3d parameters and create gl lists:
CreateDrawGL_List( aErrorMessages, aShowWarnings ); CreateDrawGL_List( aErrorMessages, aShowWarnings );
DBG( unsigned strtime = GetRunningMicroSecs() );
m_shadow_init = true; m_shadow_init = true;
glClearColor( 0, 0, 0, 1 ); glClearColor( 0, 0, 0, 1 );
...@@ -177,45 +175,80 @@ void EDA_3D_CANVAS::GenerateFakeShadowsTextures( wxString* aErrorMessages, bool ...@@ -177,45 +175,80 @@ void EDA_3D_CANVAS::GenerateFakeShadowsTextures( wxString* aErrorMessages, bool
glMatrixMode( GL_PROJECTION ); glMatrixMode( GL_PROJECTION );
glLoadIdentity(); glLoadIdentity();
const double ZDIST_MAX = Millimeter2iu( 3.5 ) * GetPrm3DVisu().m_BiuTo3Dunits; const float zDistMax = Millimeter2iu( 3.5 ) * GetPrm3DVisu().m_BiuTo3Dunits;
glOrtho( -GetPrm3DVisu().m_BoardSize.x * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f, glOrtho( -GetPrm3DVisu().m_BoardSize.x * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f,
GetPrm3DVisu().m_BoardSize.x * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f, GetPrm3DVisu().m_BoardSize.x * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f,
-GetPrm3DVisu().m_BoardSize.y * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f, -GetPrm3DVisu().m_BoardSize.y * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f,
GetPrm3DVisu().m_BoardSize.y * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f, GetPrm3DVisu().m_BoardSize.y * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f,
0.0, ZDIST_MAX ); 0.0, zDistMax );
float zpos = GetPrm3DVisu().GetLayerZcoordBIU( F_Paste ) * GetPrm3DVisu().m_BiuTo3Dunits;
// Render FRONT shadow // Render FRONT shadow
glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_MODELVIEW );
glLoadIdentity(); glLoadIdentity();
glTranslatef( 0, 0, 0.03 ); glTranslatef( 0.0f, 0.0f, zpos );
glRotatef( 180, 0.0, 1.0, 0.0 ); glRotatef( 180.0f, 0.0f, 1.0f, 0.0f );
// move the board in order to draw it with its center at 0,0 3D coordinates
glTranslatef( -GetPrm3DVisu().m_BoardPos.x * GetPrm3DVisu().m_BiuTo3Dunits,
-GetPrm3DVisu().m_BoardPos.y * GetPrm3DVisu().m_BiuTo3Dunits,
0.0f );
Create_and_Render_Shadow_Buffer( &m_text_fake_shadow_front, 512, false, 1 ); create_and_render_shadow_buffer( &m_text_fake_shadow_front, 512, false, 1 );
zpos = GetPrm3DVisu().GetLayerZcoordBIU( B_Paste ) * GetPrm3DVisu().m_BiuTo3Dunits;
// Render BACK shadow // Render BACK shadow
glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_MODELVIEW );
glLoadIdentity(); glLoadIdentity();
glTranslatef( 0, 0, 0.03 ); glTranslatef( 0.0f, 0.0f, fabs( zpos ) );
///glRotatef( 0.0, 0.0, 1.0, 0.0 );
// move the board in order to draw it with its center at 0,0 3D coordinates
glTranslatef( -GetPrm3DVisu().m_BoardPos.x * GetPrm3DVisu().m_BiuTo3Dunits,
-GetPrm3DVisu().m_BoardPos.y * GetPrm3DVisu().m_BiuTo3Dunits,
0.0f );
create_and_render_shadow_buffer( &m_text_fake_shadow_back, 512, false, 1 );
Create_and_Render_Shadow_Buffer( &m_text_fake_shadow_back, 512, false, 1 );
// Render ALL BOARD shadow // Render ALL BOARD shadow
glMatrixMode( GL_PROJECTION ); glMatrixMode( GL_PROJECTION );
glLoadIdentity(); glLoadIdentity();
glOrtho( -GetPrm3DVisu().m_BoardSize.x * SHADOW_BOARD_SCALE * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f,
GetPrm3DVisu().m_BoardSize.x * SHADOW_BOARD_SCALE * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f, // Normalization scale to convert bouding box
-GetPrm3DVisu().m_BoardSize.y * SHADOW_BOARD_SCALE * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f, // to normalize 3D units between -1.0 and +1.0
GetPrm3DVisu().m_BoardSize.y * SHADOW_BOARD_SCALE * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f,
0.0, 6.0f * ZDIST_MAX ); S3D_VERTEX v = m_fastAABBox_Shadow.Max() - m_fastAABBox_Shadow.Min();
float BoundingBoxBoardiuTo3Dunits = 2.0f / glm::max( v.x, v.y );
//float zDistance = (m_lightPos.z * zDistMax) / sqrt( (m_lightPos.z - m_fastAABBox_Shadow.Min().z) );
float zDistance = (m_lightPos.z - m_fastAABBox_Shadow.Min().z) / 3.0f;
glOrtho( -v.x * BoundingBoxBoardiuTo3Dunits / 2.0f,
v.x * BoundingBoxBoardiuTo3Dunits / 2.0f,
-v.y * BoundingBoxBoardiuTo3Dunits / 2.0f,
v.y * BoundingBoxBoardiuTo3Dunits / 2.0f,
0.0f, zDistance );
glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_MODELVIEW );
glLoadIdentity(); glLoadIdentity();
glTranslatef( 0, 0, -0.4f );
glRotatef( 180.0, 0.0, 1.0, 0.0 );
Create_and_Render_Shadow_Buffer( &m_text_fake_shadow_board, 512, true, 5 ); // fits the bouding box to scale this size
glScalef( BoundingBoxBoardiuTo3Dunits, BoundingBoxBoardiuTo3Dunits, 1.0f );
// Place the eye in the lowerpoint of boudingbox and turn arround and look up to the model
glTranslatef( 0.0f, 0.0f, m_fastAABBox_Shadow.Min().z );
glRotatef( 180.0, 0.0f, 1.0f, 0.0f );
// move the bouding box in order to draw it with its center at 0,0 3D coordinates
glTranslatef( -(m_fastAABBox_Shadow.Min().x + v.x / 2.0f), -(m_fastAABBox_Shadow.Min().y + v.y / 2.0f), 0.0f );
create_and_render_shadow_buffer( &m_text_fake_shadow_board, 512, true, 10 );
DBG( printf( " generateFakeShadowsTextures total time %f ms\n", (double) (GetRunningMicroSecs() - strtime) / 1000.0 ) );
} }
...@@ -243,7 +276,7 @@ void EDA_3D_CANVAS::Redraw() ...@@ -243,7 +276,7 @@ void EDA_3D_CANVAS::Redraw()
if( isEnabled( FL_MODULE ) && isRealisticMode() && if( isEnabled( FL_MODULE ) && isRealisticMode() &&
isEnabled( FL_RENDER_SHADOWS ) ) isEnabled( FL_RENDER_SHADOWS ) )
{ {
GenerateFakeShadowsTextures( &errorMessages, showWarnings ); generateFakeShadowsTextures( &errorMessages, showWarnings );
} }
// *MUST* be called *after* SetCurrent( ): // *MUST* be called *after* SetCurrent( ):
...@@ -290,6 +323,7 @@ void EDA_3D_CANVAS::Redraw() ...@@ -290,6 +323,7 @@ void EDA_3D_CANVAS::Redraw()
glLoadIdentity(); glLoadIdentity();
#define MAX_VIEW_ANGLE 160.0 / 45.0 #define MAX_VIEW_ANGLE 160.0 / 45.0
if( GetPrm3DVisu().m_Zoom > MAX_VIEW_ANGLE ) if( GetPrm3DVisu().m_Zoom > MAX_VIEW_ANGLE )
GetPrm3DVisu().m_Zoom = MAX_VIEW_ANGLE; GetPrm3DVisu().m_Zoom = MAX_VIEW_ANGLE;
...@@ -309,14 +343,14 @@ void EDA_3D_CANVAS::Redraw() ...@@ -309,14 +343,14 @@ void EDA_3D_CANVAS::Redraw()
double ratio_HV = (double) size.x / size.y; double ratio_HV = (double) size.x / size.y;
// Initialize Projection Matrix for Perspective View // Initialize Projection Matrix for Perspective View
gluPerspective( 45.0 * GetPrm3DVisu().m_Zoom, ratio_HV, 1, 100 ); gluPerspective( 45.0f * GetPrm3DVisu().m_Zoom, ratio_HV, 1, 100 );
} }
// position viewer // position viewer
glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_MODELVIEW );
glLoadIdentity(); glLoadIdentity();
glTranslatef( 0.0F, 0.0F, -( m_ZBottom + m_ZTop) / 2 ); glTranslatef( 0.0f, 0.0f, -(m_ZBottom + m_ZTop) / 2.0f );
// Setup light sources: // Setup light sources:
SetLights(); SetLights();
...@@ -324,6 +358,7 @@ void EDA_3D_CANVAS::Redraw() ...@@ -324,6 +358,7 @@ void EDA_3D_CANVAS::Redraw()
CheckGLError( __FILE__, __LINE__ ); CheckGLError( __FILE__, __LINE__ );
glMatrixMode( GL_MODELVIEW ); // position viewer glMatrixMode( GL_MODELVIEW ); // position viewer
// transformations // transformations
GLfloat mat[4][4]; GLfloat mat[4][4];
...@@ -347,10 +382,7 @@ void EDA_3D_CANVAS::Redraw() ...@@ -347,10 +382,7 @@ void EDA_3D_CANVAS::Redraw()
// move the board in order to draw it with its center at 0,0 3D coordinates // move the board in order to draw it with its center at 0,0 3D coordinates
glTranslatef( -GetPrm3DVisu().m_BoardPos.x * GetPrm3DVisu().m_BiuTo3Dunits, glTranslatef( -GetPrm3DVisu().m_BoardPos.x * GetPrm3DVisu().m_BiuTo3Dunits,
-GetPrm3DVisu().m_BoardPos.y * GetPrm3DVisu().m_BiuTo3Dunits, -GetPrm3DVisu().m_BoardPos.y * GetPrm3DVisu().m_BiuTo3Dunits,
0.0F ); 0.0f );
// draw all objects in lists
// transparent objects should be drawn after opaque objects
if( isEnabled( FL_MODULE ) ) if( isEnabled( FL_MODULE ) )
{ {
...@@ -358,29 +390,42 @@ void EDA_3D_CANVAS::Redraw() ...@@ -358,29 +390,42 @@ void EDA_3D_CANVAS::Redraw()
CreateDrawGL_List( &errorMessages, showWarnings ); CreateDrawGL_List( &errorMessages, showWarnings );
} }
glEnable( GL_LIGHTING );
glEnable( GL_BLEND ); glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
if( isRealisticMode() && isEnabled( FL_RENDER_TEXTURES ) )
glEnable( GL_TEXTURE_2D );
else
glDisable( GL_TEXTURE_2D );
// Set material for the board
glEnable( GL_COLOR_MATERIAL );
SetOpenGlDefaultMaterial();
// Board Body
GLint shininess_value = 32;
glMateriali ( GL_FRONT_AND_BACK, GL_SHININESS, shininess_value );
if( isEnabled( FL_SHOW_BOARD_BODY ) ) if( isEnabled( FL_SHOW_BOARD_BODY ) )
{ {
glDisable( GL_LIGHTING );
if( m_glLists[GL_ID_BODY] ) if( m_glLists[GL_ID_BODY] )
{ {
glCallList( m_glLists[GL_ID_BODY] ); glCallList( m_glLists[GL_ID_BODY] );
} }
glEnable( GL_LIGHTING );
} }
glEnable( GL_COLOR_MATERIAL );
SetOpenGlDefaultMaterial();
glm::vec4 specular( GetPrm3DVisu().m_CopperColor.m_Red * 0.3,
GetPrm3DVisu().m_CopperColor.m_Green * 0.3,
GetPrm3DVisu().m_CopperColor.m_Blue * 0.3, 1.0 );
GLint shininess_value = 8;
// Board
shininess_value = 52;
glMateriali ( GL_FRONT_AND_BACK, GL_SHININESS, shininess_value ); glMateriali ( GL_FRONT_AND_BACK, GL_SHININESS, shininess_value );
glm::vec4 specular( GetPrm3DVisu().m_CopperColor.m_Red * 0.20f,
GetPrm3DVisu().m_CopperColor.m_Green * 0.20f,
GetPrm3DVisu().m_CopperColor.m_Blue * 0.20f, 1.0f );
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.x ); glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.x );
if( m_glLists[GL_ID_BOARD] ) if( m_glLists[GL_ID_BOARD] )
...@@ -388,17 +433,17 @@ void EDA_3D_CANVAS::Redraw() ...@@ -388,17 +433,17 @@ void EDA_3D_CANVAS::Redraw()
glCallList( m_glLists[GL_ID_BOARD] ); glCallList( m_glLists[GL_ID_BOARD] );
} }
if( isRealisticMode() && isEnabled( FL_RENDER_TEXTURES ) )
glEnable( GL_TEXTURE_2D );
else
glDisable( GL_TEXTURE_2D );
SetOpenGlDefaultMaterial(); // Tech layers
shininess_value = 32;
glMateriali ( GL_FRONT_AND_BACK, GL_SHININESS, shininess_value );
glm::vec4 specularTech( 0.0f, 0.0f, 0.0f, 1.0f );
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specularTech.x );
if( m_glLists[GL_ID_TECH_LAYERS] ) if( m_glLists[GL_ID_TECH_LAYERS] )
{ {
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glCallList( m_glLists[GL_ID_TECH_LAYERS] ); glCallList( m_glLists[GL_ID_TECH_LAYERS] );
} }
...@@ -410,7 +455,9 @@ void EDA_3D_CANVAS::Redraw() ...@@ -410,7 +455,9 @@ void EDA_3D_CANVAS::Redraw()
glCallList( m_glLists[GL_ID_AUX_LAYERS] ); glCallList( m_glLists[GL_ID_AUX_LAYERS] );
} }
// Draw Component Shadow // Draw Component Shadow
if( isEnabled( FL_MODULE ) && isRealisticMode() && if( isEnabled( FL_MODULE ) && isRealisticMode() &&
isEnabled( FL_RENDER_SHADOWS ) ) isEnabled( FL_RENDER_SHADOWS ) )
{ {
...@@ -419,7 +466,7 @@ void EDA_3D_CANVAS::Redraw() ...@@ -419,7 +466,7 @@ void EDA_3D_CANVAS::Redraw()
glEnable( GL_COLOR_MATERIAL ) ; glEnable( GL_COLOR_MATERIAL ) ;
SetOpenGlDefaultMaterial(); SetOpenGlDefaultMaterial();
glColor4f( 1.0, 1.0, 1.0, 1.0 ); glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
glEnable( GL_TEXTURE_2D ); glEnable( GL_TEXTURE_2D );
...@@ -437,19 +484,21 @@ void EDA_3D_CANVAS::Redraw() ...@@ -437,19 +484,21 @@ void EDA_3D_CANVAS::Redraw()
glBindTexture( GL_TEXTURE_2D, m_text_fake_shadow_back ); glBindTexture( GL_TEXTURE_2D, m_text_fake_shadow_back );
glCallList( m_glLists[GL_ID_SHADOW_BACK] ); glCallList( m_glLists[GL_ID_SHADOW_BACK] );
} }
glColor4f( 1.0, 1.0, 1.0, 1.0 ); glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
glEnable( GL_DEPTH_TEST ); glEnable( GL_DEPTH_TEST );
glDisable( GL_TEXTURE_2D ); glDisable( GL_TEXTURE_2D );
glDisable( GL_CULL_FACE ); glDisable( GL_CULL_FACE );
} }
glEnable(GL_COLOR_MATERIAL); glEnable( GL_COLOR_MATERIAL );
SetOpenGlDefaultMaterial(); SetOpenGlDefaultMaterial();
glDisable( GL_BLEND ); glDisable( GL_BLEND );
// Draw Solid Shapes // Draw Solid Shapes
if( isEnabled( FL_MODULE ) ) if( isEnabled( FL_MODULE ) )
{ {
if( ! m_glLists[GL_ID_3DSHAPES_SOLID_FRONT] ) if( ! m_glLists[GL_ID_3DSHAPES_SOLID_FRONT] )
...@@ -461,25 +510,29 @@ void EDA_3D_CANVAS::Redraw() ...@@ -461,25 +510,29 @@ void EDA_3D_CANVAS::Redraw()
glEnable( GL_BLEND ); glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
// Grid uses transparency: draw it after all objects // Grid uses transparency: draw it after all objects
if( isEnabled( FL_GRID ) && m_glLists[GL_ID_GRID] ) if( isEnabled( FL_GRID ) && m_glLists[GL_ID_GRID] )
glCallList( m_glLists[GL_ID_GRID] ); glCallList( m_glLists[GL_ID_GRID] );
// Draw Board Shadow // Draw Board Shadow
if( isEnabled( FL_MODULE ) && isRealisticMode() &&
isEnabled( FL_RENDER_SHADOWS ) ) if( isRealisticMode() && isEnabled( FL_RENDER_SHADOWS ) )
{ {
if( m_glLists[GL_ID_SHADOW_BOARD] ) if( m_glLists[GL_ID_SHADOW_BOARD] )
{ {
glEnable( GL_BLEND ); glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glColor4f( 1.0, 1.0, 1.0, 1.0 ); glColor4f( 1.0, 1.0, 1.0, 0.85f );
glEnable( GL_CULL_FACE ); glEnable( GL_CULL_FACE );
glDisable( GL_COLOR_MATERIAL ); glDisable( GL_COLOR_MATERIAL );
glEnable( GL_TEXTURE_2D ); glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, m_text_fake_shadow_board ); glBindTexture( GL_TEXTURE_2D, m_text_fake_shadow_board );
glCallList( m_glLists[GL_ID_SHADOW_BOARD] ); glCallList( m_glLists[GL_ID_SHADOW_BOARD] );
glDisable( GL_CULL_FACE ); glDisable( GL_CULL_FACE );
glDisable( GL_TEXTURE_2D );
} }
} }
...@@ -488,12 +541,23 @@ void EDA_3D_CANVAS::Redraw() ...@@ -488,12 +541,23 @@ void EDA_3D_CANVAS::Redraw()
// non transparent objects // non transparent objects
if( isEnabled( FL_MODULE ) && m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] ) if( isEnabled( FL_MODULE ) && m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] )
{ {
glDisable( GL_TEXTURE_2D );
glEnable( GL_BLEND ); glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glCallList( m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] ); glCallList( m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] );
} }
// Debug bounding boxes
/*
glDisable( GL_BLEND );
glDisable( GL_COLOR_MATERIAL );
glDisable( GL_LIGHTING );
glColor4f( 1.0f, 0.0f, 1.0f, 1.0f );
m_fastAABBox_Shadow.GLdebug();
glColor4f( 0.0f, 1.0f, 1.0f, 1.0f );
m_boardAABBox.GLdebug();
*/
SwapBuffers(); SwapBuffers();
if( !errorMessages.IsEmpty() ) if( !errorMessages.IsEmpty() )
...@@ -503,23 +567,16 @@ void EDA_3D_CANVAS::Redraw() ...@@ -503,23 +567,16 @@ void EDA_3D_CANVAS::Redraw()
} }
void EDA_3D_CANVAS::BuildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint aBoardList ) void EDA_3D_CANVAS::buildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint aBoardList )
{ {
// Use similar calculation as Grid limits, in 3D units // Board shadows are based on board dimension.
wxSize brd_size = getBoardSize();
wxPoint brd_center_pos = getBoardCenter();
float xsize = brd_size.x;
float ysize = brd_size.y;
float scale = GetPrm3DVisu().m_BiuTo3Dunits; float xmin = m_boardAABBox.Min().x;
float xmin = (brd_center_pos.x - xsize / 2.0) * scale; float xmax = m_boardAABBox.Max().x;
float xmax = (brd_center_pos.x + xsize / 2.0) * scale; float ymin = m_boardAABBox.Min().y;
float ymin = (brd_center_pos.y - ysize / 2.0) * scale; float ymax = m_boardAABBox.Max().y;
float ymax = (brd_center_pos.y + ysize / 2.0) * scale;
float zpos = GetPrm3DVisu().GetLayerZcoordBIU( F_Paste ); float zpos = GetPrm3DVisu().GetLayerZcoordBIU( F_Paste ) * GetPrm3DVisu().m_BiuTo3Dunits;
zpos *= GetPrm3DVisu().m_BiuTo3Dunits;
// Shadow FRONT // Shadow FRONT
glNewList( aFrontList, GL_COMPILE ); glNewList( aFrontList, GL_COMPILE );
...@@ -537,8 +594,7 @@ void EDA_3D_CANVAS::BuildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint ...@@ -537,8 +594,7 @@ void EDA_3D_CANVAS::BuildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint
// Shadow BACK // Shadow BACK
zpos = GetPrm3DVisu().GetLayerZcoordBIU( B_Paste ); zpos = GetPrm3DVisu().GetLayerZcoordBIU( B_Paste ) * GetPrm3DVisu().m_BiuTo3Dunits;
zpos *= GetPrm3DVisu().m_BiuTo3Dunits;
glNewList( aBacklist, GL_COMPILE ); glNewList( aBacklist, GL_COMPILE );
...@@ -553,33 +609,29 @@ void EDA_3D_CANVAS::BuildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint ...@@ -553,33 +609,29 @@ void EDA_3D_CANVAS::BuildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint
glEndList(); glEndList();
// Shadow BOARD // Shadow BOARD
xsize = brd_size.x * SHADOW_BOARD_SCALE;
ysize = brd_size.y * SHADOW_BOARD_SCALE;
scale = GetPrm3DVisu().m_BiuTo3Dunits;
xmin = (brd_center_pos.x - xsize / 2.0) * scale;
xmax = (brd_center_pos.x + xsize / 2.0) * scale;
ymin = (brd_center_pos.y - ysize / 2.0) * scale;
ymax = (brd_center_pos.y + ysize / 2.0) * scale;
// Floor shadow is based on axis alighned bounding box dimension
xmin = m_fastAABBox_Shadow.Min().x;
xmax = m_fastAABBox_Shadow.Max().x;
ymin = m_fastAABBox_Shadow.Min().y;
ymax = m_fastAABBox_Shadow.Max().y;
glNewList( aBoardList, GL_COMPILE ); glNewList( aBoardList, GL_COMPILE );
glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( F_Paste ) ); glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( F_Paste ) );
glBegin (GL_QUADS); glBegin (GL_QUADS);
glTexCoord2f( 1.0, 0.0 ); glVertex3f( xmin, ymin, zpos * 30.0); glTexCoord2f( 1.0, 0.0 ); glVertex3f( xmin, ymin, m_fastAABBox_Shadow.Min().z );
glTexCoord2f( 0.0, 0.0 ); glVertex3f( xmax, ymin, zpos * 30.0); glTexCoord2f( 0.0, 0.0 ); glVertex3f( xmax, ymin, m_fastAABBox_Shadow.Min().z );
glTexCoord2f( 0.0, 1.0 ); glVertex3f( xmax, ymax, zpos * 30.0); glTexCoord2f( 0.0, 1.0 ); glVertex3f( xmax, ymax, m_fastAABBox_Shadow.Min().z );
glTexCoord2f( 1.0, 1.0 ); glVertex3f( xmin, ymax, zpos * 30.0); glTexCoord2f( 1.0, 1.0 ); glVertex3f( xmin, ymax, m_fastAABBox_Shadow.Min().z );
glEnd(); glEnd();
glEndList(); glEndList();
} }
void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
wxString* aErrorMessages, bool aShowWarnings ) wxString* aErrorMessages, bool aShowWarnings )
{ {
BOARD* pcb = GetBoard(); BOARD* pcb = GetBoard();
...@@ -599,12 +651,12 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, ...@@ -599,12 +651,12 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
// ( We already used this trick in plot_board_layers.cpp, // ( We already used this trick in plot_board_layers.cpp,
// see PlotSolderMaskLayer() ) // see PlotSolderMaskLayer() )
const int segcountforcircle = 18; const int segcountforcircle = 18;
double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2) ); double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2.0) );
const int segcountLowQuality = 12; // segments to draw a circle with low quality const int segcountLowQuality = 8; // segments to draw a circle with low quality
// to reduce time calculations // to reduce time calculations
// for holes and items which do not need // for holes and items which do not need
// a fine representation // a fine representation
double correctionFactorLQ = 1.0 / cos( M_PI / (segcountLowQuality * 2) ); double correctionFactorLQ = 1.0 / cos( M_PI / (segcountLowQuality * 2.0) );
CPOLYGONS_LIST bufferPolys; CPOLYGONS_LIST bufferPolys;
bufferPolys.reserve( 200000 ); // Reserve for large board (tracks mainly) bufferPolys.reserve( 200000 ); // Reserve for large board (tracks mainly)
...@@ -640,7 +692,7 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, ...@@ -640,7 +692,7 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
glNewList( aBoardList, GL_COMPILE ); glNewList( aBoardList, GL_COMPILE );
for( unsigned i=0; i<DIM(cu_seq); ++i ) for( unsigned i=0; i < DIM( cu_seq ); ++i )
cu_seq[i] = ToLAYER_ID( B_Cu - i ); cu_seq[i] = ToLAYER_ID( B_Cu - i );
for( LSEQ cu = cu_set.Seq( cu_seq, DIM(cu_seq) ); cu; ++cu ) for( LSEQ cu = cu_set.Seq( cu_seq, DIM(cu_seq) ); cu; ++cu )
...@@ -713,8 +765,15 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, ...@@ -713,8 +765,15 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
D_PAD* pad = module->Pads(); D_PAD* pad = module->Pads();
for( ; pad; pad = pad->Next() ) for( ; pad; pad = pad->Next() )
{
// Calculate a factor to apply to segcount (bigger pad size -> more segments)
wxSize padSize = pad->GetSize();
int maxPadSize = glm::max( padSize.x, padSize.y );
float segFactor = (float)maxPadSize / (float)Millimeter2iu( 0.6 );
pad->BuildPadDrillShapePolygon( allLayerHoles, 0, pad->BuildPadDrillShapePolygon( allLayerHoles, 0,
segcountLowQuality ); (int)(segcountLowQuality * segFactor) );
}
} }
} }
...@@ -813,7 +872,8 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, ...@@ -813,7 +872,8 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
throughHolesListBuilt = true; throughHolesListBuilt = true;
} }
if ( !isEnabled( FL_SHOW_BOARD_BODY ) ) if ( !isEnabled( FL_SHOW_BOARD_BODY ) ||
isEnabled( FL_USE_COPPER_THICKNESS ) )
{ {
setGLCopperColor(); setGLCopperColor();
...@@ -823,14 +883,15 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, ...@@ -823,14 +883,15 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
const VIA *via = dynamic_cast<const VIA*>(track); const VIA *via = dynamic_cast<const VIA*>(track);
if( via ) if( via )
Draw3DViaHole( via ); draw3DViaHole( via );
} }
// Draw pads holes (vertical cylinders) // Draw pads holes (vertical cylinders)
for( const MODULE* module = pcb->m_Modules; module; module = module->Next() ) for( const MODULE* module = pcb->m_Modules; module; module = module->Next() )
{ {
for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() )
Draw3DPadHole( pad ); if( pad->GetAttribute () != PAD_HOLE_NOT_PLATED )
draw3DPadHole( pad );
} }
} }
...@@ -841,7 +902,7 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, ...@@ -841,7 +902,7 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
if( isRealisticMode() ) if( isRealisticMode() )
{ {
setGLEpoxyColor( 0.95 ); setGLEpoxyColor( 1.00 );
} }
else else
{ {
...@@ -862,10 +923,10 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, ...@@ -862,10 +923,10 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
// are drawn from zpos - copper_thickness/2 to zpos + copper_thickness // are drawn from zpos - copper_thickness/2 to zpos + copper_thickness
// therefore substrate position is copper_thickness/2 to // therefore substrate position is copper_thickness/2 to
// substrate_height - copper_thickness/2 // substrate_height - copper_thickness/2
zpos += (copper_thickness + epsilon) / 2.0; zpos += (copper_thickness + epsilon) / 2.0f;
board_thickness -= copper_thickness + epsilon; board_thickness -= copper_thickness + epsilon;
glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( F_Cu ) ); glNormal3f( 0.0f, 0.0f, Get3DLayer_Z_Orientation( F_Cu ) );
KI_POLYGON_SET currLayerPolyset; KI_POLYGON_SET currLayerPolyset;
KI_POLYGON_SET polysetHoles; KI_POLYGON_SET polysetHoles;
...@@ -883,7 +944,7 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, ...@@ -883,7 +944,7 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
if( bufferPcbOutlines.GetCornersCount() ) if( bufferPcbOutlines.GetCornersCount() )
{ {
Draw3D_SolidHorizontalPolyPolygons( bufferPcbOutlines, zpos + board_thickness/2.0, Draw3D_SolidHorizontalPolyPolygons( bufferPcbOutlines, zpos + board_thickness / 2.0,
board_thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures ); board_thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures );
} }
...@@ -891,7 +952,7 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, ...@@ -891,7 +952,7 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
} }
void EDA_3D_CANVAS::BuildTechLayers3DView( wxString* aErrorMessages, bool aShowWarnings ) void EDA_3D_CANVAS::buildTechLayers3DView( wxString* aErrorMessages, bool aShowWarnings )
{ {
BOARD* pcb = GetBoard(); BOARD* pcb = GetBoard();
bool useTextures = isRealisticMode() && isEnabled( FL_RENDER_TEXTURES ); bool useTextures = isRealisticMode() && isEnabled( FL_RENDER_TEXTURES );
...@@ -1016,7 +1077,7 @@ void EDA_3D_CANVAS::BuildTechLayers3DView( wxString* aErrorMessages, bool aShowW ...@@ -1016,7 +1077,7 @@ void EDA_3D_CANVAS::BuildTechLayers3DView( wxString* aErrorMessages, bool aShowW
if( !pad->IsOnLayer( layer ) ) if( !pad->IsOnLayer( layer ) )
continue; continue;
BuildPadShapeThickOutlineAsPolygon( pad, bufferPolys, buildPadShapeThickOutlineAsPolygon( pad, bufferPolys,
linewidth, segcountforcircle, correctionFactor ); linewidth, segcountforcircle, correctionFactor );
} }
} }
...@@ -1110,12 +1171,12 @@ void EDA_3D_CANVAS::BuildTechLayers3DView( wxString* aErrorMessages, bool aShowW ...@@ -1110,12 +1171,12 @@ void EDA_3D_CANVAS::BuildTechLayers3DView( wxString* aErrorMessages, bool aShowW
/** /**
* Function BuildBoard3DAuxLayers * Function buildBoard3DAuxLayers
* Called by CreateDrawGL_List() * Called by CreateDrawGL_List()
* Fills the OpenGL GL_ID_BOARD draw list with items * Fills the OpenGL GL_ID_BOARD draw list with items
* on aux layers only * on aux layers only
*/ */
void EDA_3D_CANVAS::BuildBoard3DAuxLayers() void EDA_3D_CANVAS::buildBoard3DAuxLayers()
{ {
const int segcountforcircle = 18; const int segcountforcircle = 18;
double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2) ); double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2) );
...@@ -1222,54 +1283,48 @@ void EDA_3D_CANVAS::CreateDrawGL_List( wxString* aErrorMessages, bool aShowWarni ...@@ -1222,54 +1283,48 @@ void EDA_3D_CANVAS::CreateDrawGL_List( wxString* aErrorMessages, bool aShowWarni
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
// Create axis gl list (if it is not shown, the list will be not called // Create axis gl list (if it is not shown, the list will be not called
Draw3DAxis(); draw3DAxis();
// Create grid gl list
if( ! m_glLists[GL_ID_GRID] )
{
m_glLists[GL_ID_GRID] = glGenLists( 1 );
glNewList( m_glLists[GL_ID_GRID], GL_COMPILE );
Draw3DGrid( GetPrm3DVisu().m_3D_Grid );
glEndList();
}
// Create Board full gl lists: // Create Board full gl lists:
// For testing purpose only, display calculation time to generate 3D data
// #define PRINT_CALCULATION_TIME
#ifdef PRINT_CALCULATION_TIME
unsigned strtime = GetRunningMicroSecs();
#endif
if( ! m_glLists[GL_ID_BOARD] ) if( ! m_glLists[GL_ID_BOARD] )
{ {
DBG( unsigned strtime = GetRunningMicroSecs() );
m_glLists[GL_ID_BOARD] = glGenLists( 1 ); m_glLists[GL_ID_BOARD] = glGenLists( 1 );
m_glLists[GL_ID_BODY] = glGenLists( 1 ); m_glLists[GL_ID_BODY] = glGenLists( 1 );
BuildBoard3DView(m_glLists[GL_ID_BOARD], m_glLists[GL_ID_BODY], aErrorMessages, aShowWarnings ); buildBoard3DView(m_glLists[GL_ID_BOARD], m_glLists[GL_ID_BODY], aErrorMessages, aShowWarnings );
CheckGLError( __FILE__, __LINE__ ); CheckGLError( __FILE__, __LINE__ );
DBG( printf( " buildBoard3DView total time %f ms\n", (double) (GetRunningMicroSecs() - strtime) / 1000.0 ) );
} }
if( ! m_glLists[GL_ID_TECH_LAYERS] ) if( ! m_glLists[GL_ID_TECH_LAYERS] )
{ {
DBG( unsigned strtime = GetRunningMicroSecs() );
m_glLists[GL_ID_TECH_LAYERS] = glGenLists( 1 ); m_glLists[GL_ID_TECH_LAYERS] = glGenLists( 1 );
glNewList( m_glLists[GL_ID_TECH_LAYERS], GL_COMPILE ); glNewList( m_glLists[GL_ID_TECH_LAYERS], GL_COMPILE );
// when calling BuildTechLayers3DView, // when calling BuildTechLayers3DView,
// do not show warnings, which are the same as BuildBoard3DView // do not show warnings, which are the same as buildBoard3DView
BuildTechLayers3DView( aErrorMessages, false ); buildTechLayers3DView( aErrorMessages, false );
glEndList(); glEndList();
CheckGLError( __FILE__, __LINE__ ); CheckGLError( __FILE__, __LINE__ );
DBG( printf( " buildTechLayers3DView total time %f ms\n", (double) (GetRunningMicroSecs() - strtime) / 1000.0 ) );
} }
if( ! m_glLists[GL_ID_AUX_LAYERS] ) if( ! m_glLists[GL_ID_AUX_LAYERS] )
{ {
DBG( unsigned strtime = GetRunningMicroSecs() );
m_glLists[GL_ID_AUX_LAYERS] = glGenLists( 1 ); m_glLists[GL_ID_AUX_LAYERS] = glGenLists( 1 );
glNewList( m_glLists[GL_ID_AUX_LAYERS], GL_COMPILE ); glNewList( m_glLists[GL_ID_AUX_LAYERS], GL_COMPILE );
BuildBoard3DAuxLayers(); buildBoard3DAuxLayers();
glEndList(); glEndList();
CheckGLError( __FILE__, __LINE__ ); CheckGLError( __FILE__, __LINE__ );
DBG( printf( " buildBoard3DAuxLayers total time %f ms\n", (double) (GetRunningMicroSecs() - strtime) / 1000.0 ) );
} }
// draw modules 3D shapes // draw modules 3D shapes
...@@ -1289,58 +1344,130 @@ void EDA_3D_CANVAS::CreateDrawGL_List( wxString* aErrorMessages, bool aShowWarni ...@@ -1289,58 +1344,130 @@ void EDA_3D_CANVAS::CreateDrawGL_List( wxString* aErrorMessages, bool aShowWarni
else else
m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] = 0; m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] = 0;
BuildFootprintShape3DList( m_glLists[GL_ID_3DSHAPES_SOLID_FRONT], buildFootprintShape3DList( m_glLists[GL_ID_3DSHAPES_SOLID_FRONT],
m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT], false ); m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] );
CheckGLError( __FILE__, __LINE__ ); CheckGLError( __FILE__, __LINE__ );
}
calcBBox();
// Create grid gl list
if( ! m_glLists[GL_ID_GRID] )
{
m_glLists[GL_ID_GRID] = glGenLists( 1 );
glNewList( m_glLists[GL_ID_GRID], GL_COMPILE );
draw3DGrid( GetPrm3DVisu().m_3D_Grid );
glEndList();
}
if( !m_glLists[GL_ID_SHADOW_FRONT] )
m_glLists[GL_ID_SHADOW_FRONT] = glGenLists( 1 ); m_glLists[GL_ID_SHADOW_FRONT] = glGenLists( 1 );
if( !m_glLists[GL_ID_SHADOW_BACK] )
m_glLists[GL_ID_SHADOW_BACK] = glGenLists( 1 ); m_glLists[GL_ID_SHADOW_BACK] = glGenLists( 1 );
if( !m_glLists[GL_ID_SHADOW_BOARD] )
m_glLists[GL_ID_SHADOW_BOARD] = glGenLists( 1 ); m_glLists[GL_ID_SHADOW_BOARD] = glGenLists( 1 );
BuildShadowList( m_glLists[GL_ID_SHADOW_FRONT], m_glLists[GL_ID_SHADOW_BACK], buildShadowList( m_glLists[GL_ID_SHADOW_FRONT],
m_glLists[GL_ID_SHADOW_BOARD]); m_glLists[GL_ID_SHADOW_BACK],
m_glLists[GL_ID_SHADOW_BOARD] );
CheckGLError( __FILE__, __LINE__ ); CheckGLError( __FILE__, __LINE__ );
}
void EDA_3D_CANVAS::calcBBox()
{
BOARD* pcb = GetBoard();
m_fastAABBox.Reset();
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
{
CBBOX tmpFastAABBox;
// Compute the transformation matrix for this module based on translation, rotation and orientation.
float zpos = GetPrm3DVisu().GetModulesZcoord3DIU( module->IsFlipped() );
wxPoint pos = module->GetPosition();
glm::mat4 fullTransformMatrix;
fullTransformMatrix = glm::translate( glm::mat4(), S3D_VERTEX( (float)(pos.x * GetPrm3DVisu().m_BiuTo3Dunits),
(float)(-pos.y * GetPrm3DVisu().m_BiuTo3Dunits),
zpos ) );
if( module->GetOrientation() )
fullTransformMatrix = glm::rotate( fullTransformMatrix,
(float)(module->GetOrientation() / 10.0f),
S3D_VERTEX( 0.0f, 0.0f, 1.0f ) );
if( module->IsFlipped() )
{
fullTransformMatrix = glm::rotate( fullTransformMatrix, 180.0f, S3D_VERTEX( 0.0f, 1.0f, 0.0f ) );
fullTransformMatrix = glm::rotate( fullTransformMatrix, 180.0f, S3D_VERTEX( 0.0f, 0.0f, 1.0f ) );
} }
// Compute a union bounding box for all the shapes of the model
#ifdef PRINT_CALCULATION_TIME S3D_MASTER* shape3D = module->Models();
unsigned endtime = GetRunningMicroSecs();
wxString msg; for( ; shape3D; shape3D = shape3D->Next() )
msg.Printf( "Built data %.1f ms", (double) (endtime - strtime) / 1000 ); {
Parent()->SetStatusText( msg, 0 ); if( shape3D->Is3DType( S3D_MASTER::FILE3D_VRML ) )
#endif tmpFastAABBox.Union( shape3D->getFastAABBox() );
}
tmpFastAABBox.ApplyTransformationAA( fullTransformMatrix );
m_fastAABBox.Union( tmpFastAABBox );
}
// Create a board bounding box based on board size
wxSize brd_size = getBoardSize();
wxPoint brd_center_pos = getBoardCenter();
float xsize = brd_size.x;
float ysize = brd_size.y;
float scale = GetPrm3DVisu().m_BiuTo3Dunits;
float xmin = (brd_center_pos.x - xsize / 2.0) * scale;
float xmax = (brd_center_pos.x + xsize / 2.0) * scale;
float ymin = (brd_center_pos.y - ysize / 2.0) * scale;
float ymax = (brd_center_pos.y + ysize / 2.0) * scale;
float zmin = GetPrm3DVisu().GetLayerZcoordBIU( B_Adhes ) * scale;
float zmax = GetPrm3DVisu().GetLayerZcoordBIU( F_Adhes ) * scale;
m_boardAABBox = CBBOX( S3D_VERTEX(xmin, ymin, zmin),
S3D_VERTEX(xmax, ymax, zmax) );
// Add BB board with BB models and scale it a bit
m_fastAABBox.Union( m_boardAABBox );
m_fastAABBox_Shadow = m_fastAABBox;
m_fastAABBox_Shadow.Scale( SHADOW_BOUNDING_BOX_SCALE );
} }
void EDA_3D_CANVAS::BuildFootprintShape3DList( GLuint aOpaqueList, void EDA_3D_CANVAS::buildFootprintShape3DList( GLuint aOpaqueList,
GLuint aTransparentList, bool aSideToLoad) GLuint aTransparentList )
{ {
#ifdef PRINT_CALCULATION_TIME DBG( unsigned strtime = GetRunningMicroSecs() );
unsigned strtime = GetRunningMicroSecs();
#endif // clean the parser list if it have any already loaded files
// This lists are used to just load once of each filename model m_model_parsers_list.clear();
std::vector<S3D_MODEL_PARSER *> model_parsers_list; m_model_filename_list.clear();
std::vector<wxString> model_filename_list;
BOARD* pcb = GetBoard(); BOARD* pcb = GetBoard();
for( MODULE* module = pcb->m_Modules; module; module = module->Next() ) for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
Read3DComponentShape( module, model_parsers_list, model_filename_list ); read3DComponentShape( module );
#ifdef PRINT_CALCULATION_TIME DBG( printf( " read3DComponentShape total time %f ms\n", (double) (GetRunningMicroSecs() - strtime) / 1000.0 ) );
{
unsigned endtime = GetRunningMicroSecs();
wxString msg;
msg.Printf( " Read3DComponentShape total time %.1f ms", (double) (endtime - strtime) / 1000 );
DBG( printf( "%s\n", (const char*)msg.c_str() ) );
}
#endif
#ifdef PRINT_CALCULATION_TIME DBG( strtime = GetRunningMicroSecs() );
strtime = GetRunningMicroSecs();
#endif
bool useMaterial = g_Parm_3D_Visu.GetFlag( FL_RENDER_MATERIAL ); bool useMaterial = g_Parm_3D_Visu.GetFlag( FL_RENDER_MATERIAL );
...@@ -1354,8 +1481,9 @@ void EDA_3D_CANVAS::BuildFootprintShape3DList( GLuint aOpaqueList, ...@@ -1354,8 +1481,9 @@ void EDA_3D_CANVAS::BuildFootprintShape3DList( GLuint aOpaqueList,
bool loadOpaqueObjects = true; bool loadOpaqueObjects = true;
for( MODULE* module = pcb->m_Modules; module; module = module->Next() ) for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
Render3DComponentShape( module, loadOpaqueObjects, render3DComponentShape( module, loadOpaqueObjects,
!loadOpaqueObjects, aSideToLoad ); !loadOpaqueObjects );
glEndList(); glEndList();
...@@ -1363,8 +1491,8 @@ void EDA_3D_CANVAS::BuildFootprintShape3DList( GLuint aOpaqueList, ...@@ -1363,8 +1491,8 @@ void EDA_3D_CANVAS::BuildFootprintShape3DList( GLuint aOpaqueList,
bool loadTransparentObjects = true; bool loadTransparentObjects = true;
for( MODULE* module = pcb->m_Modules; module; module = module->Next() ) for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
Render3DComponentShape( module, !loadTransparentObjects, render3DComponentShape( module, !loadTransparentObjects,
loadTransparentObjects, aSideToLoad ); loadTransparentObjects );
glEndList(); glEndList();
} }
...@@ -1374,25 +1502,18 @@ void EDA_3D_CANVAS::BuildFootprintShape3DList( GLuint aOpaqueList, ...@@ -1374,25 +1502,18 @@ void EDA_3D_CANVAS::BuildFootprintShape3DList( GLuint aOpaqueList,
glNewList( aOpaqueList, GL_COMPILE ); glNewList( aOpaqueList, GL_COMPILE );
for( MODULE* module = pcb->m_Modules; module; module = module->Next() ) for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
Render3DComponentShape( module, false, false, aSideToLoad ); render3DComponentShape( module, false, false );
glEndList(); glEndList();
} }
#ifdef PRINT_CALCULATION_TIME DBG( printf( " render3DComponentShape total time %f ms\n", (double) (GetRunningMicroSecs() - strtime) / 1000.0 ) );
{
unsigned endtime = GetRunningMicroSecs();
wxString msg;
msg.Printf( " Render3DComponentShape total time %.1f ms", (double) (endtime - strtime) / 1000 );
DBG( printf( "%s\n", (const char*)msg.c_str() ) );
}
#endif
} }
bool EDA_3D_CANVAS::Read3DComponentShape( MODULE* module, bool EDA_3D_CANVAS::read3DComponentShape( MODULE* module )
std::vector<S3D_MODEL_PARSER *>& model_parsers_list,
std::vector<wxString>& model_filename_list )
{ {
if( module )
{
S3D_MASTER* shape3D = module->Models(); S3D_MASTER* shape3D = module->Models();
for( ; shape3D; shape3D = shape3D->Next() ) for( ; shape3D; shape3D = shape3D->Next() )
...@@ -1405,9 +1526,9 @@ bool EDA_3D_CANVAS::Read3DComponentShape( MODULE* module, ...@@ -1405,9 +1526,9 @@ bool EDA_3D_CANVAS::Read3DComponentShape( MODULE* module,
wxString shape_filename = shape3D->GetShape3DFullFilename(); wxString shape_filename = shape3D->GetShape3DFullFilename();
// Search for already loaded files // Search for already loaded files
for( i = 0; i < model_filename_list.size(); i++ ) for( i = 0; i < m_model_filename_list.size(); i++ )
{ {
if( shape_filename.Cmp(model_filename_list[i]) == 0 ) if( shape_filename.Cmp(m_model_filename_list[i]) == 0 )
{ {
found = true; found = true;
break; break;
...@@ -1416,14 +1537,25 @@ bool EDA_3D_CANVAS::Read3DComponentShape( MODULE* module, ...@@ -1416,14 +1537,25 @@ bool EDA_3D_CANVAS::Read3DComponentShape( MODULE* module,
if( found == false ) if( found == false )
{ {
shape3D->ReadData(); // Create a new parser
model_filename_list.push_back( shape_filename ); S3D_MODEL_PARSER *newParser = S3D_MODEL_PARSER::Create( shape3D, shape3D->GetShape3DExtension() );
model_parsers_list.push_back( shape3D->m_parser );
if( newParser )
{
// Read file
if( shape3D->ReadData( newParser ) == 0 )
{
// Store this couple filename / parsed file
m_model_filename_list.push_back( shape_filename );
m_model_parsers_list.push_back( newParser );
}
}
} }
else else
{ {
DBG( printf( " Read3DComponentShape reusing %s\n", (const char*)shape_filename.c_str() ) ); // Reusing file
shape3D->m_parser = model_parsers_list[i]; shape3D->m_parser = m_model_parsers_list[i];
}
} }
} }
} }
...@@ -1432,12 +1564,10 @@ bool EDA_3D_CANVAS::Read3DComponentShape( MODULE* module, ...@@ -1432,12 +1564,10 @@ bool EDA_3D_CANVAS::Read3DComponentShape( MODULE* module,
} }
void EDA_3D_CANVAS::Render3DComponentShape( MODULE* module, void EDA_3D_CANVAS::render3DComponentShape( MODULE* module,
bool aIsRenderingJustNonTransparentObjects, bool aIsRenderingJustNonTransparentObjects,
bool aIsRenderingJustTransparentObjects, bool aIsRenderingJustTransparentObjects )
bool aSideToLoad )
{ {
// Read from disk and draws the footprint 3D shapes if exists
double zpos = GetPrm3DVisu().GetModulesZcoord3DIU( module->IsFlipped() ); double zpos = GetPrm3DVisu().GetModulesZcoord3DIU( module->IsFlipped() );
glPushMatrix(); glPushMatrix();
...@@ -1449,12 +1579,12 @@ void EDA_3D_CANVAS::Render3DComponentShape( MODULE* module, ...@@ -1449,12 +1579,12 @@ void EDA_3D_CANVAS::Render3DComponentShape( MODULE* module,
zpos ); zpos );
if( module->GetOrientation() ) if( module->GetOrientation() )
glRotatef( (double) module->GetOrientation() / 10.0, 0.0, 0.0, 1.0 ); glRotatef( (double) module->GetOrientation() / 10.0, 0.0f, 0.0f, 1.0f );
if( module->IsFlipped() ) if( module->IsFlipped() )
{ {
glRotatef( 180.0, 0.0, 1.0, 0.0 ); glRotatef( 180.0f, 0.0f, 1.0f, 0.0f );
glRotatef( 180.0, 0.0, 0.0, 1.0 ); glRotatef( 180.0f, 0.0f, 0.0f, 1.0f );
} }
S3D_MASTER* shape3D = module->Models(); S3D_MASTER* shape3D = module->Models();
...@@ -1464,9 +1594,27 @@ void EDA_3D_CANVAS::Render3DComponentShape( MODULE* module, ...@@ -1464,9 +1594,27 @@ void EDA_3D_CANVAS::Render3DComponentShape( MODULE* module,
if( shape3D->Is3DType( S3D_MASTER::FILE3D_VRML ) ) if( shape3D->Is3DType( S3D_MASTER::FILE3D_VRML ) )
{ {
glPushMatrix(); glPushMatrix();
shape3D->Render( aIsRenderingJustNonTransparentObjects, shape3D->Render( aIsRenderingJustNonTransparentObjects,
aIsRenderingJustTransparentObjects ); aIsRenderingJustTransparentObjects );
if( isEnabled( FL_RENDER_SHOW_MODEL_BBOX ) )
{
// Set the alpha current color to opaque
float currentColor[4];
glGetFloatv( GL_CURRENT_COLOR,currentColor );
currentColor[3] = 1.0f;
glColor4fv( currentColor );
CBBOX thisBBox = shape3D->getBBox();
thisBBox.GLdebug();
}
glPopMatrix(); glPopMatrix();
// Debug AABBox
//thisBBox = shape3D->getfastAABBox();
//thisBBox.GLdebug();
} }
} }
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#include <modelparsers.h> #include <modelparsers.h>
// Number of segments to approximate a circle by segments // Number of segments to approximate a circle by segments
#define SEGM_PER_CIRCLE 16 #define SEGM_PER_CIRCLE 24
#ifndef CALLBACK #ifndef CALLBACK
#define CALLBACK #define CALLBACK
...@@ -57,12 +57,12 @@ static void CALLBACK tessCPolyPt2Vertex( const GLvoid* data ); ...@@ -57,12 +57,12 @@ static void CALLBACK tessCPolyPt2Vertex( const GLvoid* data );
// 2 helper functions to set the current normal vector for gle items // 2 helper functions to set the current normal vector for gle items
static inline void SetNormalZpos() static inline void SetNormalZpos()
{ {
//glNormal3f( 0.0, 0.0, 1.0 ); glNormal3f( 0.0, 0.0, 1.0 );
} }
static inline void SetNormalZneg() static inline void SetNormalZneg()
{ {
//glNormal3f( 0.0, 0.0, -1.0 ); glNormal3f( 0.0, 0.0, -1.0 );
} }
void TransfertToGLlist( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUnits ); void TransfertToGLlist( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUnits );
...@@ -203,6 +203,7 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList, ...@@ -203,6 +203,7 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
} }
// https://www.opengl.org/sdk/docs/man2/xhtml/gluTessNormal.xml // https://www.opengl.org/sdk/docs/man2/xhtml/gluTessNormal.xml
if( !aThickness )
gluTessNormal( tess, 0.0, 0.0, 0.0 ); gluTessNormal( tess, 0.0, 0.0, 0.0 );
...@@ -231,6 +232,7 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList, ...@@ -231,6 +232,7 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
s_currentZpos = zpos; // for Tess callback functions s_currentZpos = zpos; // for Tess callback functions
v_data[2] = zpos; v_data[2] = zpos;
// Set normal toward negative Z axis, for a solid object on bottom side // Set normal toward negative Z axis, for a solid object on bottom side
if( aThickness )
SetNormalZneg(); SetNormalZneg();
} }
...@@ -248,7 +250,7 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList, ...@@ -248,7 +250,7 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
} }
// Build the 3D data : vertical side // Build the 3D data : vertical side
Draw3D_VerticalPolygonalCylinder( polylist, aThickness, aZpos - (aThickness / 2.0), false, aBiuTo3DUnits ); Draw3D_VerticalPolygonalCylinder( polylist, aThickness, aZpos - (aThickness / 2.0), true, aBiuTo3DUnits );
} }
...@@ -292,9 +294,11 @@ void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius, ...@@ -292,9 +294,11 @@ void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius,
if( aHeight ) if( aHeight )
{ {
// Draw the vertical outer side // Draw the vertical outer side
Draw3D_VerticalPolygonalCylinder( outer_cornerBuffer, Draw3D_VerticalPolygonalCylinder( outer_cornerBuffer,
aHeight, aZpos, false, aBiuTo3DUnits ); aHeight, aZpos, false, aBiuTo3DUnits );
if( aThickness ) if( aThickness )
// Draws the vertical inner side (hole) // Draws the vertical inner side (hole)
Draw3D_VerticalPolygonalCylinder( inner_cornerBuffer, Draw3D_VerticalPolygonalCylinder( inner_cornerBuffer,
......
...@@ -181,7 +181,7 @@ void EDA_3D_CANVAS::setGLTechLayersColor( LAYER_NUM aLayer ) ...@@ -181,7 +181,7 @@ void EDA_3D_CANVAS::setGLTechLayersColor( LAYER_NUM aLayer )
} }
} }
void EDA_3D_CANVAS::Draw3DAxis() void EDA_3D_CANVAS::draw3DAxis()
{ {
if( ! m_glLists[GL_ID_AXIS] ) if( ! m_glLists[GL_ID_AXIS] )
{ {
...@@ -207,7 +207,7 @@ void EDA_3D_CANVAS::Draw3DAxis() ...@@ -207,7 +207,7 @@ void EDA_3D_CANVAS::Draw3DAxis()
// draw a 3D grid: an horizontal grid (XY plane and Z = 0, // draw a 3D grid: an horizontal grid (XY plane and Z = 0,
// and a vertical grid (XZ plane and Y = 0) // and a vertical grid (XZ plane and Y = 0)
void EDA_3D_CANVAS::Draw3DGrid( double aGriSizeMM ) void EDA_3D_CANVAS::draw3DGrid( double aGriSizeMM )
{ {
double zpos = 0.0; double zpos = 0.0;
EDA_COLOR_T gridcolor = DARKGRAY; // Color of grid lines EDA_COLOR_T gridcolor = DARKGRAY; // Color of grid lines
...@@ -343,7 +343,7 @@ void EDA_3D_CANVAS::Draw3DGrid( double aGriSizeMM ) ...@@ -343,7 +343,7 @@ void EDA_3D_CANVAS::Draw3DGrid( double aGriSizeMM )
// Draw 3D pads. // Draw 3D pads.
void EDA_3D_CANVAS::Draw3DPadHole( const D_PAD* aPad ) void EDA_3D_CANVAS::draw3DPadHole( const D_PAD* aPad )
{ {
// Draw the pad hole // Draw the pad hole
wxSize drillsize = aPad->GetDrillSize(); wxSize drillsize = aPad->GetDrillSize();
...@@ -363,13 +363,13 @@ void EDA_3D_CANVAS::Draw3DPadHole( const D_PAD* aPad ) ...@@ -363,13 +363,13 @@ void EDA_3D_CANVAS::Draw3DPadHole( const D_PAD* aPad )
else else
SetGLColor( DARKGRAY ); SetGLColor( DARKGRAY );
int holeZpoz = GetPrm3DVisu().GetLayerZcoordBIU( B_Cu ) + thickness / 2; int holeZpoz = GetPrm3DVisu().GetLayerZcoordBIU( B_Cu ) - thickness / 2;
int holeHeight = height - thickness; int holeHeight = height + thickness;
if( drillsize.x == drillsize.y ) // usual round hole if( drillsize.x == drillsize.y ) // usual round hole
{ {
Draw3D_ZaxisCylinder( aPad->GetPosition(), Draw3D_ZaxisCylinder( aPad->GetPosition(),
(drillsize.x + thickness) / 2, holeHeight, (drillsize.x + thickness / 2) / 2, holeHeight,
thickness, holeZpoz, GetPrm3DVisu().m_BiuTo3Dunits ); thickness, holeZpoz, GetPrm3DVisu().m_BiuTo3Dunits );
} }
else // Oblong hole else // Oblong hole
...@@ -401,11 +401,11 @@ void EDA_3D_CANVAS::Draw3DPadHole( const D_PAD* aPad ) ...@@ -401,11 +401,11 @@ void EDA_3D_CANVAS::Draw3DPadHole( const D_PAD* aPad )
} }
void EDA_3D_CANVAS::Draw3DViaHole( const VIA* aVia ) void EDA_3D_CANVAS::draw3DViaHole( const VIA* aVia )
{ {
LAYER_ID top_layer, bottom_layer; LAYER_ID top_layer, bottom_layer;
int inner_radius = aVia->GetDrillValue() / 2;
int thickness = GetPrm3DVisu().GetCopperThicknessBIU(); int thickness = GetPrm3DVisu().GetCopperThicknessBIU();
int inner_radius = (int)((float)aVia->GetDrillValue() * 1.01f) / 2.0f; // This add a bit more in order to correct a draw artifact while using tickness
aVia->LayerPair( &top_layer, &bottom_layer ); aVia->LayerPair( &top_layer, &bottom_layer );
...@@ -419,17 +419,17 @@ void EDA_3D_CANVAS::Draw3DViaHole( const VIA* aVia ) ...@@ -419,17 +419,17 @@ void EDA_3D_CANVAS::Draw3DViaHole( const VIA* aVia )
} }
int height = GetPrm3DVisu().GetLayerZcoordBIU( top_layer ) - int height = GetPrm3DVisu().GetLayerZcoordBIU( top_layer ) -
GetPrm3DVisu().GetLayerZcoordBIU( bottom_layer ) - thickness; GetPrm3DVisu().GetLayerZcoordBIU( bottom_layer ) + thickness;
int zpos = GetPrm3DVisu().GetLayerZcoordBIU( bottom_layer ) + thickness / 2; int zpos = GetPrm3DVisu().GetLayerZcoordBIU( bottom_layer ) - thickness / 2;
Draw3D_ZaxisCylinder( aVia->GetStart(), inner_radius + thickness / 2, height, Draw3D_ZaxisCylinder( aVia->GetStart(), inner_radius, height,
thickness, zpos, GetPrm3DVisu().m_BiuTo3Dunits ); thickness, zpos, GetPrm3DVisu().m_BiuTo3Dunits );
} }
/* Build a pad outline as non filled polygon, to draw pads on silkscreen layer /* Build a pad outline as non filled polygon, to draw pads on silkscreen layer
* Used only to draw pads outlines on silkscreen layers. * Used only to draw pads outlines on silkscreen layers.
*/ */
void EDA_3D_CANVAS::BuildPadShapeThickOutlineAsPolygon( const D_PAD* aPad, void EDA_3D_CANVAS::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
CPOLYGONS_LIST& aCornerBuffer, CPOLYGONS_LIST& aCornerBuffer,
int aWidth, int aWidth,
int aCircleToSegmentsCount, int aCircleToSegmentsCount,
......
...@@ -57,6 +57,7 @@ static const wxChar keyRenderTextures[] = wxT( "Render_Textures" ); ...@@ -57,6 +57,7 @@ static const wxChar keyRenderTextures[] = wxT( "Render_Textures" );
static const wxChar keyRenderSmoothNormals[] = wxT( "Render_Smooth_Normals" ); static const wxChar keyRenderSmoothNormals[] = wxT( "Render_Smooth_Normals" );
static const wxChar keyRenderUseModelNormals[] =wxT( "Render_Use_Model_Normals" ); static const wxChar keyRenderUseModelNormals[] =wxT( "Render_Use_Model_Normals" );
static const wxChar keyRenderMaterial[] = wxT( "Render_Material" ); static const wxChar keyRenderMaterial[] = wxT( "Render_Material" );
static const wxChar keyRenderShowModelBBox[] = wxT( "Render_ShowModelBoudingBoxes" );
static const wxChar keyShowAxis[] = wxT( "ShowAxis" ); static const wxChar keyShowAxis[] = wxT( "ShowAxis" );
static const wxChar keyShowGrid[] = wxT( "ShowGrid3D" ); static const wxChar keyShowGrid[] = wxT( "ShowGrid3D" );
...@@ -257,6 +258,9 @@ void EDA_3D_FRAME::LoadSettings( wxConfigBase* aCfg ) ...@@ -257,6 +258,9 @@ void EDA_3D_FRAME::LoadSettings( wxConfigBase* aCfg )
aCfg->Read( keyRenderMaterial, &tmp, false ); aCfg->Read( keyRenderMaterial, &tmp, false );
prms.SetFlag( FL_RENDER_MATERIAL, tmp ); prms.SetFlag( FL_RENDER_MATERIAL, tmp );
aCfg->Read( keyRenderShowModelBBox, &tmp, false );
prms.SetFlag( FL_RENDER_SHOW_MODEL_BBOX, tmp );
aCfg->Read( keyShowAxis, &tmp, true ); aCfg->Read( keyShowAxis, &tmp, true );
prms.SetFlag( FL_AXIS, tmp ); prms.SetFlag( FL_AXIS, tmp );
...@@ -319,6 +323,7 @@ void EDA_3D_FRAME::SaveSettings( wxConfigBase* aCfg ) ...@@ -319,6 +323,7 @@ void EDA_3D_FRAME::SaveSettings( wxConfigBase* aCfg )
aCfg->Write( keyRenderSmoothNormals, prms.GetFlag( FL_RENDER_SMOOTH_NORMALS ) ); aCfg->Write( keyRenderSmoothNormals, prms.GetFlag( FL_RENDER_SMOOTH_NORMALS ) );
aCfg->Write( keyRenderUseModelNormals, prms.GetFlag( FL_RENDER_USE_MODEL_NORMALS ) ); aCfg->Write( keyRenderUseModelNormals, prms.GetFlag( FL_RENDER_USE_MODEL_NORMALS ) );
aCfg->Write( keyRenderMaterial, prms.GetFlag( FL_RENDER_MATERIAL ) ); aCfg->Write( keyRenderMaterial, prms.GetFlag( FL_RENDER_MATERIAL ) );
aCfg->Write( keyRenderShowModelBBox, prms.GetFlag( FL_RENDER_SHOW_MODEL_BBOX ) );
aCfg->Write( keyShowAxis, prms.GetFlag( FL_AXIS ) ); aCfg->Write( keyShowAxis, prms.GetFlag( FL_AXIS ) );
aCfg->Write( keyShowGrid, prms.GetFlag( FL_GRID ) ); aCfg->Write( keyShowGrid, prms.GetFlag( FL_GRID ) );
...@@ -509,6 +514,11 @@ void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event ) ...@@ -509,6 +514,11 @@ void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event )
NewDisplay(); NewDisplay();
return; return;
case ID_MENU3D_FL_RENDER_SHOW_MODEL_BBOX:
GetPrm3DVisu().SetFlag( FL_RENDER_SHOW_MODEL_BBOX, isChecked );
NewDisplay();
return;
case ID_MENU3D_SHOW_BOARD_BODY: case ID_MENU3D_SHOW_BOARD_BODY:
GetPrm3DVisu().SetFlag( FL_SHOW_BOARD_BODY, isChecked ); GetPrm3DVisu().SetFlag( FL_SHOW_BOARD_BODY, isChecked );
NewDisplay(); NewDisplay();
...@@ -526,43 +536,43 @@ void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event ) ...@@ -526,43 +536,43 @@ void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_MENU3D_USE_COPPER_THICKNESS: case ID_MENU3D_USE_COPPER_THICKNESS:
GetPrm3DVisu().SetFlag( FL_USE_COPPER_THICKNESS, isChecked ); GetPrm3DVisu().SetFlag( FL_USE_COPPER_THICKNESS, isChecked );
NewDisplay(GL_ID_BOARD); NewDisplay( GL_ID_BOARD );
NewDisplay(GL_ID_TECH_LAYERS); NewDisplay( GL_ID_TECH_LAYERS );
return; return;
case ID_MENU3D_ZONE_ONOFF: case ID_MENU3D_ZONE_ONOFF:
GetPrm3DVisu().SetFlag( FL_ZONE, isChecked ); GetPrm3DVisu().SetFlag( FL_ZONE, isChecked );
NewDisplay(GL_ID_BOARD); NewDisplay( GL_ID_BOARD );
return; return;
case ID_MENU3D_ADHESIVE_ONOFF: case ID_MENU3D_ADHESIVE_ONOFF:
GetPrm3DVisu().SetFlag( FL_ADHESIVE, isChecked ); GetPrm3DVisu().SetFlag( FL_ADHESIVE, isChecked );
NewDisplay(GL_ID_TECH_LAYERS); NewDisplay( GL_ID_TECH_LAYERS );
return; return;
case ID_MENU3D_SILKSCREEN_ONOFF: case ID_MENU3D_SILKSCREEN_ONOFF:
GetPrm3DVisu().SetFlag( FL_SILKSCREEN, isChecked ); GetPrm3DVisu().SetFlag( FL_SILKSCREEN, isChecked );
NewDisplay(GL_ID_TECH_LAYERS); NewDisplay( GL_ID_TECH_LAYERS );
return; return;
case ID_MENU3D_SOLDER_MASK_ONOFF: case ID_MENU3D_SOLDER_MASK_ONOFF:
GetPrm3DVisu().SetFlag( FL_SOLDERMASK, isChecked ); GetPrm3DVisu().SetFlag( FL_SOLDERMASK, isChecked );
NewDisplay(GL_ID_TECH_LAYERS); NewDisplay( GL_ID_TECH_LAYERS );
return; return;
case ID_MENU3D_SOLDER_PASTE_ONOFF: case ID_MENU3D_SOLDER_PASTE_ONOFF:
GetPrm3DVisu().SetFlag( FL_SOLDERPASTE, isChecked ); GetPrm3DVisu().SetFlag( FL_SOLDERPASTE, isChecked );
NewDisplay(GL_ID_TECH_LAYERS); NewDisplay();
return; return;
case ID_MENU3D_COMMENTS_ONOFF: case ID_MENU3D_COMMENTS_ONOFF:
GetPrm3DVisu().SetFlag( FL_COMMENTS, isChecked ); GetPrm3DVisu().SetFlag( FL_COMMENTS, isChecked );
NewDisplay(GL_ID_AUX_LAYERS); NewDisplay( GL_ID_AUX_LAYERS );
return; return;
case ID_MENU3D_ECO_ONOFF: case ID_MENU3D_ECO_ONOFF:
GetPrm3DVisu().SetFlag( FL_ECO, isChecked ); GetPrm3DVisu().SetFlag( FL_ECO, isChecked );
NewDisplay(GL_ID_AUX_LAYERS); NewDisplay( GL_ID_AUX_LAYERS );
return; return;
default: default:
......
/* /*
* 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-2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2012 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
...@@ -55,10 +55,10 @@ S3D_MATERIAL::S3D_MATERIAL( S3D_MASTER* father, const wxString& name ) : ...@@ -55,10 +55,10 @@ S3D_MATERIAL::S3D_MATERIAL( S3D_MASTER* father, const wxString& name ) :
void SetOpenGlDefaultMaterial() void SetOpenGlDefaultMaterial()
{ {
glm::vec4 ambient( 0.2, 0.2, 0.2, 1.0 ); glm::vec4 ambient( 0.2f, 0.2f, 0.2f, 1.0f );
glm::vec4 specular( 0.0, 0.0, 0.0, 1.0 ); glm::vec4 specular( 0.0f, 0.0f, 0.0f, 1.0f );
glm::vec4 emissive( 0.0, 0.0, 0.0, 1.0 ); glm::vec4 emissive( 0.0f, 0.0f, 0.0f, 1.0f );
glm::vec4 diffuse( 0.0, 0.0, 0.0, 1.0 ); glm::vec4 diffuse( 0.0f, 0.0f, 0.0f, 1.0f );
GLint shininess_value = 0; GLint shininess_value = 0;
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
......
/* /*
* 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-2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2014 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
......
/* /*
* 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-2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 1992-2015 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
...@@ -27,14 +27,29 @@ ...@@ -27,14 +27,29 @@
* @brief * @brief
*/ */
#include <fctsys.h>
#include <3d_mesh_model.h> #include <3d_mesh_model.h>
#include <boost/geometry/algorithms/area.hpp> #include <boost/geometry/algorithms/area.hpp>
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
#include <gal/opengl/glm/glm.hpp>
#ifdef __WXMAC__
# ifdef __DARWIN__
# include <OpenGL/glu.h>
# else
# include <glu.h>
# endif
#else
# include <GL/glu.h>
#endif
#ifdef USE_OPENMP #ifdef USE_OPENMP
#include <omp.h> #include <omp.h>
#endif // USE_OPENMP #endif // USE_OPENMP
#include "info3d_visu.h"
S3D_MESH::S3D_MESH() S3D_MESH::S3D_MESH()
{ {
isPerFaceNormalsComputed = false; isPerFaceNormalsComputed = false;
...@@ -47,13 +62,95 @@ S3D_MESH::S3D_MESH() ...@@ -47,13 +62,95 @@ 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_center = glm::vec3( 0.0f, 0.0f, 0.0f ); // not used
} }
S3D_MESH::~S3D_MESH() S3D_MESH::~S3D_MESH()
{ {
for( unsigned int idx = 0; idx < childs.size(); idx++ )
{
if( childs[idx] )
{
delete childs[idx];
}
}
}
CBBOX &S3D_MESH::getBBox( )
{
if( !m_BBox.IsInitialized() )
calcBBoxAllChilds();
return m_BBox;
}
void S3D_MESH::calcBBoxAllChilds( )
{
// Calc your own boudingbox
calcBBox();
for( unsigned int idx = 0; idx < childs.size(); idx++ )
m_BBox.Union( childs[idx]->getBBox() );
CBBOX tmpBBox = m_BBox;
// Calc transformation matrix
glm::mat4 fullTransformMatrix;
glm::mat4 translationMatrix = glm::translate( glm::mat4(), m_translation );
if( m_rotation[3] != 0.0f )
{
glm::mat4 rotationMatrix = glm::rotate( translationMatrix, m_rotation[3],
S3D_VERTEX( m_rotation[0], m_rotation[1], m_rotation[2] ) );
fullTransformMatrix = glm::scale( rotationMatrix, m_scale );
}
else
fullTransformMatrix = glm::scale( translationMatrix, m_scale );
// Apply transformation
m_BBox.Set( S3D_VERTEX( fullTransformMatrix * glm::vec4( tmpBBox.Min(), 1.0f ) ),
S3D_VERTEX( fullTransformMatrix * glm::vec4( tmpBBox.Max(), 1.0f ) ) );
}
void S3D_MESH::calcBBox( )
{
CBBOX tmpBBox;
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 )
{
firstBBox = false;
tmpBBox = CBBOX( m_Point[m_CoordIndex[idx][ii]] ); // Initialize with the first vertex found
}
else
tmpBBox.Union( m_Point[m_CoordIndex[idx][ii]] );
}
m_BBox = tmpBBox;
} }
...@@ -72,10 +169,10 @@ void S3D_MESH::openGL_RenderAllChilds( bool aIsRenderingJustNonTransparentObjec ...@@ -72,10 +169,10 @@ void S3D_MESH::openGL_RenderAllChilds( bool aIsRenderingJustNonTransparentObjec
openGL_Render( aIsRenderingJustNonTransparentObjects, openGL_Render( aIsRenderingJustNonTransparentObjects,
aIsRenderingJustTransparentObjects ); aIsRenderingJustTransparentObjects );
// Render childs // Render childs recursively
for( unsigned int idx = 0; idx < childs.size(); idx++ ) for( unsigned int idx = 0; idx < childs.size(); idx++ )
{ {
childs[idx]->openGL_Render( aIsRenderingJustNonTransparentObjects, childs[idx]->openGL_RenderAllChilds( aIsRenderingJustNonTransparentObjects,
aIsRenderingJustTransparentObjects ); aIsRenderingJustTransparentObjects );
} }
...@@ -142,7 +239,7 @@ void S3D_MESH::openGL_Render( bool aIsRenderingJustNonTransparentObjects, ...@@ -142,7 +239,7 @@ void S3D_MESH::openGL_Render( bool aIsRenderingJustNonTransparentObjects,
{ {
if( m_Materials ) if( m_Materials )
{ {
if ( m_MaterialIndex.size() > 0 ) if ( m_MaterialIndex.size() > idx )
{ {
bool isTransparent = m_Materials->SetOpenGLMaterial( m_MaterialIndex[idx], useMaterial ); bool isTransparent = m_Materials->SetOpenGLMaterial( m_MaterialIndex[idx], useMaterial );
...@@ -153,9 +250,9 @@ void S3D_MESH::openGL_Render( bool aIsRenderingJustNonTransparentObjects, ...@@ -153,9 +250,9 @@ void S3D_MESH::openGL_Render( bool aIsRenderingJustNonTransparentObjects,
continue; continue;
if( useMaterial ) if( useMaterial )
if( m_Materials->m_Transparency.size() > idx ) if( (int)m_Materials->m_Transparency.size() > m_MaterialIndex[idx] )
if( m_Materials->m_Transparency[idx] >= 1.0f ) if( m_Materials->m_Transparency[m_MaterialIndex[idx]] >= 1.0f )
return; continue;
} }
else else
{ {
...@@ -270,37 +367,37 @@ void S3D_MESH::perVertexNormalsVerify_and_Repair() ...@@ -270,37 +367,37 @@ void S3D_MESH::perVertexNormalsVerify_and_Repair()
{ {
glm::vec3 normal = m_PerVertexNormalsNormalized[idx]; glm::vec3 normal = m_PerVertexNormalsNormalized[idx];
if( (normal.x == 1.0) && ((normal.y != 0.0) || (normal.z != 0.0)) ) if( (normal.x == 1.0f) && ((normal.y != 0.0f) || (normal.z != 0.0f)) )
{ {
normal.y = 0.0; normal.y = 0.0f;
normal.z = 0.0; normal.z = 0.0f;
} }
else else
if( (normal.y == 1.0) && ((normal.x != 0.0) || (normal.z != 0.0)) ) if( (normal.y == 1.0f) && ((normal.x != 0.0f) || (normal.z != 0.0f)) )
{ {
normal.x = 0.0; normal.x = 0.0f;
normal.z = 0.0; normal.z = 0.0f;
} }
else else
if( (normal.z == 1.0) && ((normal.x != 0.0) || (normal.y != 0.0)) ) if( (normal.z == 1.0f) && ((normal.x != 0.0f) || (normal.y != 0.0f)) )
{ {
normal.x = 0.0; normal.x = 0.0f;
normal.y = 0.0; normal.y = 0.0f;
} }
else else
if( (normal.x < FLT_EPSILON) && (normal.x > -FLT_EPSILON) ) if( (normal.x < FLT_EPSILON) && (normal.x > -FLT_EPSILON) )
{ {
normal.x = 0.0; normal.x = 0.0f;
} }
else else
if( (normal.y < FLT_EPSILON) && (normal.y > -FLT_EPSILON) ) if( (normal.y < FLT_EPSILON) && (normal.y > -FLT_EPSILON) )
{ {
normal.y = 0.0; normal.y = 0.0f;
} }
else else
if( (normal.z < FLT_EPSILON) && (normal.z > -FLT_EPSILON) ) if( (normal.z < FLT_EPSILON) && (normal.z > -FLT_EPSILON) )
{ {
normal.z = 0.0; normal.z = 0.0f;
} }
float l = glm::length( normal ); float l = glm::length( normal );
...@@ -328,10 +425,6 @@ void S3D_MESH::calcPointNormalized() ...@@ -328,10 +425,6 @@ void S3D_MESH::calcPointNormalized()
isPointNormalizedComputed = true; isPointNormalizedComputed = true;
/*
m_PointNormalized = m_Point;
*/
m_PointNormalized.clear(); m_PointNormalized.clear();
m_PointNormalized.resize( m_Point.size() ); m_PointNormalized.resize( m_Point.size() );
...@@ -406,9 +499,9 @@ void S3D_MESH::calcPerFaceNormals() ...@@ -406,9 +499,9 @@ void S3D_MESH::calcPerFaceNormals()
{ {
glm::vec3 cross_prod; glm::vec3 cross_prod;
cross_prod.x = 0.0; cross_prod.x = 0.0f;
cross_prod.y = 0.0; cross_prod.y = 0.0f;
cross_prod.z = 0.0; cross_prod.z = 0.0f;
// Newell's Method // Newell's Method
// http://www.opengl.org/wiki/Calculating_a_Surface_Normal // http://www.opengl.org/wiki/Calculating_a_Surface_Normal
...@@ -434,15 +527,6 @@ void S3D_MESH::calcPerFaceNormals() ...@@ -434,15 +527,6 @@ void S3D_MESH::calcPerFaceNormals()
float area = glm::dot( cross_prod, cross_prod ); float area = glm::dot( cross_prod, cross_prod );
area = fabs( area ); area = fabs( area );
// Dont remmember why this code was used for..
/*
if( cross_prod[2] < 0.0 )
area = -area;
if( area < FLT_EPSILON )
area = FLT_EPSILON * 2.0f;
*/
m_PerFaceNormalsRaw_X_PerFaceSquaredArea[idx] = cross_prod * area; m_PerFaceNormalsRaw_X_PerFaceSquaredArea[idx] = cross_prod * area;
if( haveAlreadyNormals_from_model_file == false ) if( haveAlreadyNormals_from_model_file == false )
...@@ -456,35 +540,35 @@ void S3D_MESH::calcPerFaceNormals() ...@@ -456,35 +540,35 @@ void S3D_MESH::calcPerFaceNormals()
} }
else else
{ {
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(%f, %f, %f) l:%f m_CoordIndex[idx].size: %u\n",
idx, idx,
cross_prod.x, cross_prod.y, cross_prod.z, cross_prod.x, cross_prod.y, cross_prod.z,
l, l,
(unsigned int)m_CoordIndex[idx].size()) ); (unsigned int)m_CoordIndex[idx].size()) );
*/
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 = 0.0; cross_prod.x = 0.0f;
cross_prod.y = 1.0; cross_prod.y = 1.0f;
cross_prod.z = 0.0; cross_prod.z = 0.0f;
} }
else if( ( cross_prod.y > cross_prod.x ) && ( cross_prod.y > cross_prod.z ) ) else if( ( cross_prod.y > cross_prod.x ) && ( cross_prod.y > cross_prod.z ) )
{ {
cross_prod.x = 0.0; cross_prod.x = 0.0f;
cross_prod.y = 1.0; cross_prod.y = 1.0f;
cross_prod.z = 0.0; cross_prod.z = 0.0f;
} }
else if( ( cross_prod.z > cross_prod.x ) && ( cross_prod.z > cross_prod.y ) ) else if( ( cross_prod.z > cross_prod.x ) && ( cross_prod.z > cross_prod.y ) )
{ {
cross_prod.x = 0.0; cross_prod.x = 0.0f;
cross_prod.y = 0.0; cross_prod.y = 0.0f;
cross_prod.z = 1.0; cross_prod.z = 1.0f;
} }
else else
{ {
cross_prod.x = 0.0; cross_prod.x = 0.0f;
cross_prod.y = 0.0; cross_prod.y = 0.0f;
cross_prod.z = 0.0; cross_prod.z = 0.0f;
} }
} }
...@@ -494,6 +578,7 @@ void S3D_MESH::calcPerFaceNormals() ...@@ -494,6 +578,7 @@ void S3D_MESH::calcPerFaceNormals()
} }
// Documentation literature
// 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()
......
/* /*
* 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-2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2014 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
...@@ -30,24 +30,12 @@ ...@@ -30,24 +30,12 @@
#ifndef __3D_MESH_MODEL_H__ #ifndef __3D_MESH_MODEL_H__
#define __3D_MESH_MODEL_H__ #define __3D_MESH_MODEL_H__
#include <fctsys.h>
#include <common.h>
#include <macros.h>
#include <base_struct.h>
#include <gal/opengl/glm/glm.hpp>
#include <vector> #include <vector>
#include <kicad_string.h> #include <gal/opengl/glm/glm.hpp>
#include <info3d_visu.h> #include "3d_struct.h"
#ifdef __WXMAC__ #include "3d_material.h"
# ifdef __DARWIN__ #include "CBBox.h"
# include <OpenGL/glu.h>
# else
# include <glu.h>
# endif
#else
# include <GL/glu.h>
#endif
#include <wx/glcanvas.h>
class S3D_MESH; class S3D_MESH;
...@@ -64,26 +52,24 @@ public: ...@@ -64,26 +52,24 @@ public:
S3D_MATERIAL *m_Materials; S3D_MATERIAL *m_Materials;
// Point and index list // Point and index list
std::vector< glm::vec3 > m_Point; std::vector< S3D_VERTEX > m_Point;
std::vector< std::vector<int> > m_CoordIndex; std::vector< std::vector<int> > m_CoordIndex;
std::vector< std::vector<int> > m_NormalIndex; std::vector< std::vector<int> > m_NormalIndex;
std::vector< glm::vec3 > m_PerFaceNormalsNormalized; std::vector< S3D_VERTEX > m_PerFaceNormalsNormalized;
std::vector< glm::vec3 > m_PerVertexNormalsNormalized; std::vector< S3D_VERTEX > m_PerVertexNormalsNormalized;
std::vector< int > m_MaterialIndex; std::vector< int > m_MaterialIndex;
std::vector< S3D_MESH * > childs;
glm::vec3 m_translation; S3D_VERTEX m_translation;
glm::vec4 m_rotation; glm::vec4 m_rotation;
glm::vec3 m_scale; S3D_VERTEX m_scale;
glm::vec4 m_scaleOrientation; // not used
glm::vec3 m_center; // not used
std::vector<S3D_MESH *> childs; CBBOX &getBBox();
private: private:
std::vector< glm::vec3 > m_PerFaceNormalsRaw_X_PerFaceSquaredArea; std::vector< S3D_VERTEX > m_PerFaceNormalsRaw_X_PerFaceSquaredArea;
std::vector< std::vector< glm::vec3 > > m_PerFaceVertexNormals; std::vector< std::vector< S3D_VERTEX > > m_PerFaceVertexNormals;
std::vector< glm::vec3 > m_PointNormalized; std::vector< S3D_VERTEX > m_PointNormalized;
std::vector< std::vector<int> > m_InvalidCoordIndexes; //!TODO: check for invalid CoordIndex in file and remove the index and the same material index std::vector< std::vector<int> > m_InvalidCoordIndexes; //!TODO: check for invalid CoordIndex in file and remove the index and the same material index
...@@ -99,6 +85,11 @@ private: ...@@ -99,6 +85,11 @@ private:
bool isPerVertexNormalsVerified; bool isPerVertexNormalsVerified;
void perVertexNormalsVerify_and_Repair(); void perVertexNormalsVerify_and_Repair();
void calcBBox();
void calcBBoxAllChilds();
CBBOX m_BBox;
void openGL_Render( bool aIsRenderingJustNonTransparentObjects, void openGL_Render( bool aIsRenderingJustNonTransparentObjects,
bool aIsRenderingJustTransparentObjects ); bool aIsRenderingJustTransparentObjects );
}; };
......
/* /*
* 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) 2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras@wanadoo.fr * Copyright (C) 2015 Jean-Pierre Charras, jp.charras@wanadoo.fr
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net> * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
...@@ -32,14 +33,14 @@ ...@@ -32,14 +33,14 @@
#include <macros.h> #include <macros.h>
#include <kicad_string.h> #include <kicad_string.h>
#include <pgm_base.h> #include <pgm_base.h>
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
#include <3d_viewer.h> #include <3d_viewer.h>
#include <info3d_visu.h> #include <info3d_visu.h>
#include "3d_struct.h" #include "3d_struct.h"
#include "modelparsers.h" #include "modelparsers.h"
S3D_MODEL_PARSER* S3D_MODEL_PARSER::Create( S3D_MASTER* aMaster, S3D_MODEL_PARSER *S3D_MODEL_PARSER::Create( S3D_MASTER* aMaster,
const wxString aExtension ) const wxString aExtension )
{ {
if ( aExtension == wxT( "x3d" ) ) if ( aExtension == wxT( "x3d" ) )
...@@ -50,46 +51,25 @@ S3D_MODEL_PARSER* S3D_MODEL_PARSER::Create( S3D_MASTER* aMaster, ...@@ -50,46 +51,25 @@ S3D_MODEL_PARSER* S3D_MODEL_PARSER::Create( S3D_MASTER* aMaster,
return NULL; return NULL;
} }
const wxString S3D_MASTER::GetShape3DFullFilename()
{
wxString shapeName;
// Expand any environment variables embedded in footprint's m_Shape3DName field.
// To ensure compatibility with most of footprint's m_Shape3DName field,
// if the m_Shape3DName is not an absolute path the default path
// given by the environment variable KISYS3DMOD will be used
if( m_Shape3DName.StartsWith( wxT("${") ) )
shapeName = wxExpandEnvVars( m_Shape3DName );
else
shapeName = m_Shape3DName;
wxFileName fn( shapeName );
if( fn.IsAbsolute() || shapeName.StartsWith( wxT(".") ) )
return shapeName;
wxString default_path;
wxGetEnv( KISYS3DMOD, &default_path );
if( default_path.IsEmpty() ) int S3D_MASTER::ReadData( S3D_MODEL_PARSER* aParser )
return shapeName;
if( !default_path.EndsWith( wxT("/") ) && !default_path.EndsWith( wxT("\\") ) )
default_path += wxT("/");
default_path += shapeName;
return default_path;
}
int S3D_MASTER::ReadData()
{ {
if( m_Shape3DName.IsEmpty() ) if( m_Shape3DName.IsEmpty() )
return 1; {
//DBG( printf("m_Shape3DName.IsEmpty") );
return -1;
}
wxString filename = GetShape3DFullFilename(); if( m_Shape3DFullFilename.IsEmpty() )
{
//DBG( printf("m_Shape3DFullFilename.IsEmpty") );
return -1;
}
if( aParser == NULL )
return -1;
wxString filename = m_Shape3DFullFilename;
#ifdef __WINDOWS__ #ifdef __WINDOWS__
filename.Replace( wxT( "/" ), wxT( "\\" ) ); filename.Replace( wxT( "/" ), wxT( "\\" ) );
...@@ -97,35 +77,30 @@ int S3D_MASTER::ReadData() ...@@ -97,35 +77,30 @@ int S3D_MASTER::ReadData()
filename.Replace( wxT( "\\" ), wxT( "/" ) ); filename.Replace( wxT( "\\" ), wxT( "/" ) );
#endif #endif
if( !wxFileName::FileExists( filename ) ) if( wxFileName::FileExists( filename ) )
{ {
wxLogDebug( wxT( "3D shape '%s' not found, even tried '%s' after env var substitution." ),
GetChars( m_Shape3DName ),
GetChars( filename )
);
return -1;
}
wxFileName fn( filename ); wxFileName fn( filename );
wxString extension = fn.GetExt(); if( aParser->Load( filename ) )
m_parser = S3D_MODEL_PARSER::Create( this, extension );
if( m_parser )
{ {
m_parser->Load( filename ); // Invalidate bounding boxes
m_fastAABBox.Reset();
m_BBox.Reset();
m_parser = aParser;
return 0; return 0;
} }
else
{
wxLogDebug( wxT( "Unknown file type '%s'" ), GetChars( extension ) );
} }
wxLogDebug( wxT( "3D shape '%s' not found, even tried '%s' after env var substitution." ),
GetChars( m_Shape3DName ),
GetChars( filename ) );
return -1; return -1;
} }
void S3D_MASTER::Render( bool aIsRenderingJustNonTransparentObjects, void S3D_MASTER::Render( bool aIsRenderingJustNonTransparentObjects,
bool aIsRenderingJustTransparentObjects ) bool aIsRenderingJustTransparentObjects )
{ {
...@@ -136,31 +111,80 @@ void S3D_MASTER::Render( bool aIsRenderingJustNonTransparentObjects, ...@@ -136,31 +111,80 @@ void S3D_MASTER::Render( bool aIsRenderingJustNonTransparentObjects,
glScalef( aVrmlunits_to_3Dunits, aVrmlunits_to_3Dunits, aVrmlunits_to_3Dunits ); glScalef( aVrmlunits_to_3Dunits, aVrmlunits_to_3Dunits, aVrmlunits_to_3Dunits );
glm::vec3 matScale( m_MatScale.x, glTranslatef( m_MatPosition.x * SCALE_3D_CONV,
m_MatScale.y, m_MatPosition.y * SCALE_3D_CONV,
m_MatScale.z ); m_MatPosition.z * SCALE_3D_CONV );
glRotatef( -m_MatRotation.z, 0.0f, 0.0f, 1.0f );
glRotatef( -m_MatRotation.y, 0.0f, 1.0f, 0.0f );
glRotatef( -m_MatRotation.x, 1.0f, 0.0f, 0.0f );
glm::vec3 matRot( m_MatRotation.x, glScalef( m_MatScale.x, m_MatScale.y, m_MatScale.z );
m_MatRotation.y,
m_MatRotation.z );
glm::vec3 matPos( m_MatPosition.x, for( unsigned int idx = 0; idx < m_parser->childs.size(); idx++ )
m_MatPosition.y, m_parser->childs[idx]->openGL_RenderAllChilds( aIsRenderingJustNonTransparentObjects,
m_MatPosition.z ); aIsRenderingJustTransparentObjects );
}
glTranslatef( matPos.x * SCALE_3D_CONV,
matPos.y * SCALE_3D_CONV,
matPos.z * SCALE_3D_CONV );
glRotatef( -matRot.z, 0.0f, 0.0f, 1.0f ); CBBOX &S3D_MASTER::getBBox( )
glRotatef( -matRot.y, 0.0f, 1.0f, 0.0f ); {
glRotatef( -matRot.x, 1.0f, 0.0f, 0.0f ); if( !m_BBox.IsInitialized() )
calcBBox();
return m_BBox;
}
CBBOX &S3D_MASTER::getFastAABBox( )
{
if( !m_fastAABBox.IsInitialized() )
calcBBox();
return m_fastAABBox;
}
glScalef( matScale.x, matScale.y, matScale.z );
void S3D_MASTER::calcBBox()
{
if( m_parser == NULL )
return;
bool firstBBox = true;
for( unsigned int idx = 0; idx < m_parser->childs.size(); idx++ ) for( unsigned int idx = 0; idx < m_parser->childs.size(); idx++ )
if( firstBBox )
{ {
m_parser->childs[idx]->openGL_RenderAllChilds( aIsRenderingJustNonTransparentObjects, firstBBox = false;
aIsRenderingJustTransparentObjects ); m_BBox = m_parser->childs[idx]->getBBox();
} }
else
m_BBox.Union( m_parser->childs[idx]->getBBox() );
// Calc transformation matrix to apply in AABBox
float aVrmlunits_to_3Dunits = g_Parm_3D_Visu.m_BiuTo3Dunits * UNITS3D_TO_UNITSPCB;
glm::mat4 fullTransformMatrix;
fullTransformMatrix = glm::scale( glm::mat4(), S3D_VERTEX( aVrmlunits_to_3Dunits,
aVrmlunits_to_3Dunits,
aVrmlunits_to_3Dunits ) );
fullTransformMatrix = glm::translate( fullTransformMatrix, S3D_VERTEX( m_MatPosition.x * SCALE_3D_CONV,
m_MatPosition.y * SCALE_3D_CONV,
m_MatPosition.z * SCALE_3D_CONV) );
if( m_MatRotation.z != 0.0 )
fullTransformMatrix = glm::rotate( fullTransformMatrix, -(float)m_MatRotation.z, S3D_VERTEX( 0.0f, 0.0f, 1.0f ) );
if( m_MatRotation.y != 0.0 )
fullTransformMatrix = glm::rotate( fullTransformMatrix, -(float)m_MatRotation.y, S3D_VERTEX( 0.0f, 1.0f, 0.0f ) );
if( m_MatRotation.x != 0.0 )
fullTransformMatrix = glm::rotate( fullTransformMatrix, -(float)m_MatRotation.x, S3D_VERTEX( 1.0f, 0.0f, 0.0f ) );
fullTransformMatrix = glm::scale( fullTransformMatrix, S3D_VERTEX( m_MatScale.x, m_MatScale.y, m_MatScale.z ) );
// Apply transformation
m_fastAABBox = m_BBox;
m_fastAABBox.ApplyTransformationAA( fullTransformMatrix );
} }
/* /*
* 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-2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net> * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
...@@ -34,54 +34,12 @@ ...@@ -34,54 +34,12 @@
#include <common.h> #include <common.h>
#include <base_struct.h> #include <base_struct.h>
#include <3d_material.h> #include <3d_material.h>
#include <gal/opengl/glm/glm.hpp> #include <3d_types.h>
#include <CBBox.h>
/**
* @note For historical reasons the 3D modeling unit is 0.1 inch
* 1 3Dunit = 2.54 mm = 0.1 inch = 100 mils
*/
#define UNITS3D_TO_UNITSPCB (IU_PER_MILS * 100)
/**
* scaling factor for 3D shape offset ( S3D_MASTER::m_MatPosition member )
* Was in inches in legacy version, and, due to a mistake, still in inches
* in .kicad_pcb files (which are using mm)
* so this scaling convert file units (inch) to 3D units (0.1 inch), only
* for S3D_MASTER::m_MatPosition parameter
*/
#define SCALE_3D_CONV 10
class S3D_MASTER; class S3D_MASTER;
class STRUCT_3D_SHAPE; class STRUCT_3D_SHAPE;
// S3D_VERTEX manages a opengl 3D coordinate (3 float numbers: x,y,z coordinates)
// float are widely used in opengl functions.
// they are used here in coordinates which are also used in opengl functions.
#define S3D_VERTEX glm::vec3
// S3DPOINT manages a set of 3 double values (x,y,z )
// It is used for values which are not directly used in opengl functions.
// It is used in dialogs, or when reading/writing files for instance
class S3DPOINT
{
public:
double x, y, z;
public:
S3DPOINT()
{
x = y = z = 0.0;
}
S3DPOINT( double px, double py, double pz)
{
x = px;
y = py;
z = pz;
}
};
class S3D_MODEL_PARSER; class S3D_MODEL_PARSER;
// Master structure for a 3D footprint shape description // Master structure for a 3D footprint shape description
...@@ -112,8 +70,10 @@ public: ...@@ -112,8 +70,10 @@ public:
bool m_use_modelfile_shininess; bool m_use_modelfile_shininess;
private: private:
wxString m_Shape3DName; // the 3D shape filename in 3D library wxString m_Shape3DName; ///< The 3D shape filename in 3D library
FILE3D_TYPE m_ShapeType; FILE3D_TYPE m_ShapeType; ///< Shape type based on filename extension
wxString m_Shape3DFullFilename; ///< Full file path name
wxString m_Shape3DNameExtension; ///< Extension of the shape file name
public: public:
S3D_MASTER( EDA_ITEM* aParent ); S3D_MASTER( EDA_ITEM* aParent );
...@@ -131,8 +91,9 @@ public: ...@@ -131,8 +91,9 @@ public:
* Function ReadData * Function ReadData
* Select the parser to read the 3D data file (vrml, x3d ...) * Select the parser to read the 3D data file (vrml, x3d ...)
* and build the description objects list * and build the description objects list
* @param aParser the parser that should be used to read model data and stored in
*/ */
int ReadData(); int ReadData( S3D_MODEL_PARSER* aParser );
void Render( bool aIsRenderingJustNonTransparentObjects, void Render( bool aIsRenderingJustNonTransparentObjects,
bool aIsRenderingJustTransparentObjects ); bool aIsRenderingJustTransparentObjects );
...@@ -177,6 +138,12 @@ public: ...@@ -177,6 +138,12 @@ public:
*/ */
const wxString GetShape3DFullFilename(); const wxString GetShape3DFullFilename();
/**
* Function GetShape3DExtension
* @return the extension of the filename of the 3D shape,
*/
const wxString GetShape3DExtension();
/** /**
* Function SetShape3DName * Function SetShape3DName
* @param aShapeName = file name of the data file relative to the 3D shape * @param aShapeName = file name of the data file relative to the 3D shape
...@@ -185,6 +152,23 @@ public: ...@@ -185,6 +152,23 @@ public:
* (vrl, x3d, idf ) the type of file. * (vrl, x3d, idf ) the type of file.
*/ */
void SetShape3DName( const wxString& aShapeName ); void SetShape3DName( const wxString& aShapeName );
/**
* Function getBBox Model Space Bouding Box
* @return return the model space bouding box
*/
CBBOX &getBBox();
/**
* Function getFastAABBox
* @return return the Axis Align Bounding Box of the other bouding boxes
*/
CBBOX &getFastAABBox();
private:
void calcBBox();
CBBOX m_BBox; ///< Model oriented Bouding Box
CBBOX m_fastAABBox; ///< Axis Align Bounding Box that contain the other bounding boxes
}; };
...@@ -208,30 +192,4 @@ public: ...@@ -208,30 +192,4 @@ public:
#endif #endif
}; };
/**
* Class S3DPOINT_VALUE_CTRL
* displays a S3DPOINT for editing (in dialogs). A S3DPOINT is a triplet of values
* Values can be scale, rotation, offset...
*/
class S3DPOINT_VALUE_CTRL
{
private:
wxTextCtrl* m_XValueCtrl, * m_YValueCtrl, * m_ZValueCtrl;
public:
S3DPOINT_VALUE_CTRL( wxWindow* parent, wxBoxSizer* BoxSizer );
~S3DPOINT_VALUE_CTRL();
/**
* Function GetValue
* @return the 3D point in internal units.
*/
S3DPOINT GetValue();
void SetValue( S3DPOINT a3Dpoint );
void Enable( bool enbl );
void SetToolTip( const wxString& text );
};
#endif // STRUCT_3D_H #endif // STRUCT_3D_H
...@@ -187,6 +187,10 @@ void EDA_3D_FRAME::CreateMenuBar() ...@@ -187,6 +187,10 @@ void EDA_3D_FRAME::CreateMenuBar()
_( "Render Material Properties" ), _( "Render Material Properties" ),
KiBitmap( green_xpm ), wxITEM_CHECK ); KiBitmap( green_xpm ), wxITEM_CHECK );
AddMenuItem( renderOptionsMenu, ID_MENU3D_FL_RENDER_SHOW_MODEL_BBOX,
_( "Show Model Bouding Boxes" ),
KiBitmap( green_xpm ), wxITEM_CHECK );
prefsMenu->AppendSeparator(); prefsMenu->AppendSeparator();
wxMenu * backgrounColorMenu = new wxMenu; wxMenu * backgrounColorMenu = new wxMenu;
...@@ -300,6 +304,9 @@ void EDA_3D_FRAME::SetMenuBarOptionsState() ...@@ -300,6 +304,9 @@ void EDA_3D_FRAME::SetMenuBarOptionsState()
item = menuBar->FindItem( ID_MENU3D_FL_RENDER_MATERIAL ); item = menuBar->FindItem( ID_MENU3D_FL_RENDER_MATERIAL );
item->Check( GetPrm3DVisu().GetFlag( FL_RENDER_MATERIAL ) ); item->Check( GetPrm3DVisu().GetFlag( FL_RENDER_MATERIAL ) );
item = menuBar->FindItem( ID_MENU3D_FL_RENDER_SHOW_MODEL_BBOX );
item->Check( GetPrm3DVisu().GetFlag( FL_RENDER_SHOW_MODEL_BBOX ) );
item = menuBar->FindItem( ID_MENU3D_SHOW_BOARD_BODY ); item = menuBar->FindItem( ID_MENU3D_SHOW_BOARD_BODY );
item->Check( GetPrm3DVisu().GetFlag( FL_SHOW_BOARD_BODY ) ); item->Check( GetPrm3DVisu().GetFlag( FL_SHOW_BOARD_BODY ) );
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file 3d_types.h
*/
#ifndef _3D_TYPES_H_
#define _3D_TYPES_H_
#include <gal/opengl/glm/glm.hpp>
#include <base_units.h> // for IU_PER_MILS
/**
* @note For historical reasons the 3D modeling unit is 0.1 inch
* 1 3Dunit = 2.54 mm = 0.1 inch = 100 mils
*/
#define UNITS3D_TO_UNITSPCB (IU_PER_MILS * 100)
/**
* scaling factor for 3D shape offset ( S3D_MASTER::m_MatPosition member )
* Was in inches in legacy version, and, due to a mistake, still in inches
* in .kicad_pcb files (which are using mm)
* so this scaling convert file units (inch) to 3D units (0.1 inch), only
* for S3D_MASTER::m_MatPosition parameter
*/
#define SCALE_3D_CONV 10
// S3D_VERTEX manages a opengl 3D coordinate (3 float numbers: x,y,z coordinates)
// float are widely used in opengl functions.
// they are used here in coordinates which are also used in opengl functions.
#define S3D_VERTEX glm::vec3
// S3DPOINT manages a set of 3 double values (x,y,z )
// It is used for values which are not directly used in opengl functions.
// It is used in dialogs, or when reading/writing files for instance
class S3DPOINT
{
public:
double x, y, z;
public:
S3DPOINT()
{
x = y = z = 0.0;
}
S3DPOINT( double px, double py, double pz)
{
x = px;
y = py;
z = pz;
}
};
/**
* Class S3DPOINT_VALUE_CTRL
* displays a S3DPOINT for editing (in dialogs). A S3DPOINT is a triplet of values
* Values can be scale, rotation, offset...
*/
class S3DPOINT_VALUE_CTRL
{
private:
wxTextCtrl* m_XValueCtrl, * m_YValueCtrl, * m_ZValueCtrl;
public:
S3DPOINT_VALUE_CTRL( wxWindow* parent, wxBoxSizer* BoxSizer );
~S3DPOINT_VALUE_CTRL();
/**
* Function GetValue
* @return the 3D point in internal units.
*/
S3DPOINT GetValue();
void SetValue( S3DPOINT a3Dpoint );
void Enable( bool enbl );
void SetToolTip( const wxString& text );
};
#endif // 3D_TYPES_H
...@@ -52,6 +52,7 @@ enum id_3dview_frm ...@@ -52,6 +52,7 @@ enum id_3dview_frm
ID_MENU3D_FL_RENDER_SMOOTH_NORMALS, ID_MENU3D_FL_RENDER_SMOOTH_NORMALS,
ID_MENU3D_FL_RENDER_USE_MODEL_NORMALS, ID_MENU3D_FL_RENDER_USE_MODEL_NORMALS,
ID_MENU3D_FL_RENDER_MATERIAL, ID_MENU3D_FL_RENDER_MATERIAL,
ID_MENU3D_FL_RENDER_SHOW_MODEL_BBOX,
ID_END_COMMAND_3D, ID_END_COMMAND_3D,
ID_TOOL_SET_VISIBLE_ITEMS, ID_TOOL_SET_VISIBLE_ITEMS,
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file CBBox.cpp
* @brief Bounding Box class implementation
*/
#include "CBBox.h"
// openGL includes used for debug the bounding box
#ifdef __WXMAC__
# ifdef __DARWIN__
# include <OpenGL/glu.h>
# else
# include <glu.h>
# endif
#else
# include <GL/glu.h>
#endif
CBBOX::CBBOX()
{
Reset();
}
CBBOX::CBBOX( const S3D_VERTEX &aPbInit )
{
m_min = aPbInit;
m_max = aPbInit;
m_initialized = true;
}
CBBOX::CBBOX( const S3D_VERTEX &aPbMin, const S3D_VERTEX &aPbMax )
{
Set( aPbMin, aPbMax );
}
CBBOX::~CBBOX()
{
}
void CBBOX::Set( const S3D_VERTEX &aPbMin, const S3D_VERTEX &aPbMax )
{
m_min.x = glm::min( aPbMin.x, aPbMax.x );
m_min.y = glm::min( aPbMin.y, aPbMax.y );
m_min.z = glm::min( aPbMin.z, aPbMax.z );
m_max.x = glm::max( aPbMin.x, aPbMax.x );
m_max.y = glm::max( aPbMin.y, aPbMax.y );
m_max.z = glm::max( aPbMin.z, aPbMax.z );
m_initialized = true;
}
bool CBBOX::IsInitialized() const
{
return m_initialized;
}
void CBBOX::Reset()
{
m_min = S3D_VERTEX( 0.0f, 0.0f, 0.0f );
m_max = S3D_VERTEX( 0.0f, 0.0f, 0.0f );
m_initialized = false;
}
void CBBOX::Union( const S3D_VERTEX &aPoint )
{
if( !m_initialized )
{
m_initialized = true;
// Initialize the bounding box with the given point
m_min = aPoint;
m_max = aPoint;
}
else
{
// get the minimun value between the added point and the existent bounding box
m_min.x = glm::min( m_min.x, aPoint.x );
m_min.y = glm::min( m_min.y, aPoint.y );
m_min.z = glm::min( m_min.z, aPoint.z );
// get the maximun value between the added point and the existent bounding box
m_max.x = glm::max( m_max.x, aPoint.x );
m_max.y = glm::max( m_max.y, aPoint.y );
m_max.z = glm::max( m_max.z, aPoint.z );
}
}
void CBBOX::Union( const CBBOX &aBBox )
{
if( aBBox.m_initialized == false )
return;
if( !m_initialized )
{
// Initialize the bounding box with the given bounding box
m_initialized = true;
m_min = aBBox.m_min;
m_max = aBBox.m_max;
}
else
{
// get the minimun value between the added bounding box and the existent bounding box
m_min.x = glm::min( m_min.x, aBBox.m_min.x );
m_min.y = glm::min( m_min.y, aBBox.m_min.y );
m_min.z = glm::min( m_min.z, aBBox.m_min.z );
// get the maximun value between the added bounding box and the existent bounding box
m_max.x = glm::max( m_max.x, aBBox.m_max.x );
m_max.y = glm::max( m_max.y, aBBox.m_max.y );
m_max.z = glm::max( m_max.z, aBBox.m_max.z );
}
}
S3D_VERTEX CBBOX::GetCenter() const
{
return (m_max + m_min) * 0.5f;
}
S3D_VERTEX CBBOX::Min() const
{
return m_min;
}
S3D_VERTEX CBBOX::Max() const
{
return m_max;
}
void CBBOX::Scale( float aScale )
{
if( m_initialized == false )
return;
S3D_VERTEX scaleV = S3D_VERTEX( aScale, aScale, aScale );
S3D_VERTEX centerV = GetCenter();
m_min = (m_min - centerV) * scaleV + centerV;
m_max = (m_max - centerV) * scaleV + centerV;
}
bool CBBOX::OverlapsBox( const CBBOX &aBBox ) const
{
if( aBBox.m_initialized == false )
return false;
bool x = ( m_max.x >= aBBox.m_min.x ) && ( m_min.x <= aBBox.m_max.x );
bool y = ( m_max.y >= aBBox.m_min.y ) && ( m_min.y <= aBBox.m_max.y );
bool z = ( m_max.z >= aBBox.m_min.z ) && ( m_min.z <= aBBox.m_max.z );
return ( x && y && z );
}
bool CBBOX::Inside( const S3D_VERTEX &aPoint ) const
{
if( m_initialized == false )
return false;
return (( aPoint.x >= m_min.x ) && ( aPoint.x <= m_max.x ) &&
( aPoint.y >= m_min.y ) && ( aPoint.y <= m_max.y ) &&
( aPoint.z >= m_min.z ) && ( aPoint.z <= m_max.z ));
}
float CBBOX::Volume() const
{
if( m_initialized == false )
return 0.0f;
S3D_VERTEX d = m_max - m_min;
return d.x * d.y * d.z;
}
void CBBOX::ApplyTransformation( glm::mat4 aTransformMatrix )
{
if( m_initialized == false )
return;
S3D_VERTEX v1 = S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) );
S3D_VERTEX v2 = S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) );
Reset();
Union( v1 );
Union( v2 );
}
void CBBOX::ApplyTransformationAA( glm::mat4 aTransformMatrix )
{
if( m_initialized == false )
return;
// apply the transformation matrix for each of vertices of the bounding box
// and make a union with all vertices
CBBOX tmpBBox = CBBOX( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) ) );
tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_min.y, m_min.z, 1.0f ) ) );
tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_max.y, m_min.z, 1.0f ) ) );
tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_max.z, 1.0f ) ) );
tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_max.y, m_max.z, 1.0f ) ) );
tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_min.z, 1.0f ) ) );
tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_min.y, m_max.z, 1.0f ) ) );
tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) ) );
m_min = tmpBBox.m_min;
m_max = tmpBBox.m_max;
}
void CBBOX::GLdebug() const
{
if( m_initialized == false )
return;
glBegin( GL_LINE_LOOP );
glVertex3f( m_min.x, m_min.y, m_min.z );
glVertex3f( m_max.x, m_min.y, m_min.z );
glVertex3f( m_max.x, m_max.y, m_min.z );
glVertex3f( m_min.x, m_max.y, m_min.z );
glEnd();
glBegin( GL_LINE_LOOP );
glVertex3f( m_min.x, m_min.y, m_max.z );
glVertex3f( m_max.x, m_min.y, m_max.z );
glVertex3f( m_max.x, m_max.y, m_max.z );
glVertex3f( m_min.x, m_max.y, m_max.z );
glEnd();
glBegin( GL_LINE_STRIP );
glVertex3f( m_min.x, m_min.y, m_min.z );
glVertex3f( m_min.x, m_min.y, m_max.z );
glEnd();
glBegin( GL_LINE_STRIP );
glVertex3f( m_max.x, m_min.y, m_min.z );
glVertex3f( m_max.x, m_min.y, m_max.z );
glEnd();
glBegin( GL_LINE_STRIP );
glVertex3f( m_max.x, m_max.y, m_min.z );
glVertex3f( m_max.x, m_max.y, m_max.z );
glEnd();
glBegin( GL_LINE_STRIP );
glVertex3f( m_min.x, m_max.y, m_min.z );
glVertex3f( m_min.x, m_max.y, m_max.z );
glEnd();
}
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file CBBox.h
* @brief Bounding Box class definition
*/
#ifndef CBBox_h
#define CBBox_h
#include <gal/opengl/glm/glm.hpp>
#include <3d_types.h>
/**
* Class CBBOX
* manages a bounding box defined by two S3D_VERTEX points.
*/
class CBBOX
{
public:
/**
* Constructor CBBOX
* Create with default values a bounding box (not inizialized)
*/
CBBOX();
/**
* Constructor CBBOX
* Initialize a bounding box with a given point
* @param aPbInit a point for the bounding box initialization
*/
CBBOX( const S3D_VERTEX &aPbInit );
/**
* Constructor CBBOX
* Initialize a bounding box with a minimon and a maximun point
* @param aPbMin the minimun point to initialize the bounding box
* @param aPbMax the maximun point to initialize the bounding box
*/
CBBOX( const S3D_VERTEX &aPbMin, const S3D_VERTEX &aPbMax );
~CBBOX();
/**
* Function Set
* Set bounding box with new parameters
* @param aPbMin the minimun point to initialize the bounding box
* @param aPbMax the maximun point to initialize the bounding box
*/
void Set( const S3D_VERTEX &aPbMin, const S3D_VERTEX &aPbMax );
/**
* Function Union
* recalculate the bounding box adding a point
* @param aPoint the point to be bounded
*/
void Union( const S3D_VERTEX &aPoint );
/**
* Function Union
* recalculate the bounding box adding other bounding box
* @param aBBox the bounding box to be bounded
*/
void Union( const CBBOX &aBBox );
/**
* Function Scale
* scales a bounding box by its center
* @param aScale scale factor to apply
*/
void Scale( float aScale );
/**
* Function OverlapsBox
* test if a bounding box overlaps this box
* @param aBBox the bounding box to check if it overlaps
*/
bool OverlapsBox( const CBBOX &aBBox ) const;
/**
* Function Inside
* check is a point is inside this bounding box
* @param aPoint point to test
*/
bool Inside( const S3D_VERTEX &aPoint ) const;
/**
* Function ApplyTransformation
* apply a transformation matrix to the box points
* @param aTransformMatrix matrix to apply to the points of the bounding box
*/
void ApplyTransformation( glm::mat4 aTransformMatrix );
/**
* Function ApplyTransformationAA
* apply a transformation matrix to the box points and recalculate it
* to fit an axis aligned bounding box
* @param aTransformMatrix matrix to apply to the points of the bounding box
*/
void ApplyTransformationAA( glm::mat4 aTransformMatrix );
/**
* Function Volume
* calculate the volume of a bounding box
* @return float - volume of this bounding box
*/
float Volume() const;
/**
* Function GLdebug
* render a wired bounding box using openGL
*/
void GLdebug() const;
/**
* Function IsInitialized
* check if this bounding box is already initialized
* @return bool - return true if it was initialized, false if otherwise
*/
bool IsInitialized() const;
/**
* Function Reset
* reset the bounding box to zero and de-initialized it
*/
void Reset();
/**
* Function GetCenter
* return the center point of the bounding box
* @return S3D_VERTEX - the position of the center of this bounding box
*/
S3D_VERTEX GetCenter() const;
/**
* Function Min
* return the minimun vertex pointer
* @return S3D_VERTEX - the minimun vertice position
*/
S3D_VERTEX Min() const;
/**
* Function Max
* return the maximum vertex pointer
* @return S3D_VERTEX - the maximun vertice position
*/
S3D_VERTEX Max() const;
private:
S3D_VERTEX m_min; ///< point of the lower position of the bounding box
S3D_VERTEX m_max; ///< point of the higher position of the bounding box
bool m_initialized; ///< initialization status of the bounding box. true - if initialized, false otherwise
};
#endif // CBBox_h
...@@ -22,17 +22,26 @@ ...@@ -22,17 +22,26 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
/**
* @file CImage.cpp
* @brief one 8bit-channel image implementation
*/
#include "CImage.h" #include "CImage.h"
#include <wx/image.h> // Used for save an image to disk
#include <string.h> // For memcpy
#ifndef CLAMP
#define CLAMP(n, min, max) {if (n < min) n=min; else if (n > max) n = max;} #define CLAMP(n, min, max) {if (n < min) n=min; else if (n > max) n = max;}
#endif
CIMAGE::CIMAGE( unsigned int xsize, unsigned int ysize ) CIMAGE::CIMAGE( unsigned int aXsize, unsigned int aYsize )
{ {
m_pixels = (unsigned char*)malloc( xsize * ysize ); m_wxh = aXsize * aYsize;
m_width = xsize; m_pixels = (unsigned char*)malloc( m_wxh );
m_height = ysize; m_width = aXsize;
m_wxh = xsize * ysize; m_height = aYsize;
m_wraping = (E_WRAP)WRAP_CLAMP; m_wraping = (E_WRAP)WRAP_CLAMP;
} }
...@@ -43,10 +52,16 @@ CIMAGE::~CIMAGE() ...@@ -43,10 +52,16 @@ CIMAGE::~CIMAGE()
} }
bool CIMAGE::wrapCoords( int *xo, int *yo ) unsigned char* CIMAGE::GetBuffer() const
{ {
int x = *xo; return m_pixels;
int y = *yo; }
bool CIMAGE::wrapCoords( int *aXo, int *aYo ) const
{
int x = *aXo;
int y = *aYo;
switch(m_wraping) switch(m_wraping)
{ {
...@@ -66,40 +81,41 @@ bool CIMAGE::wrapCoords( int *xo, int *yo ) ...@@ -66,40 +81,41 @@ bool CIMAGE::wrapCoords( int *xo, int *yo )
break; break;
} }
if( (x < 0) || (x >= (int)m_width) || (y < 0) || (y >= (int)m_height)) if( (x < 0) || (x >= (int)m_width) ||
(y < 0) || (y >= (int)m_height) )
return false; return false;
*xo = x; *aXo = x;
*yo = y; *aYo = y;
return true; return true;
} }
void CIMAGE::setpixel( int x, int y, unsigned char value ) void CIMAGE::Setpixel( int aX, int aY, unsigned char aValue )
{ {
if( wrapCoords( &x, &y ) ) if( wrapCoords( &aX, &aY ) )
m_pixels[x + y * m_width] = value; m_pixels[aX + aY * m_width] = aValue;
} }
unsigned char CIMAGE::getpixel(int x, int y) unsigned char CIMAGE::Getpixel( int aX, int aY ) const
{ {
if( wrapCoords( &x, &y ) ) if( wrapCoords( &aX, &aY ) )
return m_pixels[x + y * m_width]; return m_pixels[aX + aY * m_width];
else else
return 0; return 0;
} }
void CIMAGE::invert() void CIMAGE::Invert()
{ {
for( unsigned int it = 0;it < m_wxh; it++ ) for( unsigned int it = 0; it < m_wxh; it++ )
m_pixels[it] = 255 - m_pixels[it]; m_pixels[it] = 255 - m_pixels[it];
} }
void CIMAGE::copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOperation ) void CIMAGE::CopyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOperation )
{ {
int aV, bV; int aV, bV;
...@@ -117,8 +133,7 @@ void CIMAGE::copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOpe ...@@ -117,8 +133,7 @@ void CIMAGE::copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOpe
switch(aOperation) switch(aOperation)
{ {
case COPY_RAW: case COPY_RAW:
for( unsigned int it = 0;it < m_wxh; it++ ) memcpy( m_pixels, aImgA->m_pixels, m_wxh );
m_pixels[it] = aImgA->m_pixels[it];
break; break;
case COPY_ADD: case COPY_ADD:
...@@ -189,6 +204,13 @@ void CIMAGE::copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOpe ...@@ -189,6 +204,13 @@ void CIMAGE::copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOpe
break; break;
case COPY_BLEND50: case COPY_BLEND50:
for( unsigned int it = 0;it < m_wxh; it++ )
{
aV = aImgA->m_pixels[it];
bV = aImgB->m_pixels[it];
m_pixels[it] = (aV + bV) / 2;
}
break; break;
case COPY_MIN: case COPY_MIN:
...@@ -210,11 +232,16 @@ void CIMAGE::copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOpe ...@@ -210,11 +232,16 @@ void CIMAGE::copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOpe
m_pixels[it] = (aV > bV)?aV:bV; m_pixels[it] = (aV > bV)?aV:bV;
} }
break; break;
default:
break;
} }
} }
// TIP: If you want create or test filters you can use GIMP
S_FILTER FILTERS[9] = { // with a generic convolution matrix and get the values from there.
// http://docs.gimp.org/nl/plug-in-convmatrix.html
static const S_FILTER FILTERS[] = {
// Hi Pass // Hi Pass
{ {
{ { 0, -1, -1, -1, 0}, { { 0, -1, -1, -1, 0},
...@@ -230,17 +257,28 @@ S_FILTER FILTERS[9] = { ...@@ -230,17 +257,28 @@ S_FILTER FILTERS[9] = {
// Blur // Blur
{ {
{ { 3, 5, 7, 5, 3}, { { 3, 5, 7, 5, 3},
{ 4, 9, 12, 9, 5}, { 5, 9, 12, 9, 5},
{ 7, 12, 20, 12, 7}, { 7, 12, 20, 12, 7},
{ 4, 9, 12, 9, 5}, { 5, 9, 12, 9, 5},
{ 3, 5, 7, 5, 3} { 3, 5, 7, 5, 3}
}, },
180, 182,
0 0
}, },
// Blur Invert
{
{ { 0, 0, 0, 0, 0},
{ 0, 0, -1, 0, 0},
{ 0, -1, 0, -1, 0},
{ 0, 0, -1, 0, 0},
{ 0, 0, 0, 0, 0}
},
4,
255
},
// KS 01 //
{ {
{ { 0, 2, 4, 2, 0}, { { 0, 2, 4, 2, 0},
{ 2, -2, 1, -2, 2}, { 2, -2, 1, -2, 2},
...@@ -326,31 +364,41 @@ S_FILTER FILTERS[9] = { ...@@ -326,31 +364,41 @@ S_FILTER FILTERS[9] = {
};// Filters };// Filters
void CIMAGE::efxFilter( CIMAGE *aInImg, float aGain, E_FILTER aFilterType ) //!TODO: This functions can be optimized slipting it between the edges and
// do it without use the getpixel function.
// Optimization can be done to m_pixels[ix + iy * m_width]
// but keep in mind the parallel process of the algorithm
void CIMAGE::EfxFilter( CIMAGE *aInImg, E_FILTER aFilterType )
{ {
S_FILTER filter = FILTERS[aFilterType]; S_FILTER filter = FILTERS[aFilterType];
aInImg->m_wraping = WRAP_CLAMP; aInImg->m_wraping = WRAP_CLAMP;
m_wraping = WRAP_CLAMP; m_wraping = WRAP_CLAMP;
#ifdef USE_OPENMP
#pragma omp parallel for
#endif /* USE_OPENMP */
for( int iy = 0; iy < (int)m_height; iy++) for( int iy = 0; iy < (int)m_height; iy++)
{ {
for( int ix = 0; ix < (int)m_width; ix++ ) for( int ix = 0; ix < (int)m_width; ix++ )
{ {
int v = filter.offset; int v = 0;
for( int sy = 0; sy < 5; sy++ ) for( int sy = 0; sy < 5; sy++ )
{ {
for( int sx = 0; sx < 5; sx++ ) for( int sx = 0; sx < 5; sx++ )
{ {
int factor = filter.kernel[sx][sy]; int factor = filter.kernel[sx][sy];
unsigned char pixelv = aInImg->getpixel( ix + sx - 2, iy + sy - 2 ); unsigned char pixelv = aInImg->Getpixel( ix + sx - 2, iy + sy - 2 );
v += pixelv * factor; v += pixelv * factor;
} }
} }
v /= filter.div; v /= filter.div;
v += filter.offset;
CLAMP(v, 0, 255); CLAMP(v, 0, 255);
m_pixels[ix + iy * m_width] = v; m_pixels[ix + iy * m_width] = v;
...@@ -359,7 +407,7 @@ void CIMAGE::efxFilter( CIMAGE *aInImg, float aGain, E_FILTER aFilterType ) ...@@ -359,7 +407,7 @@ void CIMAGE::efxFilter( CIMAGE *aInImg, float aGain, E_FILTER aFilterType )
} }
void CIMAGE::setPixelsFromNormalizedFloat( const float * aNormalizedFloatArray ) void CIMAGE::SetPixelsFromNormalizedFloat( const float * aNormalizedFloatArray )
{ {
for( unsigned int i = 0; i < m_wxh; i++ ) for( unsigned int i = 0; i < m_wxh; i++ )
{ {
...@@ -370,26 +418,23 @@ void CIMAGE::setPixelsFromNormalizedFloat( const float * aNormalizedFloatArray ) ...@@ -370,26 +418,23 @@ void CIMAGE::setPixelsFromNormalizedFloat( const float * aNormalizedFloatArray )
} }
void CIMAGE::saveAsPNG( wxString aFileName ) void CIMAGE::SaveAsPNG( wxString aFileName ) const
{ {
unsigned char* pixelbuffer = (unsigned char*) malloc( m_wxh * 3 ); unsigned char* pixelbuffer = (unsigned char*) malloc( m_wxh * 3 );
//unsigned char* alphabuffer = (unsigned char*) malloc( m_width * aHeight );
wxImage image( m_width, m_height ); wxImage image( m_width, m_height );
for( unsigned int i = 0; i < m_wxh; i++) for( unsigned int i = 0; i < m_wxh; i++)
{ {
unsigned char v = m_pixels[i]; unsigned char v = m_pixels[i];
// Set RGB value with all same values intensities
pixelbuffer[i * 3 + 0] = v; pixelbuffer[i * 3 + 0] = v;
pixelbuffer[i * 3 + 1] = v; pixelbuffer[i * 3 + 1] = v;
pixelbuffer[i * 3 + 2] = v; pixelbuffer[i * 3 + 2] = v;
//alphabuffer[i * 1 + 0] = aRGBABufferImage[i * 4 + 3];
} }
image.SetData( pixelbuffer ); image.SetData( pixelbuffer );
//image.SetAlpha( alphabuffer );
image = image.Mirror( false ); image = image.Mirror( false );
image.SaveFile( aFileName + ".png", wxBITMAP_TYPE_PNG ); image.SaveFile( aFileName + ".png", wxBITMAP_TYPE_PNG );
image.Destroy(); image.Destroy();
} }
...@@ -22,11 +22,17 @@ ...@@ -22,11 +22,17 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
/**
* @file CImage.h
* @brief one 8bit-channel image definition
*/
#ifndef CImage_h #ifndef CImage_h
#define CImage_h #define CImage_h
#include <wx/image.h> #include <wx/string.h>
/// Image operation type
enum E_IMAGE_OP { enum E_IMAGE_OP {
COPY_RAW, COPY_RAW,
COPY_ADD, COPY_ADD,
...@@ -41,17 +47,23 @@ enum E_IMAGE_OP { ...@@ -41,17 +47,23 @@ enum E_IMAGE_OP {
COPY_MAX COPY_MAX
}; };
/// Image wrap type enumeration
enum E_WRAP { enum E_WRAP {
WRAP_ZERO, ///< Coords that wraps are not evaluated WRAP_ZERO, ///< Coords that wraps are not evaluated
WRAP_CLAMP, WRAP_CLAMP, ///< Coords are clamped to image size
WRAP_WRAP ///< Coords are wrapped arround WRAP_WRAP ///< Coords are wrapped arround
}; };
/// Filter type enumeration
enum E_FILTER { enum E_FILTER {
FILTER_HIPASS, FILTER_HIPASS,
FILTER_BLUR FILTER_GAUSSIAN_BLUR,
FILTER_INVERT_BLUR,
}; };
/// 5x5 Filter struct parameters
typedef struct { typedef struct {
signed char kernel[5][5]; signed char kernel[5][5];
unsigned char div; unsigned char div;
...@@ -59,36 +71,120 @@ typedef struct { ...@@ -59,36 +71,120 @@ typedef struct {
}S_FILTER; }S_FILTER;
/**
* Class CIMAGE
* manages a 8-bit channel image
*/
class CIMAGE class CIMAGE
{ {
public: public:
CIMAGE( unsigned int xsize, unsigned int ysize ); /**
* Constructor CIMAGE
* constructs a CIMAGE based on image size
* @param aXsize x size
* @param aYsize y size
*/
CIMAGE( unsigned int aXsize, unsigned int aYsize );
~CIMAGE(); ~CIMAGE();
void setpixel( int x, int y, unsigned char value ); /**
unsigned char getpixel( int x, int y ); * Function Setpixel
* set a value in a pixel position, position is clamped in accord with the
* current clamp settings
* @param aX x position
* @param aY y position
* @param aValue value to set the pixel
*/
void Setpixel( int aX, int aY, unsigned char aValue );
/**
* Function Getpixel
* get the pixel value from pixel position, position is clamped in accord with the
* current clamp settings
* @param aX x position
* @param aY y position
* @return unsigned char - pixel value
*/
unsigned char Getpixel( int aX, int aY ) const;
/**
* Function CopyFull
* perform a copy operation, based on operation type. The result destination is the self image class
* @param aImgA an image input
* @param aImgB an image input
* @param aOperation operation to perform
* COPY_RAW this <- aImgA
* COPY_ADD this <- CLAMP(aImgA + aImgB)
* COPY_SUB this <- CLAMP(aImgA - aImgB)
* COPY_DIF this <- abs(aImgA - aImgB)
* COPY_MUL this <- aImgA * aImgB
* COPY_AND this <- aImgA & aImgB
* COPY_OR this <- aImgA | aImgB
* COPY_XOR this <- aImgA ^ aImgB
* COPY_BLEND50 this <- (aImgA + aImgB) / 2
* COPY_MIN this <- (aImgA < aImgB)?aImgA:aImgB
* COPY_MAX this <- (aImgA > aImgB)?aImgA:aImgB
*/
void CopyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOperation );
void copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOperation ); /**
* Function Invert
* invert the values of image this <- (255 - this)
*/
void Invert();
/**
* Function EfxFilter
* apply a filter to the input image and stores it in the image class
* this <- FilterType(aInImg)
* @param aInImg input image
* @param aFilterType filter type to apply
*/
void EfxFilter( CIMAGE *aInImg, E_FILTER aFilterType );
void invert(); /**
* Function SaveAsPNG
* save image buffer to a PNG file into the working folder.
* each of RGB channel will have the 8bit-channel from the image.
* @param aFileName fime name (without extension)
*/
void SaveAsPNG( wxString aFileName ) const;
void efxFilter( CIMAGE *aInImg, float aGain, E_FILTER aFilterType ); /**
* Function SetPixelsFromNormalizedFloat
* set the current channel from a float normalized (0.0 - 1.0) buffer
* this <- CLAMP(NormalizedFloat * 255)
* @param aNormalizedFloatArray a float array with the same size of the image
*/
void SetPixelsFromNormalizedFloat( const float * aNormalizedFloatArray );
void saveAsPNG( wxString aFileName ); /**
* Function GetBuffer
* get the image buffer pointer
* @return unsigned char * - the pointer of the buffer 8bit channel
*/
unsigned char* GetBuffer() const;
void setPixelsFromNormalizedFloat( const float * aNormalizedFloatArray );
private: private:
bool wrapCoords( int *xo, int *yo );
public: /**
unsigned char* m_pixels; * Function wrapCoords
unsigned int m_width; * calculate the coordinates points in accord with the current clamping settings
unsigned int m_height; * @param aXo X coordinate to be converted (output)
unsigned int m_wxh; * @param aXo Y coordinate to be converted (output)
E_WRAP m_wraping; * @return bool - true if the coordinates are inside the image, false otherwise
*/
bool wrapCoords( int *aXo, int *aYo ) const;
private:
unsigned char* m_pixels; ///< buffer to store the image 8bit-channel
unsigned int m_width; ///< width of the image
unsigned int m_height; ///< height of the image
unsigned int m_wxh; ///< width * height precalc value
E_WRAP m_wraping; ///< current wrapping type
}; };
#endif #endif // CImage_h
...@@ -31,6 +31,7 @@ set(3D-VIEWER_SRCS ...@@ -31,6 +31,7 @@ set(3D-VIEWER_SRCS
vrml_v2_modelparser.cpp vrml_v2_modelparser.cpp
x3dmodelparser.cpp x3dmodelparser.cpp
CImage.cpp CImage.cpp
CBBox.cpp
) )
add_library(3d-viewer STATIC ${3D-VIEWER_SRCS}) add_library(3d-viewer STATIC ${3D-VIEWER_SRCS})
......
...@@ -231,10 +231,19 @@ void INFO3D_VISU::InitSettings( BOARD* aBoard ) ...@@ -231,10 +231,19 @@ void INFO3D_VISU::InitSettings( BOARD* aBoard )
*/ */
double INFO3D_VISU::GetModulesZcoord3DIU( bool aIsFlipped ) double INFO3D_VISU::GetModulesZcoord3DIU( bool aIsFlipped )
{ {
// NOTE: Z position to display modules in top of Paste and near the shadow
if( aIsFlipped ) if( aIsFlipped )
return m_layerZcoord[B_Paste] - ( m_copperThickness / 2 ); {
if( g_Parm_3D_Visu.GetFlag( FL_SOLDERPASTE ) )
return m_layerZcoord[B_SilkS] - ( m_copperThickness / 2.0 );
else
return m_layerZcoord[B_Paste] - ( m_copperThickness / 2.0 );
}
else else
return m_layerZcoord[F_Paste] + ( m_copperThickness / 2 ); {
if( g_Parm_3D_Visu.GetFlag( FL_SOLDERPASTE ) )
return m_layerZcoord[F_SilkS] + ( m_copperThickness / 2.0 );
else
return m_layerZcoord[F_Paste] + ( m_copperThickness / 2.0 );
}
} }
...@@ -78,6 +78,7 @@ enum DISPLAY3D_FLG { ...@@ -78,6 +78,7 @@ enum DISPLAY3D_FLG {
FL_RENDER_SMOOTH_NORMALS, FL_RENDER_SMOOTH_NORMALS,
FL_RENDER_USE_MODEL_NORMALS, FL_RENDER_USE_MODEL_NORMALS,
FL_RENDER_MATERIAL, FL_RENDER_MATERIAL,
FL_RENDER_SHOW_MODEL_BBOX,
FL_LAST FL_LAST
}; };
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include <3d_mesh_model.h> #include <3d_mesh_model.h>
class S3D_MASTER; class S3D_MASTER;
class S3D_MODEL_PARSER;
class X3D_MODEL_PARSER; class X3D_MODEL_PARSER;
/** /**
...@@ -49,13 +48,7 @@ public: ...@@ -49,13 +48,7 @@ public:
master( aMaster ) master( aMaster )
{} {}
~S3D_MODEL_PARSER() virtual ~S3D_MODEL_PARSER(){}
{
for( unsigned int idx = 0; idx < childs.size(); idx++ )
{
delete childs[idx];
}
}
S3D_MASTER* GetMaster() S3D_MASTER* GetMaster()
{ {
...@@ -73,22 +66,14 @@ public: ...@@ -73,22 +66,14 @@ public:
static S3D_MODEL_PARSER* Create( S3D_MASTER* aMaster, const wxString aExtension ); static S3D_MODEL_PARSER* Create( S3D_MASTER* aMaster, const wxString aExtension );
/** /**
* pure virtual Function * virtual Function
* Concrete parsers should implement this function * Concrete parsers should implement this function
* @param aFilename = the full file name of the file to load * @param aFilename = the full file name of the file to load
* @return true if as succeeded * @return true if as succeeded
*/ */
virtual bool Load( const wxString& aFilename ) = 0; virtual bool Load( const wxString& aFilename ) {
return false;
/** };
* Function Render
* Render the model to openGL. The arguments can be both false but just only one
* can be true.
* @param aIsRenderingJustNonTransparentObjects
* @param aIsRenderingJustTransparentObjects
*/
void Render( bool aIsRenderingJustNonTransparentObjects,
bool aIsRenderingJustTransparentObjects );
std::vector< S3D_MESH* > childs; std::vector< S3D_MESH* > childs;
...@@ -158,6 +143,7 @@ private: ...@@ -158,6 +143,7 @@ private:
typedef std::map< std::string, std::vector< glm::vec3 > > VRML2_COORDINATE_MAP; typedef std::map< std::string, std::vector< glm::vec3 > > VRML2_COORDINATE_MAP;
typedef std::map< std::string, S3D_MESH* > VRML2_DEF_GROUP_MAP;
/** /**
* class VRML2_MODEL_PARSER * class VRML2_MODEL_PARSER
...@@ -171,6 +157,15 @@ public: ...@@ -171,6 +157,15 @@ public:
bool Load( const wxString& aFilename ); bool Load( const wxString& aFilename );
/**
* Function Load
* Load a VRML2 filename and apply a transformation to the root
* @param aFilename file name with path
* @param aTransformationModel a model with translation, rotation and scale to apply to default root
* @return bool - true if finnished with success
*/
bool Load( const wxString& aFilename, S3D_MESH *aTransformationModel );
/** /**
* Return string representing VRML2 file in vrml2 format * Return string representing VRML2 file in vrml2 format
* Function Load must be called before this function, otherwise empty * Function Load must be called before this function, otherwise empty
...@@ -179,6 +174,7 @@ public: ...@@ -179,6 +174,7 @@ public:
wxString VRML2_representation(); wxString VRML2_representation();
private: private:
int loadFileModel( S3D_MESH *transformationModel );
int read_Transform(); int read_Transform();
int read_DEF(); int read_DEF();
int read_DEF_Coordinate(); int read_DEF_Coordinate();
...@@ -195,16 +191,33 @@ private: ...@@ -195,16 +191,33 @@ private:
int read_Color(); int read_Color();
int read_coordIndex(); int read_coordIndex();
int read_colorIndex(); int read_colorIndex();
int read_USE(); int read_geometry();
int read_IndexedFaceSet_USE();
int read_Transform_USE();
int read_Inline();
/** Function debug_enter
* Used in debug to increase a ' ' in the m_debugSpacer,
* should be called after the first debug comment in a function
*/
void debug_enter();
/** Function debug_exit
* Used in debug to decrease a ' ' in the m_debugSpacer,
* should be called before the last debug comment in a funtion before exit
*/
void debug_exit();
bool m_normalPerVertex; bool m_normalPerVertex;
bool colorPerVertex; bool colorPerVertex;
S3D_MESH* m_model; S3D_MESH* m_model; ///< It stores the current model that the parsing is adding data
FILE* m_file; FILE* m_file;
wxString m_Filename; wxFileName m_Filename;
VRML2_COORDINATE_MAP m_defCoordinateMap; VRML2_COORDINATE_MAP m_defCoordinateMap;
VRML2_DEF_GROUP_MAP m_defGroupMap; ///< Stores a list of labels for groups and meshs that will be used later by the USE keyword
S3D_MODEL_PARSER* m_ModelParser; S3D_MODEL_PARSER* m_ModelParser;
S3D_MASTER* m_Master; S3D_MASTER* m_Master;
wxString m_debugSpacer; ///< Used to give identation space
}; };
...@@ -267,7 +280,6 @@ public: ...@@ -267,7 +280,6 @@ public:
* by the vrml file data * by the vrml file data
*/ */
VRML_MODEL_PARSER( S3D_MASTER* aMaster ); VRML_MODEL_PARSER( S3D_MASTER* aMaster );
~VRML_MODEL_PARSER(); ~VRML_MODEL_PARSER();
/** /**
...@@ -279,11 +291,6 @@ public: ...@@ -279,11 +291,6 @@ public:
* to our internal units. * to our internal units.
*/ */
bool Load( const wxString& aFilename ); bool Load( const wxString& aFilename );
private:
S3D_MASTER* m_curr3DShape; ///< the current 3D shape to build from the file
VRML1_MODEL_PARSER* vrml1_parser;
VRML2_MODEL_PARSER* vrml2_parser;
}; };
......
/* /*
* 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-2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 1992-2015 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
...@@ -24,11 +24,58 @@ ...@@ -24,11 +24,58 @@
/** /**
* @file vrml_aux.cpp * @file vrml_aux.cpp
* @brief implements auxiliar functions to parse VRML files
*/ */
#include "vrml_aux.h" #include "vrml_aux.h"
bool GetString( FILE* File, char* aDstString, size_t maxDstLen )
{
if( (!aDstString) || (maxDstLen == 0) )
return false;
int c;
while( ( c = fgetc( File ) ) != EOF )
{
if( c == '\"' )
{
break;
}
}
if( c != '\"' )
{
return false;
}
while( (( c = fgetc( File ) ) != EOF) && (maxDstLen > 0) )
{
if( c == '\"' )
{
break;
}
maxDstLen--;
*aDstString = c;
aDstString++;
}
*aDstString = 0;
if( c == '\"' )
{
return true;
}
return false;
}
static int SkipGetChar ( FILE* File ); static int SkipGetChar ( FILE* File );
...@@ -140,7 +187,7 @@ bool GetNextTag( FILE* File, char* tag, size_t len ) ...@@ -140,7 +187,7 @@ bool GetNextTag( FILE* File, char* tag, size_t len )
} }
int read_NotImplemented( FILE* File, char closeChar ) int Read_NotImplemented( FILE* File, char closeChar )
{ {
int c; int c;
...@@ -150,12 +197,12 @@ int read_NotImplemented( FILE* File, char closeChar ) ...@@ -150,12 +197,12 @@ int read_NotImplemented( FILE* File, char closeChar )
if( c == '{' ) if( c == '{' )
{ {
// DBG( printf( "{\n") ); // DBG( printf( "{\n") );
read_NotImplemented( File, '}' ); Read_NotImplemented( File, '}' );
} }
else if( c == '[' ) else if( c == '[' )
{ {
// DBG( printf( "[\n") ); // DBG( printf( "[\n") );
read_NotImplemented( File, ']' ); Read_NotImplemented( File, ']' );
} }
else if( c == closeChar ) else if( c == closeChar )
{ {
...@@ -169,15 +216,15 @@ int read_NotImplemented( FILE* File, char closeChar ) ...@@ -169,15 +216,15 @@ int read_NotImplemented( FILE* File, char closeChar )
} }
int parseVertexList( FILE* File, std::vector<glm::vec3>& dst_vector ) int ParseVertexList( FILE* File, std::vector<glm::vec3>& dst_vector )
{ {
// DBG( printf( " parseVertexList\n" ) ); // DBG( printf( " ParseVertexList\n" ) );
dst_vector.clear(); dst_vector.clear();
glm::vec3 vertex; glm::vec3 vertex;
while( parseVertex( File, vertex ) == 3 ) while( ParseVertex( File, vertex ) == 3 )
{ {
dst_vector.push_back( vertex ); dst_vector.push_back( vertex );
} }
...@@ -186,7 +233,7 @@ int parseVertexList( FILE* File, std::vector<glm::vec3>& dst_vector ) ...@@ -186,7 +233,7 @@ int parseVertexList( FILE* File, std::vector<glm::vec3>& dst_vector )
} }
int parseVertex( FILE* File, glm::vec3& dst_vertex ) int ParseVertex( FILE* File, glm::vec3& dst_vertex )
{ {
float a, b, c; float a, b, c;
int ret = fscanf( File, "%e %e %e", &a, &b, &c ); int ret = fscanf( File, "%e %e %e", &a, &b, &c );
...@@ -209,7 +256,7 @@ int parseVertex( FILE* File, glm::vec3& dst_vertex ) ...@@ -209,7 +256,7 @@ int parseVertex( FILE* File, glm::vec3& dst_vertex )
} }
int parseFloat( FILE* File, float* dst_float ) int ParseFloat( FILE* File, float* dst_float )
{ {
float value; float value;
int ret = fscanf( File, "%e", &value ); int ret = fscanf( File, "%e", &value );
......
/* /*
* 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-2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2014 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
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
/** /**
* @file vrml_aux.h * @file vrml_aux.h
* @brief auxiliar functions to parse VRML files
*/ */
#ifndef _VRML_AUX_H #ifndef _VRML_AUX_H
...@@ -48,10 +49,63 @@ ...@@ -48,10 +49,63 @@
#endif #endif
#include <wx/glcanvas.h> #include <wx/glcanvas.h>
int read_NotImplemented( FILE* File, char closeChar); /**
int parseVertexList( FILE* File, std::vector< glm::vec3 > &dst_vector); * Function GetEpoxyThicknessBIU
int parseVertex( FILE* File, glm::vec3 &dst_vertex ); * skip a VRML block and eventualy internal blocks until it find the close char
int parseFloat( FILE* File, float *dst_float ); * @param File file to read from
* @param closeChar the expected close char of the block
* @return int - -1 if failed, 0 if OK
*/
int Read_NotImplemented( FILE* File, char closeChar);
/**
* Function ParseVertexList
* parse a vertex list
* @param File file to read from
* @param dst_vector destination vector list
* @return int - -1 if failed, 0 if OK
*/
int ParseVertexList( FILE* File, std::vector< glm::vec3 > &dst_vector);
/**
* Function ParseVertex
* parse a vertex
* @param File file to read from
* @param dst_vertex destination vector
* @return int - return the number of elements readed
*/
int ParseVertex( FILE* File, glm::vec3 &dst_vertex );
/**
* Function ParseFloat
* parse a float value
* @param File file to read from
* @param dst_float destination float
* @return int - Return the number of floats readed
*/
int ParseFloat( FILE* File, float *dst_float );
/**
* Function GetNextTag
* parse the next tag
* @param File file to read from
* @param tag destination pointer
* @param len max length of storage
* @return bool - true if succeeded, false if EOF
*/
bool GetNextTag( FILE* File, char* tag, size_t len ); bool GetNextTag( FILE* File, char* tag, size_t len );
/**
* Function GetString
* parse a string, it expects starting by " and end with "
* @param File file to read from
* @param aDstString destination pointer
* @param maxDstLen max length of storage
* @return bool - true if successful read the string, false if failed to get a string
*/
bool GetString( FILE* File, char* aDstString, size_t maxDstLen );
#endif #endif
...@@ -138,7 +138,7 @@ int VRML1_MODEL_PARSER::read_separator() ...@@ -138,7 +138,7 @@ int VRML1_MODEL_PARSER::read_separator()
else if( ( *text != '}' ) ) else if( ( *text != '}' ) )
{ {
// DBG( printf( "read_NotImplemented %s\n", text ) ); // DBG( printf( "read_NotImplemented %s\n", text ) );
read_NotImplemented( m_file, '}' ); Read_NotImplemented( m_file, '}' );
} }
else else
break; break;
...@@ -272,7 +272,7 @@ int VRML1_MODEL_PARSER::readMaterial_ambientColor() ...@@ -272,7 +272,7 @@ int VRML1_MODEL_PARSER::readMaterial_ambientColor()
{ {
// DBG( printf( " readMaterial_ambientColor\n" ) ); // DBG( printf( " readMaterial_ambientColor\n" ) );
return parseVertexList( m_file, m_model->m_Materials->m_AmbientColor ); return ParseVertexList( m_file, m_model->m_Materials->m_AmbientColor );
} }
...@@ -280,7 +280,7 @@ int VRML1_MODEL_PARSER::readMaterial_diffuseColor() ...@@ -280,7 +280,7 @@ int VRML1_MODEL_PARSER::readMaterial_diffuseColor()
{ {
// DBG( printf( " readMaterial_diffuseColor\n" ) ); // DBG( printf( " readMaterial_diffuseColor\n" ) );
return parseVertexList( m_file, m_model->m_Materials->m_DiffuseColor ); return ParseVertexList( m_file, m_model->m_Materials->m_DiffuseColor );
} }
...@@ -288,7 +288,7 @@ int VRML1_MODEL_PARSER::readMaterial_emissiveColor() ...@@ -288,7 +288,7 @@ int VRML1_MODEL_PARSER::readMaterial_emissiveColor()
{ {
// DBG( printf( " readMaterial_emissiveColor\n" ) ); // DBG( printf( " readMaterial_emissiveColor\n" ) );
int ret = parseVertexList( m_file, m_model->m_Materials->m_EmissiveColor ); int ret = ParseVertexList( m_file, m_model->m_Materials->m_EmissiveColor );
if( m_Master->m_use_modelfile_emissiveColor == false ) if( m_Master->m_use_modelfile_emissiveColor == false )
{ {
...@@ -303,7 +303,7 @@ int VRML1_MODEL_PARSER::readMaterial_specularColor() ...@@ -303,7 +303,7 @@ int VRML1_MODEL_PARSER::readMaterial_specularColor()
{ {
// DBG( printf( " readMaterial_specularColor\n" ) ); // DBG( printf( " readMaterial_specularColor\n" ) );
int ret = parseVertexList( m_file, m_model->m_Materials->m_SpecularColor ); int ret = ParseVertexList( m_file, m_model->m_Materials->m_SpecularColor );
if( m_Master->m_use_modelfile_specularColor == false ) if( m_Master->m_use_modelfile_specularColor == false )
{ {
...@@ -368,7 +368,7 @@ int VRML1_MODEL_PARSER::readCoordinate3_point() ...@@ -368,7 +368,7 @@ int VRML1_MODEL_PARSER::readCoordinate3_point()
{ {
// DBG( printf( " readCoordinate3_point\n" ) ); // DBG( printf( " readCoordinate3_point\n" ) );
if( parseVertexList( m_file, m_model->m_Point ) == 0 ) if( ParseVertexList( m_file, m_model->m_Point ) == 0 )
{ {
return 0; return 0;
} }
......
/* /*
* 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-2015 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 2013 Tuomas Vaherkoski <tuomasvaherkoski@gmail.com> * Copyright (C) 2013 Tuomas Vaherkoski <tuomasvaherkoski@gmail.com>
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras@wanadoo.fr * Copyright (C) 2012 Jean-Pierre Charras, jp.charras@wanadoo.fr
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net> * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#include "modelparsers.h" #include "modelparsers.h"
#include "vrml_aux.h" #include "vrml_aux.h"
#define BUFLINE_SIZE 32 #define BUFLINE_SIZE 1024
/** /**
* Trace mask used to enable or disable the trace output of the VRML V2 parser code. * Trace mask used to enable or disable the trace output of the VRML V2 parser code.
...@@ -58,6 +58,7 @@ VRML2_MODEL_PARSER::VRML2_MODEL_PARSER( S3D_MODEL_PARSER* aModelParser ) ...@@ -58,6 +58,7 @@ VRML2_MODEL_PARSER::VRML2_MODEL_PARSER( S3D_MODEL_PARSER* aModelParser )
m_file = NULL; m_file = NULL;
m_normalPerVertex = true; m_normalPerVertex = true;
colorPerVertex = true; colorPerVertex = true;
m_debugSpacer = "";
} }
...@@ -65,25 +66,83 @@ VRML2_MODEL_PARSER::~VRML2_MODEL_PARSER() ...@@ -65,25 +66,83 @@ VRML2_MODEL_PARSER::~VRML2_MODEL_PARSER()
{ {
} }
void VRML2_MODEL_PARSER::debug_enter()
{
m_debugSpacer.Append(' ');
}
void VRML2_MODEL_PARSER::debug_exit()
{
m_debugSpacer.RemoveLast();
}
bool VRML2_MODEL_PARSER::Load( const wxString& aFilename ) bool VRML2_MODEL_PARSER::Load( const wxString& aFilename )
{ {
char text[BUFLINE_SIZE]; wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Loading: %s" ), GetChars( aFilename ) );
debug_enter();
m_file = wxFopen( aFilename, wxT( "rt" ) );
if( m_file == NULL )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Failed to open file: %s" ), GetChars( aFilename ) );
return false;
}
m_Filename = aFilename;
// Switch the locale to standard C (needed to print floating point numbers)
LOCALE_IO toggle;
loadFileModel( NULL );
fclose( m_file );
debug_exit();
return true;
}
wxLogTrace( traceVrmlV2Parser, wxT( "Loading: %s" ), GetChars( aFilename ) ); bool VRML2_MODEL_PARSER::Load( const wxString& aFilename, S3D_MESH *aTransformationModel )
{
if( aTransformationModel )
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Loading: %s" ), GetChars( aFilename ) );
debug_enter();
m_file = wxFopen( aFilename, wxT( "rt" ) ); m_file = wxFopen( aFilename, wxT( "rt" ) );
if( m_file == NULL ) if( m_file == NULL )
{ {
wxLogTrace( traceVrmlV2Parser, wxT( "Failed to open file: %s" ), GetChars( aFilename ) ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Failed to open file: %s" ), GetChars( aFilename ) );
return false; return false;
} }
m_Filename = aFilename;
// Switch the locale to standard C (needed to print floating point numbers) // Switch the locale to standard C (needed to print floating point numbers)
LOCALE_IO toggle; LOCALE_IO toggle;
m_ModelParser->childs.clear(); loadFileModel( aTransformationModel );
fclose( m_file );
debug_exit();
return true;
}
debug_exit();
return false;
}
int VRML2_MODEL_PARSER::loadFileModel( S3D_MESH *aTransformationModel )
{
char text[BUFLINE_SIZE];
debug_enter();
while( GetNextTag( m_file, text, sizeof(text) ) ) while( GetNextTag( m_file, text, sizeof(text) ) )
{ {
...@@ -95,49 +154,125 @@ bool VRML2_MODEL_PARSER::Load( const wxString& aFilename ) ...@@ -95,49 +154,125 @@ bool VRML2_MODEL_PARSER::Load( const wxString& aFilename )
if( strcmp( text, "Transform" ) == 0 ) if( strcmp( text, "Transform" ) == 0 )
{ {
m_model = new S3D_MESH(); m_model = new S3D_MESH();
m_ModelParser->childs.push_back( m_model );
if( read_Transform() == 0) S3D_MESH* save_ptr = m_model;
if( read_Transform() == 0 )
{
m_model = save_ptr;
if( ((m_model->m_Point.size() == 0) || (m_model->m_CoordIndex.size() == 0)) &&
(m_model->childs.size() == 0) )
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " m_Point.size: %u" ), (unsigned int)m_model->m_Point.size() ); delete m_model;
//wxLogTrace( traceVrmlV2Parser, wxT( " m_CoordIndex.size: %u" ), (unsigned int)m_model->m_CoordIndex.size() ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "loadFileModel: skipping model with no points or childs" ) );
}
else
{
if( aTransformationModel )
{
m_model->m_translation = aTransformationModel->m_translation;
m_model->m_rotation = aTransformationModel->m_rotation;
m_model->m_scale = aTransformationModel->m_scale;
}
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "loadFileModel: Add model with %lu points, %lu coordIndex, %lu childs." ),
m_model->m_Point.size(),
m_model->m_CoordIndex.size(),
m_model->childs.size() );
m_ModelParser->childs.push_back( m_model );
}
}
else
{
delete m_model;
} }
} }
else if( strcmp( text, "DEF" ) == 0 ) else if( strcmp( text, "DEF" ) == 0 )
{ {
m_model = new S3D_MESH(); m_model = new S3D_MESH();
m_ModelParser->childs.push_back( m_model );
S3D_MESH* save_ptr = m_model;
if( read_DEF() == 0 ) if( read_DEF() == 0 )
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " m_Point.size: %u" ), (unsigned int)m_model->m_Point.size() ); m_model = save_ptr;
//wxLogTrace( traceVrmlV2Parser, wxT( " m_CoordIndex.size: %u" ), (unsigned int)m_model->m_CoordIndex.size() );
if( ((m_model->m_Point.size() == 0) || (m_model->m_CoordIndex.size() == 0)) &&
(m_model->childs.size() == 0) )
{
delete m_model;
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "loadFileModel: skipping model with no points or childs" ) );
}
else
{
if( aTransformationModel )
{
m_model->m_translation = aTransformationModel->m_translation;
m_model->m_rotation = aTransformationModel->m_rotation;
m_model->m_scale = aTransformationModel->m_scale;
}
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "loadFileModel: Add model with %lu points, %lu coordIndex, %lu childs." ),
m_model->m_Point.size(),
m_model->m_CoordIndex.size(),
m_model->childs.size() );
m_ModelParser->childs.push_back( m_model );
}
}
else
{
delete m_model;
} }
} }
else if( strcmp( text, "Shape" ) == 0 ) else if( strcmp( text, "Shape" ) == 0 )
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " Shape" ) );
m_model = new S3D_MESH(); m_model = new S3D_MESH();
m_ModelParser->childs.push_back( m_model );
S3D_MESH* save_ptr = m_model;
if( read_Shape() == 0 ) if( read_Shape() == 0 )
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " m_Point.size: %u" ), (unsigned int)m_model->m_Point.size() ); m_model = save_ptr;
//wxLogTrace( traceVrmlV2Parser, wxT( " m_CoordIndex.size: %u" ), (unsigned int)m_model->m_CoordIndex.size() );
} if( ((m_model->m_Point.size() == 0) || (m_model->m_CoordIndex.size() == 0)) &&
(m_model->childs.size() == 0) )
{
delete m_model;
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "loadFileModel: skipping model with no points or childs" ) );
} }
else
{
if( aTransformationModel )
{
m_model->m_translation = aTransformationModel->m_translation;
m_model->m_rotation = aTransformationModel->m_rotation;
m_model->m_scale = aTransformationModel->m_scale;
} }
fclose( m_file ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "loadFileModel: Add model with %lu points, %lu coordIndex, %lu childs." ),
m_model->m_Point.size(),
m_model->m_CoordIndex.size(),
m_model->childs.size() );
return true; m_ModelParser->childs.push_back( m_model );
}
}
else
{
delete m_model;
}
}
}
debug_exit();
return 0;
} }
int VRML2_MODEL_PARSER::read_Transform() int VRML2_MODEL_PARSER::read_Transform()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_Transform" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform" ) );
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
...@@ -150,17 +285,50 @@ int VRML2_MODEL_PARSER::read_Transform() ...@@ -150,17 +285,50 @@ int VRML2_MODEL_PARSER::read_Transform()
if( *text == '}' ) if( *text == '}' )
{ {
break; debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform exit" ) );
return 0;
}
if( strcmp( text, "Transform" ) == 0 )
{
m_model = new S3D_MESH();
S3D_MESH* save_ptr = m_model;
if( read_Transform() == 0 )
{
m_model = save_ptr;
if( ((m_model->m_Point.size() == 0) || (m_model->m_CoordIndex.size() == 0)) &&
(m_model->childs.size() == 0) )
{
delete m_model;
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform: skipping model with no points or childs" ) );
} }
else
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform: Add child model with %lu points, %lu coordIndex, %lu childs." ),
m_model->m_Point.size(),
m_model->m_CoordIndex.size(),
m_model->childs.size() );
if( strcmp( text, "translation" ) == 0 ) m_ModelParser->childs.push_back( m_model );
}
}
else
{ {
parseVertex( m_file, m_model->m_translation ); delete m_model;
}
}
else if( strcmp( text, "translation" ) == 0 )
{
ParseVertex( m_file, m_model->m_translation );
//wxLogTrace( traceVrmlV2Parser, wxT( " translation (%f,%f,%f)" ), wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "translation (%f,%f,%f)" ),
// m_model->m_translation.x, m_model->m_translation.x,
// m_model->m_translation.y, m_model->m_translation.y,
// m_model->m_translation.z ); m_model->m_translation.z );
} }
else if( strcmp( text, "rotation" ) == 0 ) else if( strcmp( text, "rotation" ) == 0 )
{ {
...@@ -174,39 +342,41 @@ int VRML2_MODEL_PARSER::read_Transform() ...@@ -174,39 +342,41 @@ int VRML2_MODEL_PARSER::read_Transform()
m_model->m_rotation[2] = 0.0f; m_model->m_rotation[2] = 0.0f;
m_model->m_rotation[3] = 0.0f; m_model->m_rotation[3] = 0.0f;
wxLogTrace( traceVrmlV2Parser, wxT( " rotation failed, setting to zeros" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "rotation failed, setting to zeros" ) );
} }
else else
{ {
m_model->m_rotation[3] = m_model->m_rotation[3] * 180.0f / 3.14f; // !TODO: use constants or functions m_model->m_rotation[3] = m_model->m_rotation[3] * 180.0f / 3.14f; // !TODO: use constants or functions
} }
//wxLogTrace( traceVrmlV2Parser, wxT( " rotation (%f,%f,%f,%f)" ), wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "rotation (%f,%f,%f,%f)" ),
// m_model->m_rotation[0], m_model->m_rotation[0],
// m_model->m_rotation[1], m_model->m_rotation[1],
// m_model->m_rotation[2], m_model->m_rotation[2],
// m_model->m_rotation[3] ); m_model->m_rotation[3] );
} }
else if( strcmp( text, "scale" ) == 0 ) else if( strcmp( text, "scale" ) == 0 )
{ {
parseVertex( m_file, m_model->m_scale ); ParseVertex( m_file, m_model->m_scale );
//wxLogTrace( traceVrmlV2Parser, wxT( " scale (%f,%f,%f)" ), m_model->m_scale.x, m_model->m_scale.y, m_model->m_scale.z ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "scale (%f,%f,%f)" ), m_model->m_scale.x, m_model->m_scale.y, m_model->m_scale.z );
} }
else if( strcmp( text, "scaleOrientation" ) == 0 ) else if( strcmp( text, "scaleOrientation" ) == 0 )
{ {
// this m_scaleOrientation is not implemented, but it will be parsed wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "scaleOrientation is not implemented, but it will be parsed" ) );
if( fscanf( m_file, "%f %f %f %f", &m_model->m_scaleOrientation[0],
&m_model->m_scaleOrientation[1], glm::vec4 vecDummy;
&m_model->m_scaleOrientation[2], if( fscanf( m_file, "%f %f %f %f", &vecDummy[0],
&m_model->m_scaleOrientation[3] ) != 4 ) &vecDummy[1],
&vecDummy[2],
&vecDummy[3] ) != 4 )
{ {
m_model->m_scaleOrientation[0] = 0.0f; vecDummy[0] = 0.0f;
m_model->m_scaleOrientation[1] = 0.0f; vecDummy[1] = 0.0f;
m_model->m_scaleOrientation[2] = 0.0f; vecDummy[2] = 0.0f;
m_model->m_scaleOrientation[3] = 0.0f; vecDummy[3] = 0.0f;
wxLogTrace( traceVrmlV2Parser, wxT( " scaleOrientation failed, setting to zeros" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "scaleOrientation failed, setting to zeros" ) );
} }
//wxLogTrace( traceVrmlV2Parser, wxT( " scaleOrientation (%f,%f,%f,%f)" ), //wxLogTrace( traceVrmlV2Parser, wxT( " scaleOrientation (%f,%f,%f,%f)" ),
...@@ -217,9 +387,11 @@ int VRML2_MODEL_PARSER::read_Transform() ...@@ -217,9 +387,11 @@ int VRML2_MODEL_PARSER::read_Transform()
} }
else if( strcmp( text, "center" ) == 0 ) else if( strcmp( text, "center" ) == 0 )
{ {
parseVertex( m_file, m_model->m_center ); // this is not used
glm::vec3 vecDummy;
ParseVertex( m_file, vecDummy );
//wxLogTrace( traceVrmlV2Parser, wxT( " center (%f,%f,%f)" ), m_model->m_center.x, m_model->m_center.y, m_model->m_center.z ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "center is not implemented (%f,%f,%f)" ), vecDummy.x, vecDummy.y, vecDummy.z );
} }
else if( strcmp( text, "children" ) == 0 ) else if( strcmp( text, "children" ) == 0 )
{ {
...@@ -244,21 +416,52 @@ int VRML2_MODEL_PARSER::read_Transform() ...@@ -244,21 +416,52 @@ int VRML2_MODEL_PARSER::read_Transform()
} }
else if( strcmp( text, "Group" ) == 0 ) else if( strcmp( text, "Group" ) == 0 )
{ {
// skip // Keep looking for things in a transform
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Group" ) );
read_Transform();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Transform Group exit" ) );
//return ret;
}
else if( strcmp( text, "Inline" ) == 0 )
{
read_Inline();
} }
else if( strcmp( text, "Shape" ) == 0 ) else if( strcmp( text, "Shape" ) == 0 )
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " Shape" ) ); // Save the pointer
S3D_MESH* parent = m_model; S3D_MESH* parent = m_model;
S3D_MESH* new_mesh_model = new S3D_MESH(); S3D_MESH* new_mesh_model = new S3D_MESH();
m_model->childs.push_back( new_mesh_model ); // Assign the current pointer
m_model = new_mesh_model; m_model = new_mesh_model;
read_Shape(); S3D_MESH* save_ptr = m_model;
if( read_Shape() == 0 )
{
m_model = save_ptr;
if( ((m_model->m_Point.size() == 0) || (m_model->m_CoordIndex.size() == 0)) &&
(m_model->childs.size() == 0) )
{
delete m_model;
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform: Shape, skipping model with no points or childs" ) );
}
else
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform: Shape, Add child model with %lu points, %lu coordIndex, %lu childs." ),
m_model->m_Point.size(),
m_model->m_CoordIndex.size(),
m_model->childs.size() );
parent->childs.push_back( m_model );
}
}
else
{
delete m_model;
}
m_model = parent; m_model = parent;
} }
...@@ -266,26 +469,175 @@ int VRML2_MODEL_PARSER::read_Transform() ...@@ -266,26 +469,175 @@ int VRML2_MODEL_PARSER::read_Transform()
{ {
read_DEF(); read_DEF();
} }
else if( strcmp( text, "USE" ) == 0 )
{
char useLabel[BUFLINE_SIZE];
if( GetNextTag( m_file, useLabel, sizeof(useLabel) ) )
{
// Check if a ',' is at the end and remove it
if( useLabel[strlen(useLabel) - 1] == ',' )
{
useLabel[strlen(useLabel) - 1] = 0;
}
std::string strUseLabel = useLabel;
// Look for it in our group map.
VRML2_DEF_GROUP_MAP::iterator groupIt;
groupIt = m_defGroupMap.find( strUseLabel );
// Checf if not previously defined.
if( groupIt == m_defGroupMap.end() )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "USE: group %s not previously defined "
"in a DEF section." ), strUseLabel );
return -1;
}
S3D_MESH* ptrModel = groupIt->second;
if( ((ptrModel->m_Point.size() == 0) || (ptrModel->m_CoordIndex.size() == 0)) &&
(ptrModel->childs.size() == 0) )
{
// !TODO: delete in the end
//delete ptrModel;
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform: USE %s, skipping model with no points or childs" ), useLabel );
}
else else
{ {
wxLogTrace( traceVrmlV2Parser, wxT( " %s NotImplemented" ), text ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform: USE %s Add child model with %lu points, %lu coordIndex, %lu childs." ),
read_NotImplemented( m_file, '}' ); useLabel,
ptrModel->m_Point.size(),
ptrModel->m_CoordIndex.size(),
ptrModel->childs.size() );
m_model->childs.push_back( ptrModel );
} }
} }
else
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform: USE Failed to get the label name" ) );
return -1;
}
}
else
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform: %s NotImplemented" ), text );
Read_NotImplemented( m_file, '}' );
}
}
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform failed" ) );
return -1;
}
int VRML2_MODEL_PARSER::read_Inline()
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Inline" ) );
debug_enter();
char text[BUFLINE_SIZE];
while( GetNextTag( m_file, text, sizeof(text) ) )
{
if( *text == ']' )
continue;
if( *text == '}' )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Inline exit" ) );
return 0; return 0;
}
if( strcmp( text, "url" ) == 0 )
{
if( GetString( m_file, text, sizeof(text) ) )
{
wxString filename;
filename = filename.FromUTF8( text );
#ifdef __WINDOWS__
filename.Replace( wxT( "/" ), wxT( "\\" ) );
#else
filename.Replace( wxT( "\\" ), wxT( "/" ) );
#endif
bool fileExists = false;
if( wxFileName::FileExists( filename ) )
{
fileExists = true;
}
else
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "URL Failed to open file as a full path: \"%s\", will try now a relative path..." ), filename );
#ifdef __WINDOWS__
filename = m_Filename.GetPath() + '\\' + filename;
#else
filename = m_Filename.GetPath() + '/' + filename;
#endif
if( wxFileName::FileExists( filename ) )
{
fileExists = true;
}
else
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "URL Failed to open file: \"%s\"" ), filename );
}
}
if( fileExists )
{
// Will now create a new parser and set the default
// transfomation model to apply on the root
VRML2_MODEL_PARSER *newParser = new VRML2_MODEL_PARSER( this->m_ModelParser );
newParser->Load( filename, m_model );
delete newParser;
}
else
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "URL Failed to open file: %s" ), text );
}
}
else
{
// If fail get url text, exit with failure
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "URL failed read url string" ) );
break;
}
}
}
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Inline failed" ) );
return -1;
} }
int VRML2_MODEL_PARSER::read_DEF_Coordinate() int VRML2_MODEL_PARSER::read_DEF_Coordinate()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_DEF_Coordinate" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF_Coordinate" ) );
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
// Get the name of the definition. // Get the name of the definition.
if( !GetNextTag( m_file, text, sizeof(text) ) ) if( !GetNextTag( m_file, text, sizeof(text) ) )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF_Coordinate failed to get next tag" ) );
return -1; return -1;
}
std::string coordinateName = text; std::string coordinateName = text;
...@@ -295,7 +647,11 @@ int VRML2_MODEL_PARSER::read_DEF_Coordinate() ...@@ -295,7 +647,11 @@ int VRML2_MODEL_PARSER::read_DEF_Coordinate()
continue; continue;
if( *text == '}' ) if( *text == '}' )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF_Coordinate exit" ) );
return 0; return 0;
}
if( strcmp( text, "Coordinate" ) == 0 ) if( strcmp( text, "Coordinate" ) == 0 )
{ {
...@@ -304,25 +660,29 @@ int VRML2_MODEL_PARSER::read_DEF_Coordinate() ...@@ -304,25 +660,29 @@ int VRML2_MODEL_PARSER::read_DEF_Coordinate()
if( retVal == 0 ) if( retVal == 0 )
m_defCoordinateMap.insert( std::make_pair( coordinateName, m_model->m_Point ) ); m_defCoordinateMap.insert( std::make_pair( coordinateName, m_model->m_Point ) );
debug_exit();
return retVal; return retVal;
} }
} }
wxLogTrace( traceVrmlV2Parser, wxT( " read_DEF_Coordinate failed" ) ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF_Coordinate failed" ) );
return -1; return -1;
} }
int VRML2_MODEL_PARSER::read_DEF() int VRML2_MODEL_PARSER::read_DEF()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_DEF" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF" ) );
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
char tagName[BUFLINE_SIZE]; char tagName[BUFLINE_SIZE];
if( !GetNextTag( m_file, tagName, sizeof(tagName) ) ) if( !GetNextTag( m_file, tagName, sizeof(tagName) ) )
{ {
wxLogTrace( traceVrmlV2Parser, wxT( " DEF failed GetNextTag first" ) ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "DEF failed GetNextTag first" ) );
return -1; return -1;
} }
...@@ -330,18 +690,23 @@ int VRML2_MODEL_PARSER::read_DEF() ...@@ -330,18 +690,23 @@ int VRML2_MODEL_PARSER::read_DEF()
{ {
if( *text == ']' ) if( *text == ']' )
{ {
wxLogTrace( traceVrmlV2Parser, wxT( " skipping %c" ), *text ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "skipping %c" ), *text );
continue; continue;
} }
if( *text == '}' ) if( *text == '}' )
{ {
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF exit" ) );
return 0; return 0;
} }
if( strcmp( text, "Transform" ) == 0 ) if( strcmp( text, "Transform" ) == 0 )
{ {
return read_Transform(); int ret = read_Transform();
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF exit after Transform, please check and validate" ) );
return ret;
} }
else if( strcmp( text, "children" ) == 0 ) else if( strcmp( text, "children" ) == 0 )
{ {
...@@ -361,37 +726,113 @@ int VRML2_MODEL_PARSER::read_DEF() ...@@ -361,37 +726,113 @@ int VRML2_MODEL_PARSER::read_DEF()
} }
else if( strcmp( text, "Shape" ) == 0 ) else if( strcmp( text, "Shape" ) == 0 )
{ {
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Shape" ) );
// Save the pointer
S3D_MESH* parent = m_model; S3D_MESH* parent = m_model;
S3D_MESH* new_mesh_model = new S3D_MESH(); S3D_MESH* new_mesh_model = new S3D_MESH();
m_model->childs.push_back( new_mesh_model );
// Assign the current pointer
m_model = new_mesh_model; m_model = new_mesh_model;
read_Shape();
S3D_MESH* save_ptr = m_model;
if( read_Shape() == 0 )
{
m_model = save_ptr;
if( ((m_model->m_Point.size() == 0) || (m_model->m_CoordIndex.size() == 0)) &&
(m_model->childs.size() == 0) )
{
delete m_model;
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF: Shape, skipping model with no points or childs" ) );
}
else
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF: Shape, Add child model with %lu points, %lu coordIndex, %lu childs." ),
m_model->m_Point.size(),
m_model->m_CoordIndex.size(),
m_model->childs.size() );
parent->childs.push_back( m_model );
}
}
else
{
delete m_model;
}
m_model = parent; m_model = parent;
} }
else if( strcmp( text, "IndexedFaceSet" ) == 0 )
{
read_IndexedFaceSet();
}
else if( strcmp( text, "Group" ) == 0 )
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Group %s" ), tagName );
// Save the pointer
S3D_MESH* parent = m_model;
S3D_MESH* new_mesh_model = new S3D_MESH();
// Assign the current pointer
m_model = new_mesh_model;
// It will be the same as read a new Transform
if( read_Transform() == 0 )
{
std::string groupName = tagName;
//m_defGroupMap.insert( std::make_pair( groupName, new_mesh_model ) );
m_defGroupMap[groupName] = new_mesh_model;
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Group %s: inserted model with %lu points, %lu coordIndex, %lu childs." ),
tagName,
new_mesh_model->m_Point.size(),
new_mesh_model->m_CoordIndex.size(),
new_mesh_model->childs.size() );
}
else else
{ {
wxLogTrace( traceVrmlV2Parser, wxT( " DEF %s %s NotImplemented, skipping." ), tagName, text ); delete m_model;
read_NotImplemented( m_file, '}' ); }
return -1; // Restore current model pointer
m_model = parent;
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF %s Group exit" ), tagName );
return 0;
}
else
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "DEF %s %s NotImplemented, skipping." ), tagName, text );
Read_NotImplemented( m_file, '}' );
} }
} }
wxLogTrace( traceVrmlV2Parser, wxT( " DEF failed" ) ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "DEF failed" ) );
return -1; return -1;
} }
int VRML2_MODEL_PARSER::read_USE() int VRML2_MODEL_PARSER::read_IndexedFaceSet_USE()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_USE" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedFaceSet_USE" ) );
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
// Get the name of the definition. // Get the name of the definition.
if( !GetNextTag( m_file, text, sizeof(text) ) ) if( !GetNextTag( m_file, text, sizeof(text) ) )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedFaceSet_USE failed to get next tag" ) );
return -1; return -1;
}
std::string coordinateName = text; std::string coordinateName = text;
...@@ -402,19 +843,22 @@ int VRML2_MODEL_PARSER::read_USE() ...@@ -402,19 +843,22 @@ int VRML2_MODEL_PARSER::read_USE()
// Not previously defined. // Not previously defined.
if( coordinate == m_defCoordinateMap.end() ) if( coordinate == m_defCoordinateMap.end() )
{ {
wxLogTrace( traceVrmlV2Parser, wxT( "USE: coordinate %s not previously defined " debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "USE: coordinate %s not previously defined "
"in a DEF section." ), text ); "in a DEF section." ), text );
return -1; return -1;
} }
m_model->m_Point = coordinate->second; m_model->m_Point = coordinate->second;
debug_exit();
return 0; return 0;
} }
int VRML2_MODEL_PARSER::read_Shape() int VRML2_MODEL_PARSER::read_Shape()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_Shape" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Shape" ) );
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
...@@ -427,6 +871,8 @@ int VRML2_MODEL_PARSER::read_Shape() ...@@ -427,6 +871,8 @@ int VRML2_MODEL_PARSER::read_Shape()
if( *text == '}' ) if( *text == '}' )
{ {
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Shape exit" ) );
return 0; return 0;
} }
...@@ -441,8 +887,7 @@ int VRML2_MODEL_PARSER::read_Shape() ...@@ -441,8 +887,7 @@ int VRML2_MODEL_PARSER::read_Shape()
} }
else if( strcmp( text, "geometry" ) == 0 ) else if( strcmp( text, "geometry" ) == 0 )
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " \"geometry\" key word not supported." ) ); read_geometry();
// skip
} }
else if( strcmp( text, "IndexedFaceSet" ) == 0 ) else if( strcmp( text, "IndexedFaceSet" ) == 0 )
{ {
...@@ -454,19 +899,76 @@ int VRML2_MODEL_PARSER::read_Shape() ...@@ -454,19 +899,76 @@ int VRML2_MODEL_PARSER::read_Shape()
} }
else else
{ {
wxLogTrace( traceVrmlV2Parser, wxT( " %s NotImplemented" ), text ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "%s NotImplemented" ), text );
read_NotImplemented( m_file, '}' ); Read_NotImplemented( m_file, '}' );
} }
} }
wxLogTrace( traceVrmlV2Parser, wxT( " Shape failed" ) ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Shape failed" ) );
return -1;
}
int VRML2_MODEL_PARSER::read_geometry()
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_geometry" ) );
debug_enter();
char text[BUFLINE_SIZE];
char tagName[BUFLINE_SIZE];
tagName[0] = 0;
while( GetNextTag( m_file, text, sizeof(text) ) )
{
if( *text == ']' )
{
continue;
}
if( *text == '}' )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_geometry exit" ) );
return 0;
}
if( strcmp( text, "DEF" ) == 0 )
{
if( !GetNextTag( m_file, tagName, sizeof(tagName) ) )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "DEF failed GetNextTag first" ) );
return -1;
}
}
else if( strcmp( text, "IndexedFaceSet" ) == 0 )
{
int ret = read_IndexedFaceSet();
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_geometry exit, after IndexedFaceSet" ) );
return ret;
}
else
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_geometry: %s NotImplemented" ), text );
int ret = Read_NotImplemented( m_file, '}' );
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_geometry exit, after %s" ), text);
return ret;
}
}
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_geometry failed" ) );
return -1; return -1;
} }
int VRML2_MODEL_PARSER::read_Appearance() int VRML2_MODEL_PARSER::read_Appearance()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_Appearance" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Appearance" ) );
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
...@@ -479,6 +981,8 @@ int VRML2_MODEL_PARSER::read_Appearance() ...@@ -479,6 +981,8 @@ int VRML2_MODEL_PARSER::read_Appearance()
if( *text == '}' ) if( *text == '}' )
{ {
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Appearance exit" ) );
return 0; return 0;
} }
...@@ -488,14 +992,16 @@ int VRML2_MODEL_PARSER::read_Appearance() ...@@ -488,14 +992,16 @@ int VRML2_MODEL_PARSER::read_Appearance()
} }
} }
wxLogTrace( traceVrmlV2Parser, wxT( " Appearance failed" ) ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Appearance failed" ) );
return -1; return -1;
} }
int VRML2_MODEL_PARSER::read_material() int VRML2_MODEL_PARSER::read_material()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_material" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_material" ) );
debug_enter();
S3D_MATERIAL* material = NULL; S3D_MATERIAL* material = NULL;
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
...@@ -511,7 +1017,9 @@ int VRML2_MODEL_PARSER::read_material() ...@@ -511,7 +1017,9 @@ int VRML2_MODEL_PARSER::read_material()
if( strcmp( text, "Material" ) == 0 ) if( strcmp( text, "Material" ) == 0 )
{ {
return read_Material(); int ret = read_Material();
debug_exit();
return ret;
} }
} }
else if( strcmp( text, "DEF" ) == 0 ) else if( strcmp( text, "DEF" ) == 0 )
...@@ -529,7 +1037,9 @@ int VRML2_MODEL_PARSER::read_material() ...@@ -529,7 +1037,9 @@ int VRML2_MODEL_PARSER::read_material()
{ {
if( strcmp( text, "Material" ) == 0 ) if( strcmp( text, "Material" ) == 0 )
{ {
return read_Material(); int ret = read_Material();
debug_exit();
return ret;
} }
} }
} }
...@@ -546,23 +1056,26 @@ int VRML2_MODEL_PARSER::read_material() ...@@ -546,23 +1056,26 @@ int VRML2_MODEL_PARSER::read_material()
if( material->m_Name == mat_name ) if( material->m_Name == mat_name )
{ {
m_model->m_Materials = material; m_model->m_Materials = material;
debug_exit();
return 0; return 0;
} }
} }
wxLogTrace( traceVrmlV2Parser, wxT( " read_material error: material not found" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_material error: material not found" ) );
} }
} }
} }
wxLogTrace( traceVrmlV2Parser, wxT( " failed material" ) ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "failed material" ) );
return -1; return -1;
} }
int VRML2_MODEL_PARSER::read_Material() int VRML2_MODEL_PARSER::read_Material()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_Material" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Material" ) );
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
glm::vec3 vertex; glm::vec3 vertex;
...@@ -576,17 +1089,19 @@ int VRML2_MODEL_PARSER::read_Material() ...@@ -576,17 +1089,19 @@ int VRML2_MODEL_PARSER::read_Material()
if( *text == '}' ) if( *text == '}' )
{ {
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Material exit" ) );
return 0; return 0;
} }
if( strcmp( text, "diffuseColor" ) == 0 ) if( strcmp( text, "diffuseColor" ) == 0 )
{ {
parseVertex( m_file, vertex ); ParseVertex( m_file, vertex );
m_model->m_Materials->m_DiffuseColor.push_back( vertex ); m_model->m_Materials->m_DiffuseColor.push_back( vertex );
} }
else if( strcmp( text, "emissiveColor" ) == 0 ) else if( strcmp( text, "emissiveColor" ) == 0 )
{ {
parseVertex( m_file, vertex ); ParseVertex( m_file, vertex );
if( m_Master->m_use_modelfile_emissiveColor == true ) if( m_Master->m_use_modelfile_emissiveColor == true )
{ {
...@@ -595,7 +1110,7 @@ int VRML2_MODEL_PARSER::read_Material() ...@@ -595,7 +1110,7 @@ int VRML2_MODEL_PARSER::read_Material()
} }
else if( strcmp( text, "specularColor" ) == 0 ) else if( strcmp( text, "specularColor" ) == 0 )
{ {
parseVertex( m_file, vertex ); ParseVertex( m_file, vertex );
if( m_Master->m_use_modelfile_specularColor == true ) if( m_Master->m_use_modelfile_specularColor == true )
{ {
...@@ -605,7 +1120,7 @@ int VRML2_MODEL_PARSER::read_Material() ...@@ -605,7 +1120,7 @@ int VRML2_MODEL_PARSER::read_Material()
else if( strcmp( text, "ambientIntensity" ) == 0 ) else if( strcmp( text, "ambientIntensity" ) == 0 )
{ {
float ambientIntensity; float ambientIntensity;
parseFloat( m_file, &ambientIntensity ); ParseFloat( m_file, &ambientIntensity );
if( m_Master->m_use_modelfile_ambientIntensity == true ) if( m_Master->m_use_modelfile_ambientIntensity == true )
{ {
...@@ -616,7 +1131,7 @@ int VRML2_MODEL_PARSER::read_Material() ...@@ -616,7 +1131,7 @@ int VRML2_MODEL_PARSER::read_Material()
else if( strcmp( text, "transparency" ) == 0 ) else if( strcmp( text, "transparency" ) == 0 )
{ {
float transparency; float transparency;
parseFloat( m_file, &transparency ); ParseFloat( m_file, &transparency );
if( m_Master->m_use_modelfile_transparency == true ) if( m_Master->m_use_modelfile_transparency == true )
{ {
...@@ -626,7 +1141,7 @@ int VRML2_MODEL_PARSER::read_Material() ...@@ -626,7 +1141,7 @@ int VRML2_MODEL_PARSER::read_Material()
else if( strcmp( text, "shininess" ) == 0 ) else if( strcmp( text, "shininess" ) == 0 )
{ {
float shininess; float shininess;
parseFloat( m_file, &shininess ); ParseFloat( m_file, &shininess );
// VRML value is normalized and openGL expects a value 0 - 128 // VRML value is normalized and openGL expects a value 0 - 128
if( m_Master->m_use_modelfile_shininess == true ) if( m_Master->m_use_modelfile_shininess == true )
...@@ -637,14 +1152,16 @@ int VRML2_MODEL_PARSER::read_Material() ...@@ -637,14 +1152,16 @@ int VRML2_MODEL_PARSER::read_Material()
} }
} }
wxLogTrace( traceVrmlV2Parser, wxT( " Material failed" ) ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Material failed" ) );
return -1; return -1;
} }
int VRML2_MODEL_PARSER::read_IndexedFaceSet() int VRML2_MODEL_PARSER::read_IndexedFaceSet()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_IndexedFaceSet" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedFaceSet" ) );
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
...@@ -660,6 +1177,8 @@ int VRML2_MODEL_PARSER::read_IndexedFaceSet() ...@@ -660,6 +1177,8 @@ int VRML2_MODEL_PARSER::read_IndexedFaceSet()
if( *text == '}' ) if( *text == '}' )
{ {
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedFaceSet exit" ) );
return 0; return 0;
} }
...@@ -712,18 +1231,20 @@ int VRML2_MODEL_PARSER::read_IndexedFaceSet() ...@@ -712,18 +1231,20 @@ int VRML2_MODEL_PARSER::read_IndexedFaceSet()
} }
else if( strcmp( text, "USE" ) == 0 ) else if( strcmp( text, "USE" ) == 0 )
{ {
read_USE(); read_IndexedFaceSet_USE();
} }
} }
wxLogTrace( traceVrmlV2Parser, wxT( " IndexedFaceSet failed %s" ), text ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "IndexedFaceSet failed %s" ), text );
return -1; return -1;
} }
int VRML2_MODEL_PARSER::read_IndexedLineSet() int VRML2_MODEL_PARSER::read_IndexedLineSet()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_IndexedLineSet" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedLineSet" ) );
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
...@@ -733,7 +1254,11 @@ int VRML2_MODEL_PARSER::read_IndexedLineSet() ...@@ -733,7 +1254,11 @@ int VRML2_MODEL_PARSER::read_IndexedLineSet()
continue; continue;
if( *text == '}' ) if( *text == '}' )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedLineSet exit" ) );
return 0; return 0;
}
if( strcmp( text, "Coordinate" ) == 0 ) if( strcmp( text, "Coordinate" ) == 0 )
read_Coordinate(); read_Coordinate();
...@@ -743,13 +1268,16 @@ int VRML2_MODEL_PARSER::read_IndexedLineSet() ...@@ -743,13 +1268,16 @@ int VRML2_MODEL_PARSER::read_IndexedLineSet()
read_DEF_Coordinate(); read_DEF_Coordinate();
} }
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedLineSet failed" ) );
return -1; return -1;
} }
int VRML2_MODEL_PARSER::read_colorIndex() int VRML2_MODEL_PARSER::read_colorIndex()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_colorIndex" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_colorIndex" ) );
debug_enter();
m_model->m_MaterialIndex.clear(); m_model->m_MaterialIndex.clear();
...@@ -781,15 +1309,16 @@ int VRML2_MODEL_PARSER::read_colorIndex() ...@@ -781,15 +1309,16 @@ int VRML2_MODEL_PARSER::read_colorIndex()
} }
} }
//wxLogTrace( traceVrmlV2Parser, wxT( " read_colorIndex m_MaterialIndex.size: %u" ), (unsigned int)m_model->m_MaterialIndex.size() ); //wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_colorIndex m_MaterialIndex.size: %u" ), (unsigned int)m_model->m_MaterialIndex.size() );
debug_exit();
return 0; return 0;
} }
int VRML2_MODEL_PARSER::read_NormalIndex() int VRML2_MODEL_PARSER::read_NormalIndex()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_NormalIndex" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_NormalIndex" ) );
debug_enter();
m_model->m_NormalIndex.clear(); m_model->m_NormalIndex.clear();
...@@ -813,15 +1342,16 @@ int VRML2_MODEL_PARSER::read_NormalIndex() ...@@ -813,15 +1342,16 @@ int VRML2_MODEL_PARSER::read_NormalIndex()
} }
} }
//wxLogTrace( traceVrmlV2Parser, wxT( " read_NormalIndex m_NormalIndex.size: %u" ), (unsigned int)m_model->m_NormalIndex.size() ); //wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_NormalIndex m_NormalIndex.size: %u" ), (unsigned int)m_model->m_NormalIndex.size() );
debug_exit();
return 0; return 0;
} }
int VRML2_MODEL_PARSER::read_coordIndex() int VRML2_MODEL_PARSER::read_coordIndex()
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_coordIndex" ) ); wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_coordIndex" ) );
debug_enter();
m_model->m_CoordIndex.clear(); m_model->m_CoordIndex.clear();
...@@ -845,14 +1375,17 @@ int VRML2_MODEL_PARSER::read_coordIndex() ...@@ -845,14 +1375,17 @@ int VRML2_MODEL_PARSER::read_coordIndex()
} }
} }
//wxLogTrace( traceVrmlV2Parser, wxT( " read_coordIndex m_CoordIndex.size: %u" ), (unsigned int)m_model->m_CoordIndex.size() ); //wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_coordIndex m_CoordIndex.size: %u" ), (unsigned int)m_model->m_CoordIndex.size() );
debug_exit();
return 0; return 0;
} }
int VRML2_MODEL_PARSER::read_Color() int VRML2_MODEL_PARSER::read_Color()
{ {
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Color" ) );
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
while( GetNextTag( m_file, text, sizeof(text) ) ) while( GetNextTag( m_file, text, sizeof(text) ) )
...@@ -864,22 +1397,28 @@ int VRML2_MODEL_PARSER::read_Color() ...@@ -864,22 +1397,28 @@ int VRML2_MODEL_PARSER::read_Color()
if( *text == '}' ) if( *text == '}' )
{ {
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Color exit" ) );
return 0; return 0;
} }
if( strcmp( text, "color" ) == 0 ) if( strcmp( text, "color" ) == 0 )
{ {
parseVertexList( m_file, m_model->m_Materials->m_DiffuseColor ); ParseVertexList( m_file, m_model->m_Materials->m_DiffuseColor );
} }
} }
//wxLogTrace( traceVrmlV2Parser, wxT( " read_Color failed" ) ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Color failed" ) );
return -1; return -1;
} }
int VRML2_MODEL_PARSER::read_Normal() int VRML2_MODEL_PARSER::read_Normal()
{ {
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Normal" ) );
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
while( GetNextTag( m_file, text, sizeof(text) ) ) while( GetNextTag( m_file, text, sizeof(text) ) )
...@@ -891,11 +1430,14 @@ int VRML2_MODEL_PARSER::read_Normal() ...@@ -891,11 +1430,14 @@ int VRML2_MODEL_PARSER::read_Normal()
if( *text == '}' ) if( *text == '}' )
{ {
// Debug
//if( m_normalPerVertex == false ) //if( m_normalPerVertex == false )
// wxLogTrace( traceVrmlV2Parser, wxT( " read_Normal m_PerFaceNormalsNormalized.size: %u" ), (unsigned int)m_model->m_PerFaceNormalsNormalized.size() ); // wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Normal m_PerFaceNormalsNormalized.size: %u" ), (unsigned int)m_model->m_PerFaceNormalsNormalized.size() );
//else //else
// wxLogTrace( traceVrmlV2Parser, wxT( " read_Normal m_PerVertexNormalsNormalized.size: %u" ), (unsigned int)m_model->m_PerVertexNormalsNormalized.size() ); // wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Normal m_PerVertexNormalsNormalized.size: %u" ), (unsigned int)m_model->m_PerVertexNormalsNormalized.size() );
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Normal exit" ) );
return 0; return 0;
} }
...@@ -903,22 +1445,25 @@ int VRML2_MODEL_PARSER::read_Normal() ...@@ -903,22 +1445,25 @@ int VRML2_MODEL_PARSER::read_Normal()
{ {
if( m_normalPerVertex == false ) if( m_normalPerVertex == false )
{ {
parseVertexList( m_file, m_model->m_PerFaceNormalsNormalized ); ParseVertexList( m_file, m_model->m_PerFaceNormalsNormalized );
} }
else else
{ {
parseVertexList( m_file, m_model->m_PerVertexNormalsNormalized ); ParseVertexList( m_file, m_model->m_PerVertexNormalsNormalized );
} }
} }
} }
wxLogTrace( traceVrmlV2Parser, wxT( " read_Normal failed" ) ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Normal failed" ) );
return -1; return -1;
} }
int VRML2_MODEL_PARSER::read_Coordinate() int VRML2_MODEL_PARSER::read_Coordinate()
{ {
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
while( GetNextTag( m_file, text, sizeof(text) ) ) while( GetNextTag( m_file, text, sizeof(text) ) )
...@@ -930,17 +1475,20 @@ int VRML2_MODEL_PARSER::read_Coordinate() ...@@ -930,17 +1475,20 @@ int VRML2_MODEL_PARSER::read_Coordinate()
if( *text == '}' ) if( *text == '}' )
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_Coordinate m_Point.size: %u" ), (unsigned int)m_model->m_Point.size() ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Coordinate exit" ) );
//wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Coordinate m_Point.size: %u" ), (unsigned int)m_model->m_Point.size() );
return 0; return 0;
} }
if( strcmp( text, "point" ) == 0 ) if( strcmp( text, "point" ) == 0 )
{ {
parseVertexList( m_file, m_model->m_Point ); ParseVertexList( m_file, m_model->m_Point );
} }
} }
wxLogTrace( traceVrmlV2Parser, wxT( " read_Coordinate failed" ) ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Coordinate failed" ) );
return -1; return -1;
} }
...@@ -950,6 +1498,8 @@ int VRML2_MODEL_PARSER::read_Coordinate() ...@@ -950,6 +1498,8 @@ int VRML2_MODEL_PARSER::read_Coordinate()
*/ */
int VRML2_MODEL_PARSER::read_CoordinateDef() int VRML2_MODEL_PARSER::read_CoordinateDef()
{ {
debug_enter();
char text[BUFLINE_SIZE]; char text[BUFLINE_SIZE];
while( GetNextTag( m_file, text, sizeof(text) ) ) while( GetNextTag( m_file, text, sizeof(text) ) )
...@@ -959,14 +1509,17 @@ int VRML2_MODEL_PARSER::read_CoordinateDef() ...@@ -959,14 +1509,17 @@ int VRML2_MODEL_PARSER::read_CoordinateDef()
if( *text == '}' ) if( *text == '}' )
{ {
//wxLogTrace( traceVrmlV2Parser, wxT( " read_CoordinateDef m_Point.size: %u" ), (unsigned int)m_model->m_Point.size() ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_CoordinateDef exit" ) );
//wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_CoordinateDef m_Point.size: %u" ), (unsigned int)m_model->m_Point.size() );
return 0; return 0;
} }
if( strcmp( text, "point" ) == 0 ) if( strcmp( text, "point" ) == 0 )
parseVertexList( m_file, m_model->m_Point ); ParseVertexList( m_file, m_model->m_Point );
} }
wxLogTrace( traceVrmlV2Parser, wxT( " read_CoordinateDef failed" ) ); debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_CoordinateDef failed" ) );
return -1; return -1;
} }
...@@ -41,17 +41,20 @@ ...@@ -41,17 +41,20 @@
VRML_MODEL_PARSER::VRML_MODEL_PARSER( S3D_MASTER* aMaster ) : VRML_MODEL_PARSER::VRML_MODEL_PARSER( S3D_MASTER* aMaster ) :
S3D_MODEL_PARSER( aMaster ) S3D_MODEL_PARSER( aMaster )
{ {
vrml1_parser = NULL;
vrml2_parser = NULL;
m_curr3DShape = NULL;
} }
VRML_MODEL_PARSER::~VRML_MODEL_PARSER() VRML_MODEL_PARSER::~VRML_MODEL_PARSER()
{ {
for( unsigned int idx = 0; idx < childs.size(); idx++ )
{
if( childs[idx] )
{
delete childs[idx];
childs[idx] = 0;
}
}
} }
bool VRML_MODEL_PARSER::Load( const wxString& aFilename ) bool VRML_MODEL_PARSER::Load( const wxString& aFilename )
{ {
char line[11 + 1]; char line[11 + 1];
...@@ -72,20 +75,20 @@ bool VRML_MODEL_PARSER::Load( const wxString& aFilename ) ...@@ -72,20 +75,20 @@ bool VRML_MODEL_PARSER::Load( const wxString& aFilename )
fclose( file ); fclose( file );
childs.clear();
if( stricmp( line, "#VRML V2.0" ) == 0 ) if( stricmp( line, "#VRML V2.0" ) == 0 )
{ {
vrml2_parser = new VRML2_MODEL_PARSER( this ); VRML2_MODEL_PARSER *vrml2_parser = new VRML2_MODEL_PARSER( this );
vrml2_parser->Load( aFilename ); vrml2_parser->Load( aFilename );
delete vrml2_parser; delete vrml2_parser;
vrml2_parser = NULL;
return true; return true;
} }
else if( stricmp( line, "#VRML V1.0" ) == 0 ) else if( stricmp( line, "#VRML V1.0" ) == 0 )
{ {
vrml1_parser = new VRML1_MODEL_PARSER( this ); VRML1_MODEL_PARSER *vrml1_parser = new VRML1_MODEL_PARSER( this );
vrml1_parser->Load( aFilename ); vrml1_parser->Load( aFilename );
delete vrml1_parser; delete vrml1_parser;
vrml1_parser = NULL;
return true; return true;
} }
......
...@@ -58,6 +58,14 @@ X3D_MODEL_PARSER::X3D_MODEL_PARSER( S3D_MASTER* aMaster ) : ...@@ -58,6 +58,14 @@ X3D_MODEL_PARSER::X3D_MODEL_PARSER( S3D_MASTER* aMaster ) :
X3D_MODEL_PARSER::~X3D_MODEL_PARSER() X3D_MODEL_PARSER::~X3D_MODEL_PARSER()
{ {
for( unsigned int idx = 0; idx < childs.size(); idx++ )
{
if( childs[idx] )
{
delete childs[idx];
childs[idx] = 0;
}
}
} }
......
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