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
ay = aVertices[1].y - aVertices[0].y;
az = aVertices[1].z - aVertices[0].z;
bx = aVertices[aVertices.size() - 1].x - aVertices[0].x;
by = aVertices[aVertices.size() - 1].y - aVertices[0].y;
bz = aVertices[aVertices.size() - 1].z - aVertices[0].z;
bx = aVertices[2].x - aVertices[0].x;
by = aVertices[2].y - aVertices[0].y;
bz = aVertices[2].z - aVertices[0].z;
nx = ay * bz - az * by;
ny = az * bx - ax * bz;
......
......@@ -94,6 +94,8 @@ EDA_3D_CANVAS::EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList ) :
m_ZBottom = 0.0;
m_ZTop = 0.0;
m_lightPos = S3D_VERTEX(0.0f, 0.0f, 50.0f);
// Clear all gl list identifiers:
for( int ii = GL_ID_BEGIN; ii < GL_ID_END; ii++ )
m_glLists[ii] = 0;
......@@ -110,6 +112,12 @@ EDA_3D_CANVAS::~EDA_3D_CANVAS()
ClearLists();
m_init = false;
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 )
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()
void EDA_3D_CANVAS::SetLights()
{
// 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)
light_color[3] = 1.0;
// 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 );
light_color[0] = light_color[1] = light_color[2] = 1.0;
......@@ -580,7 +599,7 @@ void EDA_3D_CANVAS::SetLights()
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 );
glEnable( GL_LIGHT0 ); // White spot on Z axis ( top )
......
......@@ -43,7 +43,9 @@
#endif
#include <3d_struct.h>
#include <modelparsers.h>
#include <class_module.h>
#include <CBBox.h>
class BOARD_DESIGN_SETTINGS;
class EDA_3D_FRAME;
......@@ -78,16 +80,15 @@ class EDA_3D_CANVAS : public wxGLCanvas
{
private:
bool m_init;
bool m_reportWarnings; // true to report all wranings when build the 3D scene
// false to report errors only
GLuint m_glLists[GL_ID_END]; // GL lists
bool m_reportWarnings; ///< true to report all wranings when build the 3D scene false to report errors only
GLuint m_glLists[GL_ID_END]; ///< GL lists
wxGLContext* m_glRC;
wxRealPoint m_draw3dOffset; // offset to draw the 3D mesh.
double m_ZBottom; // position of the back layer
double m_ZTop; // position of the front layer
wxRealPoint m_draw3dOffset; ///< offset to draw the 3D mesh.
double m_ZBottom; ///< position of the back 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_silk; // an index to the texture generated for silk layers
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
// Index to the textures generated for shadows
bool m_shadow_init;
......@@ -95,9 +96,21 @@ private:
GLuint m_text_fake_shadow_back;
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 );
void calcBBox();
public:
EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList = 0 );
~EDA_3D_CANVAS();
......@@ -187,33 +200,33 @@ private:
wxPoint getBoardCenter() const;
/**
* Helper function SetGLTechLayersColor
* Helper function setGLTechLayersColor
* Initialize the color to draw the non copper layers
* in realistic mode and normal mode.
*/
void setGLTechLayersColor( LAYER_NUM aLayer );
/**
* Helper function SetGLCopperColor
* Helper function setGLCopperColor
* Initialize the copper color to draw the board
* in realistic mode (a golden yellow color )
*/
void setGLCopperColor();
/**
* Helper function SetGLEpoxyColor
* Helper function setGLEpoxyColor
* Initialize the color to draw the epoxy body board in realistic mode.
*/
void setGLEpoxyColor( float aTransparency = 1.0 );
/**
* Helper function SetGLSolderMaskColor
* Helper function setGLSolderMaskColor
* Initialize the color to draw the solder mask layers in realistic mode.
*/
void setGLSolderMaskColor( float aTransparency = 1.0 );
/**
* Function BuildBoard3DView
* Function buildBoard3DView
* Called by CreateDrawGL_List()
* 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
......@@ -224,27 +237,27 @@ private:
* created by the build process (can be NULL)
* @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 );
/**
* Function BuildTechLayers3DView
* Function buildTechLayers3DView
* Called by CreateDrawGL_List()
* Populates the OpenGL GL_ID_TECH_LAYERS draw list with items on tech layers
* @param aErrorMessages = a wxString to add error and warning messages
* created by the build process (can be NULL)
* @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()
*/
void BuildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint aBoardList );
void buildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint aBoardList );
/**
* Function BuildFootprintShape3DList
* Function buildFootprintShape3DList
* Called by CreateDrawGL_List()
* Fills the OpenGL GL_ID_3DSHAPES_SOLID and GL_ID_3DSHAPES_TRANSP
* draw lists with 3D footprint shapes
......@@ -252,19 +265,18 @@ private:
* @param aTransparentList is the gl list for non transparent items,
* which need to be drawn after all other items
*/
void BuildFootprintShape3DList( GLuint aOpaqueList,
GLuint aTransparentList,
bool aSideToLoad );
void buildFootprintShape3DList( GLuint aOpaqueList,
GLuint aTransparentList );
/**
* Function BuildBoard3DAuxLayers
* Function buildBoard3DAuxLayers
* Called by CreateDrawGL_List()
* Fills the OpenGL GL_ID_AUX_LAYERS draw list
* with items on aux layers only
*/
void BuildBoard3DAuxLayers();
void buildBoard3DAuxLayers();
void Draw3DGrid( double aGriSizeMM );
void Draw3DAxis();
void draw3DGrid( double aGriSizeMM );
void draw3DAxis();
/**
* Helper function BuildPadShapeThickOutlineAsPolygon:
......@@ -272,7 +284,7 @@ private:
* with a line thickness = aWidth
* Used only to draw pads outlines on silkscreen layers.
*/
void BuildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
void buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
CPOLYGONS_LIST& aCornerBuffer,
int aWidth,
int aCircleToSegmentsCount,
......@@ -280,54 +292,48 @@ private:
/**
* Helper function Draw3DViaHole:
* Helper function draw3DViaHole:
* Draw the via hole:
* 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:
* 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
* @param module
* @param aIsRenderingJustNonTransparentObjects = 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
*/
void Render3DComponentShape( MODULE* module,
void render3DComponentShape( MODULE* module,
bool aIsRenderingJustNonTransparentObjects,
bool aIsRenderingJustTransparentObjects,
bool aSideToLoad );
bool aIsRenderingJustTransparentObjects );
/**
* function Read3DComponentShape
* function read3DComponentShape
* read the 3D component shape(s) of the footprint (physical shape).
* @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
*/
bool Read3DComponentShape( MODULE* module,
std::vector<S3D_MODEL_PARSER *>& model_parsers_list,
std::vector<wxString>& model_filename_list );
bool read3DComponentShape( MODULE* module );
/**
* function GenerateFakeShadowsTextures
* function generateFakeShadowsTextures
* creates shadows of the board an footprints
* for aesthetical purpose
* @param aErrorMessages = a wxString to add error and warning messages
* created by the build process (can be NULL)
* @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()
};
......
/**
* @file 3d_class.cpp
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
......@@ -25,6 +21,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file 3d_class.cpp
*/
#include <fctsys.h>
......@@ -79,12 +78,14 @@ S3D_MASTER:: ~S3D_MASTER()
{
next = m_3D_Drawings->Next();
delete m_3D_Drawings;
m_3D_Drawings = 0;
}
for( ; m_Materials != NULL; m_Materials = nextmat )
{
nextmat = m_Materials->Next();
delete m_Materials;
m_Materials = 0;
}
}
......@@ -115,19 +116,59 @@ void S3D_MASTER::SetShape3DName( const wxString& aShapeName )
return;
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;
else if( ext == wxT( "idf" ) )
else if( m_Shape3DNameExtension == wxT( "idf" ) )
m_ShapeType = FILE3D_IDF;
else
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;
}
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 ) :
EDA_ITEM( aParent, NOT_USED )
{
......
/*
* 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.
*
* This program is free software; you can redistribute it and/or
......@@ -23,6 +24,7 @@
/**
* @file 3d_draw.cpp
*
*/
#include <fctsys.h>
......@@ -42,7 +44,8 @@
#include <class_pcb_text.h>
#include <colors_selection.h>
#include <convert_basic_shapes_to_polygon.h>
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
#include <gal/opengl/opengl_compositor.h>
#ifdef __WINDOWS__
#include <GL/glew.h> // must be included before gl.h
#endif
......@@ -65,11 +68,9 @@
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 )
{
unsigned char *depthbufferRGBA = (unsigned char*) malloc( aTexture_size * aTexture_size * 4 );
glDisable( GL_TEXTURE_2D );
glViewport( 0, 0, aTexture_size, aTexture_size);
......@@ -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 );
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
glTranslatef( -GetPrm3DVisu().m_BoardPos.x * GetPrm3DVisu().m_BiuTo3Dunits,
-GetPrm3DVisu().m_BoardPos.y * GetPrm3DVisu().m_BiuTo3Dunits,
0.0F );
// Render body and shapes
if( aDraw_body && 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,
if( 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) );
for( unsigned int i = 0; i < (aTexture_size * aTexture_size); i++ )
depthbufferFloat[i] = 1.0f;
......@@ -101,6 +100,7 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture,
aTexture_size, aTexture_size,
GL_DEPTH_COMPONENT, GL_FLOAT, depthbufferFloat );
CheckGLError( __FILE__, __LINE__ );
glEnable( GL_TEXTURE_2D );
glGenTextures( 1, 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 imgDepthBufferAux( aTexture_size, aTexture_size );
imgDepthBuffer.setPixelsFromNormalizedFloat( depthbufferFloat );
imgDepthBuffer.SetPixelsFromNormalizedFloat( depthbufferFloat );
free( depthbufferFloat );
wxString filename;
// Debug texture image
//wxString filename;
//filename.Printf( "imgDepthBuffer_%04d", *aDst_gl_texture );
//imgDepthBuffer.saveAsPNG( filename );
//imgDepthBuffer.SaveAsPNG( filename );
while (aBlurPasses > 0)
while( aBlurPasses > 0 )
{
aBlurPasses--;
imgDepthBufferAux.efxFilter( &imgDepthBuffer, 1.0, FILTER_BLUR);
imgDepthBuffer.efxFilter( &imgDepthBufferAux, 1.0, FILTER_BLUR);
imgDepthBufferAux.EfxFilter( &imgDepthBuffer, FILTER_GAUSSIAN_BLUR );
imgDepthBuffer.EfxFilter( &imgDepthBufferAux, FILTER_GAUSSIAN_BLUR );
}
//filename.Printf( "imgDepthBuffer_blur_%04d", *aDst_gl_texture );
//imgDepthBuffer.saveAsPNG( filename );
imgDepthBuffer.copyFull( &imgDepthBuffer, &imgDepthBuffer, COPY_MUL );
//imgDepthBuffer.copyFull( &imgDepthBuffer, &imgDepthBuffer, COPY_MUL );
//filename.Printf( "imgDepthBuffer_mul_%04d", *aDst_gl_texture );
//imgDepthBuffer.saveAsPNG( filename );
// Debug texture image
//filename.Printf( "imgDepthBuffer_blur%04d", *aDst_gl_texture );
//imgDepthBuffer.SaveAsPNG( filename );
//imgDepthBufferAux.efxFilter( &imgDepthBuffer, 1.0, FILTER_BLUR);
//imgDepthBuffer.efxFilter( &imgDepthBufferAux, 1.0, FILTER_BLUR);
//filename.Printf( "imgDepthBuffer_mulblur_%04d", *aDst_gl_texture );
//imgDepthBuffer.saveAsPNG( filename );
imgDepthBuffer.invert();
//filename.Printf( "imgDepthBuffer_invert_%04d", *aDst_gl_texture );
//imgDepthBuffer.saveAsPNG( filename );
unsigned char *depthbufferRGBA = (unsigned char*) malloc( aTexture_size * aTexture_size * 4 );
unsigned char *pPixels = imgDepthBuffer.GetBuffer();
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 + 1] = 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 );
......@@ -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 );
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 )
{
......@@ -170,6 +166,8 @@ void EDA_3D_CANVAS::GenerateFakeShadowsTextures( wxString* aErrorMessages, bool
// Init info 3d parameters and create gl lists:
CreateDrawGL_List( aErrorMessages, aShowWarnings );
DBG( unsigned strtime = GetRunningMicroSecs() );
m_shadow_init = true;
glClearColor( 0, 0, 0, 1 );
......@@ -177,45 +175,80 @@ void EDA_3D_CANVAS::GenerateFakeShadowsTextures( wxString* aErrorMessages, bool
glMatrixMode( GL_PROJECTION );
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,
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,
0.0, ZDIST_MAX );
0.0, zDistMax );
float zpos = GetPrm3DVisu().GetLayerZcoordBIU( F_Paste ) * GetPrm3DVisu().m_BiuTo3Dunits;
// Render FRONT shadow
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0, 0, 0.03 );
glRotatef( 180, 0.0, 1.0, 0.0 );
glTranslatef( 0.0f, 0.0f, zpos );
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
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0, 0, 0.03 );
///glRotatef( 0.0, 0.0, 1.0, 0.0 );
glTranslatef( 0.0f, 0.0f, fabs( zpos ) );
// 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
glMatrixMode( GL_PROJECTION );
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,
-GetPrm3DVisu().m_BoardSize.y * SHADOW_BOARD_SCALE * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f,
GetPrm3DVisu().m_BoardSize.y * SHADOW_BOARD_SCALE * GetPrm3DVisu().m_BiuTo3Dunits / 2.0f,
0.0, 6.0f * ZDIST_MAX );
// Normalization scale to convert bouding box
// to normalize 3D units between -1.0 and +1.0
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 );
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()
if( isEnabled( FL_MODULE ) && isRealisticMode() &&
isEnabled( FL_RENDER_SHADOWS ) )
{
GenerateFakeShadowsTextures( &errorMessages, showWarnings );
generateFakeShadowsTextures( &errorMessages, showWarnings );
}
// *MUST* be called *after* SetCurrent( ):
......@@ -290,6 +323,7 @@ void EDA_3D_CANVAS::Redraw()
glLoadIdentity();
#define MAX_VIEW_ANGLE 160.0 / 45.0
if( GetPrm3DVisu().m_Zoom > MAX_VIEW_ANGLE )
GetPrm3DVisu().m_Zoom = MAX_VIEW_ANGLE;
......@@ -309,14 +343,14 @@ void EDA_3D_CANVAS::Redraw()
double ratio_HV = (double) size.x / size.y;
// 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
glMatrixMode( GL_MODELVIEW );
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:
SetLights();
......@@ -324,6 +358,7 @@ void EDA_3D_CANVAS::Redraw()
CheckGLError( __FILE__, __LINE__ );
glMatrixMode( GL_MODELVIEW ); // position viewer
// transformations
GLfloat mat[4][4];
......@@ -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
glTranslatef( -GetPrm3DVisu().m_BoardPos.x * GetPrm3DVisu().m_BiuTo3Dunits,
-GetPrm3DVisu().m_BoardPos.y * GetPrm3DVisu().m_BiuTo3Dunits,
0.0F );
// draw all objects in lists
// transparent objects should be drawn after opaque objects
0.0f );
if( isEnabled( FL_MODULE ) )
{
......@@ -358,29 +390,42 @@ void EDA_3D_CANVAS::Redraw()
CreateDrawGL_List( &errorMessages, showWarnings );
}
glEnable( GL_LIGHTING );
glEnable( GL_BLEND );
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 ) )
{
glDisable( GL_LIGHTING );
if( 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 );
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 );
if( m_glLists[GL_ID_BOARD] )
......@@ -388,17 +433,17 @@ void EDA_3D_CANVAS::Redraw()
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] )
{
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glCallList( m_glLists[GL_ID_TECH_LAYERS] );
}
......@@ -410,7 +455,9 @@ void EDA_3D_CANVAS::Redraw()
glCallList( m_glLists[GL_ID_AUX_LAYERS] );
}
// Draw Component Shadow
if( isEnabled( FL_MODULE ) && isRealisticMode() &&
isEnabled( FL_RENDER_SHADOWS ) )
{
......@@ -419,7 +466,7 @@ void EDA_3D_CANVAS::Redraw()
glEnable( GL_COLOR_MATERIAL ) ;
SetOpenGlDefaultMaterial();
glColor4f( 1.0, 1.0, 1.0, 1.0 );
glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
glEnable( GL_TEXTURE_2D );
......@@ -437,19 +484,21 @@ void EDA_3D_CANVAS::Redraw()
glBindTexture( GL_TEXTURE_2D, m_text_fake_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 );
glDisable( GL_TEXTURE_2D );
glDisable( GL_CULL_FACE );
}
glEnable(GL_COLOR_MATERIAL);
glEnable( GL_COLOR_MATERIAL );
SetOpenGlDefaultMaterial();
glDisable( GL_BLEND );
// Draw Solid Shapes
if( isEnabled( FL_MODULE ) )
{
if( ! m_glLists[GL_ID_3DSHAPES_SOLID_FRONT] )
......@@ -461,25 +510,29 @@ void EDA_3D_CANVAS::Redraw()
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
// Grid uses transparency: draw it after all objects
if( isEnabled( FL_GRID ) && m_glLists[GL_ID_GRID] )
glCallList( m_glLists[GL_ID_GRID] );
// 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] )
{
glEnable( GL_BLEND );
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 );
glDisable( GL_COLOR_MATERIAL );
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, m_text_fake_shadow_board );
glCallList( m_glLists[GL_ID_SHADOW_BOARD] );
glDisable( GL_CULL_FACE );
glDisable( GL_TEXTURE_2D );
}
}
......@@ -488,12 +541,23 @@ void EDA_3D_CANVAS::Redraw()
// non transparent objects
if( isEnabled( FL_MODULE ) && m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] )
{
glDisable( GL_TEXTURE_2D );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
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();
if( !errorMessages.IsEmpty() )
......@@ -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
wxSize brd_size = getBoardSize();
wxPoint brd_center_pos = getBoardCenter();
float xsize = brd_size.x;
float ysize = brd_size.y;
// Board shadows are based on board dimension.
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 xmin = m_boardAABBox.Min().x;
float xmax = m_boardAABBox.Max().x;
float ymin = m_boardAABBox.Min().y;
float ymax = m_boardAABBox.Max().y;
float zpos = GetPrm3DVisu().GetLayerZcoordBIU( F_Paste );
zpos *= GetPrm3DVisu().m_BiuTo3Dunits;
float zpos = GetPrm3DVisu().GetLayerZcoordBIU( F_Paste ) * GetPrm3DVisu().m_BiuTo3Dunits;
// Shadow FRONT
glNewList( aFrontList, GL_COMPILE );
......@@ -537,8 +594,7 @@ void EDA_3D_CANVAS::BuildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint
// Shadow BACK
zpos = GetPrm3DVisu().GetLayerZcoordBIU( B_Paste );
zpos *= GetPrm3DVisu().m_BiuTo3Dunits;
zpos = GetPrm3DVisu().GetLayerZcoordBIU( B_Paste ) * GetPrm3DVisu().m_BiuTo3Dunits;
glNewList( aBacklist, GL_COMPILE );
......@@ -553,33 +609,29 @@ void EDA_3D_CANVAS::BuildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint
glEndList();
// 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 );
glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( F_Paste ) );
glBegin (GL_QUADS);
glTexCoord2f( 1.0, 0.0 ); glVertex3f( xmin, ymin, zpos * 30.0);
glTexCoord2f( 0.0, 0.0 ); glVertex3f( xmax, ymin, zpos * 30.0);
glTexCoord2f( 0.0, 1.0 ); glVertex3f( xmax, ymax, zpos * 30.0);
glTexCoord2f( 1.0, 1.0 ); glVertex3f( xmin, ymax, zpos * 30.0);
glTexCoord2f( 1.0, 0.0 ); glVertex3f( xmin, ymin, m_fastAABBox_Shadow.Min().z );
glTexCoord2f( 0.0, 0.0 ); glVertex3f( xmax, ymin, m_fastAABBox_Shadow.Min().z );
glTexCoord2f( 0.0, 1.0 ); glVertex3f( xmax, ymax, m_fastAABBox_Shadow.Min().z );
glTexCoord2f( 1.0, 1.0 ); glVertex3f( xmin, ymax, m_fastAABBox_Shadow.Min().z );
glEnd();
glEndList();
}
void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
wxString* aErrorMessages, bool aShowWarnings )
{
BOARD* pcb = GetBoard();
......@@ -599,12 +651,12 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
// ( We already used this trick in plot_board_layers.cpp,
// see PlotSolderMaskLayer() )
const int segcountforcircle = 18;
double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2) );
const int segcountLowQuality = 12; // segments to draw a circle with low quality
double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2.0) );
const int segcountLowQuality = 8; // segments to draw a circle with low quality
// to reduce time calculations
// for holes and items which do not need
// 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;
bufferPolys.reserve( 200000 ); // Reserve for large board (tracks mainly)
......@@ -640,7 +692,7 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
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 );
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,
D_PAD* pad = module->Pads();
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,
segcountLowQuality );
(int)(segcountLowQuality * segFactor) );
}
}
}
......@@ -813,7 +872,8 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
throughHolesListBuilt = true;
}
if ( !isEnabled( FL_SHOW_BOARD_BODY ) )
if ( !isEnabled( FL_SHOW_BOARD_BODY ) ||
isEnabled( FL_USE_COPPER_THICKNESS ) )
{
setGLCopperColor();
......@@ -823,14 +883,15 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
const VIA *via = dynamic_cast<const VIA*>(track);
if( via )
Draw3DViaHole( via );
draw3DViaHole( via );
}
// Draw pads holes (vertical cylinders)
for( const MODULE* module = pcb->m_Modules; module; module = module->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,
if( isRealisticMode() )
{
setGLEpoxyColor( 0.95 );
setGLEpoxyColor( 1.00 );
}
else
{
......@@ -862,10 +923,10 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
// are drawn from zpos - copper_thickness/2 to zpos + copper_thickness
// therefore substrate position is copper_thickness/2 to
// substrate_height - copper_thickness/2
zpos += (copper_thickness + epsilon) / 2.0;
zpos += (copper_thickness + epsilon) / 2.0f;
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 polysetHoles;
......@@ -883,7 +944,7 @@ void EDA_3D_CANVAS::BuildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
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 );
}
......@@ -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();
bool useTextures = isRealisticMode() && isEnabled( FL_RENDER_TEXTURES );
......@@ -1016,7 +1077,7 @@ void EDA_3D_CANVAS::BuildTechLayers3DView( wxString* aErrorMessages, bool aShowW
if( !pad->IsOnLayer( layer ) )
continue;
BuildPadShapeThickOutlineAsPolygon( pad, bufferPolys,
buildPadShapeThickOutlineAsPolygon( pad, bufferPolys,
linewidth, segcountforcircle, correctionFactor );
}
}
......@@ -1110,12 +1171,12 @@ void EDA_3D_CANVAS::BuildTechLayers3DView( wxString* aErrorMessages, bool aShowW
/**
* Function BuildBoard3DAuxLayers
* Function buildBoard3DAuxLayers
* Called by CreateDrawGL_List()
* Fills the OpenGL GL_ID_BOARD draw list with items
* on aux layers only
*/
void EDA_3D_CANVAS::BuildBoard3DAuxLayers()
void EDA_3D_CANVAS::buildBoard3DAuxLayers()
{
const int segcountforcircle = 18;
double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2) );
......@@ -1222,54 +1283,48 @@ void EDA_3D_CANVAS::CreateDrawGL_List( wxString* aErrorMessages, bool aShowWarni
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
// Create axis gl list (if it is not shown, the list will be not called
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();
}
draw3DAxis();
// 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] )
{
DBG( unsigned strtime = GetRunningMicroSecs() );
m_glLists[GL_ID_BOARD] = 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__ );
DBG( printf( " buildBoard3DView total time %f ms\n", (double) (GetRunningMicroSecs() - strtime) / 1000.0 ) );
}
if( ! m_glLists[GL_ID_TECH_LAYERS] )
{
DBG( unsigned strtime = GetRunningMicroSecs() );
m_glLists[GL_ID_TECH_LAYERS] = glGenLists( 1 );
glNewList( m_glLists[GL_ID_TECH_LAYERS], GL_COMPILE );
// when calling BuildTechLayers3DView,
// do not show warnings, which are the same as BuildBoard3DView
BuildTechLayers3DView( aErrorMessages, false );
// do not show warnings, which are the same as buildBoard3DView
buildTechLayers3DView( aErrorMessages, false );
glEndList();
CheckGLError( __FILE__, __LINE__ );
DBG( printf( " buildTechLayers3DView total time %f ms\n", (double) (GetRunningMicroSecs() - strtime) / 1000.0 ) );
}
if( ! m_glLists[GL_ID_AUX_LAYERS] )
{
DBG( unsigned strtime = GetRunningMicroSecs() );
m_glLists[GL_ID_AUX_LAYERS] = glGenLists( 1 );
glNewList( m_glLists[GL_ID_AUX_LAYERS], GL_COMPILE );
BuildBoard3DAuxLayers();
buildBoard3DAuxLayers();
glEndList();
CheckGLError( __FILE__, __LINE__ );
DBG( printf( " buildBoard3DAuxLayers total time %f ms\n", (double) (GetRunningMicroSecs() - strtime) / 1000.0 ) );
}
// draw modules 3D shapes
......@@ -1289,58 +1344,130 @@ void EDA_3D_CANVAS::CreateDrawGL_List( wxString* aErrorMessages, bool aShowWarni
else
m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] = 0;
BuildFootprintShape3DList( m_glLists[GL_ID_3DSHAPES_SOLID_FRONT],
m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT], false );
buildFootprintShape3DList( m_glLists[GL_ID_3DSHAPES_SOLID_FRONT],
m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] );
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 );
if( !m_glLists[GL_ID_SHADOW_BACK] )
m_glLists[GL_ID_SHADOW_BACK] = glGenLists( 1 );
if( !m_glLists[GL_ID_SHADOW_BOARD] )
m_glLists[GL_ID_SHADOW_BOARD] = glGenLists( 1 );
BuildShadowList( m_glLists[GL_ID_SHADOW_FRONT], m_glLists[GL_ID_SHADOW_BACK],
m_glLists[GL_ID_SHADOW_BOARD]);
buildShadowList( m_glLists[GL_ID_SHADOW_FRONT],
m_glLists[GL_ID_SHADOW_BACK],
m_glLists[GL_ID_SHADOW_BOARD] );
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
unsigned endtime = GetRunningMicroSecs();
wxString msg;
msg.Printf( "Built data %.1f ms", (double) (endtime - strtime) / 1000 );
Parent()->SetStatusText( msg, 0 );
#endif
S3D_MASTER* shape3D = module->Models();
for( ; shape3D; shape3D = shape3D->Next() )
{
if( shape3D->Is3DType( S3D_MASTER::FILE3D_VRML ) )
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,
GLuint aTransparentList, bool aSideToLoad)
void EDA_3D_CANVAS::buildFootprintShape3DList( GLuint aOpaqueList,
GLuint aTransparentList )
{
#ifdef PRINT_CALCULATION_TIME
unsigned strtime = GetRunningMicroSecs();
#endif
// This lists are used to just load once of each filename model
std::vector<S3D_MODEL_PARSER *> model_parsers_list;
std::vector<wxString> model_filename_list;
DBG( unsigned strtime = GetRunningMicroSecs() );
// clean the parser list if it have any already loaded files
m_model_parsers_list.clear();
m_model_filename_list.clear();
BOARD* pcb = GetBoard();
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
Read3DComponentShape( module, model_parsers_list, model_filename_list );
read3DComponentShape( module );
#ifdef PRINT_CALCULATION_TIME
{
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
DBG( printf( " read3DComponentShape total time %f ms\n", (double) (GetRunningMicroSecs() - strtime) / 1000.0 ) );
#ifdef PRINT_CALCULATION_TIME
strtime = GetRunningMicroSecs();
#endif
DBG( strtime = GetRunningMicroSecs() );
bool useMaterial = g_Parm_3D_Visu.GetFlag( FL_RENDER_MATERIAL );
......@@ -1354,8 +1481,9 @@ void EDA_3D_CANVAS::BuildFootprintShape3DList( GLuint aOpaqueList,
bool loadOpaqueObjects = true;
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
Render3DComponentShape( module, loadOpaqueObjects,
!loadOpaqueObjects, aSideToLoad );
render3DComponentShape( module, loadOpaqueObjects,
!loadOpaqueObjects );
glEndList();
......@@ -1363,8 +1491,8 @@ void EDA_3D_CANVAS::BuildFootprintShape3DList( GLuint aOpaqueList,
bool loadTransparentObjects = true;
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
Render3DComponentShape( module, !loadTransparentObjects,
loadTransparentObjects, aSideToLoad );
render3DComponentShape( module, !loadTransparentObjects,
loadTransparentObjects );
glEndList();
}
......@@ -1374,25 +1502,18 @@ void EDA_3D_CANVAS::BuildFootprintShape3DList( GLuint aOpaqueList,
glNewList( aOpaqueList, GL_COMPILE );
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
Render3DComponentShape( module, false, false, aSideToLoad );
render3DComponentShape( module, false, false );
glEndList();
}
#ifdef PRINT_CALCULATION_TIME
{
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
DBG( printf( " render3DComponentShape total time %f ms\n", (double) (GetRunningMicroSecs() - strtime) / 1000.0 ) );
}
bool EDA_3D_CANVAS::Read3DComponentShape( MODULE* module,
std::vector<S3D_MODEL_PARSER *>& model_parsers_list,
std::vector<wxString>& model_filename_list )
bool EDA_3D_CANVAS::read3DComponentShape( MODULE* module )
{
if( module )
{
S3D_MASTER* shape3D = module->Models();
for( ; shape3D; shape3D = shape3D->Next() )
......@@ -1405,9 +1526,9 @@ bool EDA_3D_CANVAS::Read3DComponentShape( MODULE* module,
wxString shape_filename = shape3D->GetShape3DFullFilename();
// 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;
break;
......@@ -1416,14 +1537,25 @@ bool EDA_3D_CANVAS::Read3DComponentShape( MODULE* module,
if( found == false )
{
shape3D->ReadData();
model_filename_list.push_back( shape_filename );
model_parsers_list.push_back( shape3D->m_parser );
// Create a new parser
S3D_MODEL_PARSER *newParser = S3D_MODEL_PARSER::Create( shape3D, shape3D->GetShape3DExtension() );
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
{
DBG( printf( " Read3DComponentShape reusing %s\n", (const char*)shape_filename.c_str() ) );
shape3D->m_parser = model_parsers_list[i];
// Reusing file
shape3D->m_parser = m_model_parsers_list[i];
}
}
}
}
......@@ -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 aIsRenderingJustTransparentObjects,
bool aSideToLoad )
bool aIsRenderingJustTransparentObjects )
{
// Read from disk and draws the footprint 3D shapes if exists
double zpos = GetPrm3DVisu().GetModulesZcoord3DIU( module->IsFlipped() );
glPushMatrix();
......@@ -1449,12 +1579,12 @@ void EDA_3D_CANVAS::Render3DComponentShape( MODULE* module,
zpos );
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() )
{
glRotatef( 180.0, 0.0, 1.0, 0.0 );
glRotatef( 180.0, 0.0, 0.0, 1.0 );
glRotatef( 180.0f, 0.0f, 1.0f, 0.0f );
glRotatef( 180.0f, 0.0f, 0.0f, 1.0f );
}
S3D_MASTER* shape3D = module->Models();
......@@ -1464,9 +1594,27 @@ void EDA_3D_CANVAS::Render3DComponentShape( MODULE* module,
if( shape3D->Is3DType( S3D_MASTER::FILE3D_VRML ) )
{
glPushMatrix();
shape3D->Render( aIsRenderingJustNonTransparentObjects,
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();
// Debug AABBox
//thisBBox = shape3D->getfastAABBox();
//thisBBox.GLdebug();
}
}
......
......@@ -36,7 +36,7 @@
#include <modelparsers.h>
// Number of segments to approximate a circle by segments
#define SEGM_PER_CIRCLE 16
#define SEGM_PER_CIRCLE 24
#ifndef CALLBACK
#define CALLBACK
......@@ -57,12 +57,12 @@ static void CALLBACK tessCPolyPt2Vertex( const GLvoid* data );
// 2 helper functions to set the current normal vector for gle items
static inline void SetNormalZpos()
{
//glNormal3f( 0.0, 0.0, 1.0 );
glNormal3f( 0.0, 0.0, 1.0 );
}
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 );
......@@ -203,6 +203,7 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
}
// https://www.opengl.org/sdk/docs/man2/xhtml/gluTessNormal.xml
if( !aThickness )
gluTessNormal( tess, 0.0, 0.0, 0.0 );
......@@ -231,6 +232,7 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
s_currentZpos = zpos; // for Tess callback functions
v_data[2] = zpos;
// Set normal toward negative Z axis, for a solid object on bottom side
if( aThickness )
SetNormalZneg();
}
......@@ -248,7 +250,7 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
}
// 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,
if( aHeight )
{
// Draw the vertical outer side
Draw3D_VerticalPolygonalCylinder( outer_cornerBuffer,
aHeight, aZpos, false, aBiuTo3DUnits );
if( aThickness )
// Draws the vertical inner side (hole)
Draw3D_VerticalPolygonalCylinder( inner_cornerBuffer,
......
......@@ -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] )
{
......@@ -207,7 +207,7 @@ void EDA_3D_CANVAS::Draw3DAxis()
// draw a 3D grid: an horizontal grid (XY plane and Z = 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;
EDA_COLOR_T gridcolor = DARKGRAY; // Color of grid lines
......@@ -343,7 +343,7 @@ void EDA_3D_CANVAS::Draw3DGrid( double aGriSizeMM )
// 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
wxSize drillsize = aPad->GetDrillSize();
......@@ -363,13 +363,13 @@ void EDA_3D_CANVAS::Draw3DPadHole( const D_PAD* aPad )
else
SetGLColor( DARKGRAY );
int holeZpoz = GetPrm3DVisu().GetLayerZcoordBIU( B_Cu ) + thickness / 2;
int holeHeight = height - thickness;
int holeZpoz = GetPrm3DVisu().GetLayerZcoordBIU( B_Cu ) - thickness / 2;
int holeHeight = height + thickness;
if( drillsize.x == drillsize.y ) // usual round hole
{
Draw3D_ZaxisCylinder( aPad->GetPosition(),
(drillsize.x + thickness) / 2, holeHeight,
(drillsize.x + thickness / 2) / 2, holeHeight,
thickness, holeZpoz, GetPrm3DVisu().m_BiuTo3Dunits );
}
else // Oblong hole
......@@ -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;
int inner_radius = aVia->GetDrillValue() / 2;
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 );
......@@ -419,17 +419,17 @@ void EDA_3D_CANVAS::Draw3DViaHole( const VIA* aVia )
}
int height = GetPrm3DVisu().GetLayerZcoordBIU( top_layer ) -
GetPrm3DVisu().GetLayerZcoordBIU( bottom_layer ) - thickness;
int zpos = GetPrm3DVisu().GetLayerZcoordBIU( bottom_layer ) + thickness / 2;
GetPrm3DVisu().GetLayerZcoordBIU( bottom_layer ) + thickness;
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 );
}
/* Build a pad outline as non filled polygon, to draw pads on silkscreen layer
* 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,
int aWidth,
int aCircleToSegmentsCount,
......
......@@ -57,6 +57,7 @@ static const wxChar keyRenderTextures[] = wxT( "Render_Textures" );
static const wxChar keyRenderSmoothNormals[] = wxT( "Render_Smooth_Normals" );
static const wxChar keyRenderUseModelNormals[] =wxT( "Render_Use_Model_Normals" );
static const wxChar keyRenderMaterial[] = wxT( "Render_Material" );
static const wxChar keyRenderShowModelBBox[] = wxT( "Render_ShowModelBoudingBoxes" );
static const wxChar keyShowAxis[] = wxT( "ShowAxis" );
static const wxChar keyShowGrid[] = wxT( "ShowGrid3D" );
......@@ -257,6 +258,9 @@ void EDA_3D_FRAME::LoadSettings( wxConfigBase* aCfg )
aCfg->Read( keyRenderMaterial, &tmp, false );
prms.SetFlag( FL_RENDER_MATERIAL, tmp );
aCfg->Read( keyRenderShowModelBBox, &tmp, false );
prms.SetFlag( FL_RENDER_SHOW_MODEL_BBOX, tmp );
aCfg->Read( keyShowAxis, &tmp, true );
prms.SetFlag( FL_AXIS, tmp );
......@@ -319,6 +323,7 @@ void EDA_3D_FRAME::SaveSettings( wxConfigBase* aCfg )
aCfg->Write( keyRenderSmoothNormals, prms.GetFlag( FL_RENDER_SMOOTH_NORMALS ) );
aCfg->Write( keyRenderUseModelNormals, prms.GetFlag( FL_RENDER_USE_MODEL_NORMALS ) );
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( keyShowGrid, prms.GetFlag( FL_GRID ) );
......@@ -509,6 +514,11 @@ void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event )
NewDisplay();
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:
GetPrm3DVisu().SetFlag( FL_SHOW_BOARD_BODY, isChecked );
NewDisplay();
......@@ -526,43 +536,43 @@ void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_MENU3D_USE_COPPER_THICKNESS:
GetPrm3DVisu().SetFlag( FL_USE_COPPER_THICKNESS, isChecked );
NewDisplay(GL_ID_BOARD);
NewDisplay(GL_ID_TECH_LAYERS);
NewDisplay( GL_ID_BOARD );
NewDisplay( GL_ID_TECH_LAYERS );
return;
case ID_MENU3D_ZONE_ONOFF:
GetPrm3DVisu().SetFlag( FL_ZONE, isChecked );
NewDisplay(GL_ID_BOARD);
NewDisplay( GL_ID_BOARD );
return;
case ID_MENU3D_ADHESIVE_ONOFF:
GetPrm3DVisu().SetFlag( FL_ADHESIVE, isChecked );
NewDisplay(GL_ID_TECH_LAYERS);
NewDisplay( GL_ID_TECH_LAYERS );
return;
case ID_MENU3D_SILKSCREEN_ONOFF:
GetPrm3DVisu().SetFlag( FL_SILKSCREEN, isChecked );
NewDisplay(GL_ID_TECH_LAYERS);
NewDisplay( GL_ID_TECH_LAYERS );
return;
case ID_MENU3D_SOLDER_MASK_ONOFF:
GetPrm3DVisu().SetFlag( FL_SOLDERMASK, isChecked );
NewDisplay(GL_ID_TECH_LAYERS);
NewDisplay( GL_ID_TECH_LAYERS );
return;
case ID_MENU3D_SOLDER_PASTE_ONOFF:
GetPrm3DVisu().SetFlag( FL_SOLDERPASTE, isChecked );
NewDisplay(GL_ID_TECH_LAYERS);
NewDisplay();
return;
case ID_MENU3D_COMMENTS_ONOFF:
GetPrm3DVisu().SetFlag( FL_COMMENTS, isChecked );
NewDisplay(GL_ID_AUX_LAYERS);
NewDisplay( GL_ID_AUX_LAYERS );
return;
case ID_MENU3D_ECO_ONOFF:
GetPrm3DVisu().SetFlag( FL_ECO, isChecked );
NewDisplay(GL_ID_AUX_LAYERS);
NewDisplay( GL_ID_AUX_LAYERS );
return;
default:
......
/*
* 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.
*
* 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 ) :
void SetOpenGlDefaultMaterial()
{
glm::vec4 ambient( 0.2, 0.2, 0.2, 1.0 );
glm::vec4 specular( 0.0, 0.0, 0.0, 1.0 );
glm::vec4 emissive( 0.0, 0.0, 0.0, 1.0 );
glm::vec4 diffuse( 0.0, 0.0, 0.0, 1.0 );
glm::vec4 ambient( 0.2f, 0.2f, 0.2f, 1.0f );
glm::vec4 specular( 0.0f, 0.0f, 0.0f, 1.0f );
glm::vec4 emissive( 0.0f, 0.0f, 0.0f, 1.0f );
glm::vec4 diffuse( 0.0f, 0.0f, 0.0f, 1.0f );
GLint shininess_value = 0;
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
......
/*
* 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.
*
* 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.
*
* 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.
*
* This program is free software; you can redistribute it and/or
......@@ -27,14 +27,29 @@
* @brief
*/
#include <fctsys.h>
#include <3d_mesh_model.h>
#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
#include <omp.h>
#endif // USE_OPENMP
#include "info3d_visu.h"
S3D_MESH::S3D_MESH()
{
isPerFaceNormalsComputed = false;
......@@ -47,13 +62,95 @@ S3D_MESH::S3D_MESH()
m_translation = glm::vec3( 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_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()
{
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
openGL_Render( aIsRenderingJustNonTransparentObjects,
aIsRenderingJustTransparentObjects );
// Render childs
// Render childs recursively
for( unsigned int idx = 0; idx < childs.size(); idx++ )
{
childs[idx]->openGL_Render( aIsRenderingJustNonTransparentObjects,
childs[idx]->openGL_RenderAllChilds( aIsRenderingJustNonTransparentObjects,
aIsRenderingJustTransparentObjects );
}
......@@ -142,7 +239,7 @@ void S3D_MESH::openGL_Render( bool aIsRenderingJustNonTransparentObjects,
{
if( m_Materials )
{
if ( m_MaterialIndex.size() > 0 )
if ( m_MaterialIndex.size() > idx )
{
bool isTransparent = m_Materials->SetOpenGLMaterial( m_MaterialIndex[idx], useMaterial );
......@@ -153,9 +250,9 @@ void S3D_MESH::openGL_Render( bool aIsRenderingJustNonTransparentObjects,
continue;
if( useMaterial )
if( m_Materials->m_Transparency.size() > idx )
if( m_Materials->m_Transparency[idx] >= 1.0f )
return;
if( (int)m_Materials->m_Transparency.size() > m_MaterialIndex[idx] )
if( m_Materials->m_Transparency[m_MaterialIndex[idx]] >= 1.0f )
continue;
}
else
{
......@@ -270,37 +367,37 @@ void S3D_MESH::perVertexNormalsVerify_and_Repair()
{
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.z = 0.0;
normal.y = 0.0f;
normal.z = 0.0f;
}
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.z = 0.0;
normal.x = 0.0f;
normal.z = 0.0f;
}
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.y = 0.0;
normal.x = 0.0f;
normal.y = 0.0f;
}
else
if( (normal.x < FLT_EPSILON) && (normal.x > -FLT_EPSILON) )
{
normal.x = 0.0;
normal.x = 0.0f;
}
else
if( (normal.y < FLT_EPSILON) && (normal.y > -FLT_EPSILON) )
{
normal.y = 0.0;
normal.y = 0.0f;
}
else
if( (normal.z < FLT_EPSILON) && (normal.z > -FLT_EPSILON) )
{
normal.z = 0.0;
normal.z = 0.0f;
}
float l = glm::length( normal );
......@@ -328,10 +425,6 @@ void S3D_MESH::calcPointNormalized()
isPointNormalizedComputed = true;
/*
m_PointNormalized = m_Point;
*/
m_PointNormalized.clear();
m_PointNormalized.resize( m_Point.size() );
......@@ -406,9 +499,9 @@ void S3D_MESH::calcPerFaceNormals()
{
glm::vec3 cross_prod;
cross_prod.x = 0.0;
cross_prod.y = 0.0;
cross_prod.z = 0.0;
cross_prod.x = 0.0f;
cross_prod.y = 0.0f;
cross_prod.z = 0.0f;
// Newell's Method
// http://www.opengl.org/wiki/Calculating_a_Surface_Normal
......@@ -434,15 +527,6 @@ void S3D_MESH::calcPerFaceNormals()
float area = glm::dot( cross_prod, cross_prod );
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;
if( haveAlreadyNormals_from_model_file == false )
......@@ -456,35 +540,35 @@ void S3D_MESH::calcPerFaceNormals()
}
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,
cross_prod.x, cross_prod.y, cross_prod.z,
l,
(unsigned int)m_CoordIndex[idx].size()) );
*/
if( ( cross_prod.x > cross_prod.y ) && ( cross_prod.x > cross_prod.z ) )
{
cross_prod.x = 0.0;
cross_prod.y = 1.0;
cross_prod.z = 0.0;
cross_prod.x = 0.0f;
cross_prod.y = 1.0f;
cross_prod.z = 0.0f;
}
else if( ( cross_prod.y > cross_prod.x ) && ( cross_prod.y > cross_prod.z ) )
{
cross_prod.x = 0.0;
cross_prod.y = 1.0;
cross_prod.z = 0.0;
cross_prod.x = 0.0f;
cross_prod.y = 1.0f;
cross_prod.z = 0.0f;
}
else if( ( cross_prod.z > cross_prod.x ) && ( cross_prod.z > cross_prod.y ) )
{
cross_prod.x = 0.0;
cross_prod.y = 0.0;
cross_prod.z = 1.0;
cross_prod.x = 0.0f;
cross_prod.y = 0.0f;
cross_prod.z = 1.0f;
}
else
{
cross_prod.x = 0.0;
cross_prod.y = 0.0;
cross_prod.z = 0.0;
cross_prod.x = 0.0f;
cross_prod.y = 0.0f;
cross_prod.z = 0.0f;
}
}
......@@ -494,6 +578,7 @@ void S3D_MESH::calcPerFaceNormals()
}
// Documentation literature
// http://www.bytehazard.com/code/vertnorm.html
// http://www.emeyex.com/site/tuts/VertexNormals.pdf
void S3D_MESH::calcPerPointNormals()
......
/*
* 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.
*
* This program is free software; you can redistribute it and/or
......@@ -30,24 +30,12 @@
#ifndef __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 <kicad_string.h>
#include <info3d_visu.h>
#ifdef __WXMAC__
# ifdef __DARWIN__
# include <OpenGL/glu.h>
# else
# include <glu.h>
# endif
#else
# include <GL/glu.h>
#endif
#include <wx/glcanvas.h>
#include <gal/opengl/glm/glm.hpp>
#include "3d_struct.h"
#include "3d_material.h"
#include "CBBox.h"
class S3D_MESH;
......@@ -64,26 +52,24 @@ public:
S3D_MATERIAL *m_Materials;
// 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_NormalIndex;
std::vector< glm::vec3 > m_PerFaceNormalsNormalized;
std::vector< glm::vec3 > m_PerVertexNormalsNormalized;
std::vector< S3D_VERTEX > m_PerFaceNormalsNormalized;
std::vector< S3D_VERTEX > m_PerVertexNormalsNormalized;
std::vector< int > m_MaterialIndex;
std::vector< S3D_MESH * > childs;
glm::vec3 m_translation;
S3D_VERTEX m_translation;
glm::vec4 m_rotation;
glm::vec3 m_scale;
glm::vec4 m_scaleOrientation; // not used
glm::vec3 m_center; // not used
S3D_VERTEX m_scale;
std::vector<S3D_MESH *> childs;
CBBOX &getBBox();
private:
std::vector< glm::vec3 > m_PerFaceNormalsRaw_X_PerFaceSquaredArea;
std::vector< std::vector< glm::vec3 > > m_PerFaceVertexNormals;
std::vector< glm::vec3 > m_PointNormalized;
std::vector< S3D_VERTEX > m_PerFaceNormalsRaw_X_PerFaceSquaredArea;
std::vector< std::vector< S3D_VERTEX > > m_PerFaceVertexNormals;
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
......@@ -99,6 +85,11 @@ private:
bool isPerVertexNormalsVerified;
void perVertexNormalsVerify_and_Repair();
void calcBBox();
void calcBBoxAllChilds();
CBBOX m_BBox;
void openGL_Render( bool aIsRenderingJustNonTransparentObjects,
bool aIsRenderingJustTransparentObjects );
};
......
/*
* 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) 2011 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
......@@ -32,14 +33,14 @@
#include <macros.h>
#include <kicad_string.h>
#include <pgm_base.h>
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
#include <3d_viewer.h>
#include <info3d_visu.h>
#include "3d_struct.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 )
{
if ( aExtension == wxT( "x3d" ) )
......@@ -50,46 +51,25 @@ S3D_MODEL_PARSER* S3D_MODEL_PARSER::Create( S3D_MASTER* aMaster,
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() )
return shapeName;
if( !default_path.EndsWith( wxT("/") ) && !default_path.EndsWith( wxT("\\") ) )
default_path += wxT("/");
default_path += shapeName;
return default_path;
}
int S3D_MASTER::ReadData()
int S3D_MASTER::ReadData( S3D_MODEL_PARSER* aParser )
{
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__
filename.Replace( wxT( "/" ), wxT( "\\" ) );
......@@ -97,35 +77,30 @@ int S3D_MASTER::ReadData()
filename.Replace( wxT( "\\" ), wxT( "/" ) );
#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 );
wxString extension = fn.GetExt();
m_parser = S3D_MODEL_PARSER::Create( this, extension );
if( m_parser )
if( aParser->Load( filename ) )
{
m_parser->Load( filename );
// Invalidate bounding boxes
m_fastAABBox.Reset();
m_BBox.Reset();
m_parser = aParser;
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;
}
void S3D_MASTER::Render( bool aIsRenderingJustNonTransparentObjects,
bool aIsRenderingJustTransparentObjects )
{
......@@ -136,31 +111,80 @@ void S3D_MASTER::Render( bool aIsRenderingJustNonTransparentObjects,
glScalef( aVrmlunits_to_3Dunits, aVrmlunits_to_3Dunits, aVrmlunits_to_3Dunits );
glm::vec3 matScale( m_MatScale.x,
m_MatScale.y,
m_MatScale.z );
glTranslatef( m_MatPosition.x * SCALE_3D_CONV,
m_MatPosition.y * SCALE_3D_CONV,
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,
m_MatRotation.y,
m_MatRotation.z );
glScalef( m_MatScale.x, m_MatScale.y, m_MatScale.z );
glm::vec3 matPos( m_MatPosition.x,
m_MatPosition.y,
m_MatPosition.z );
for( unsigned int idx = 0; idx < m_parser->childs.size(); idx++ )
m_parser->childs[idx]->openGL_RenderAllChilds( aIsRenderingJustNonTransparentObjects,
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 );
glRotatef( -matRot.y, 0.0f, 1.0f, 0.0f );
glRotatef( -matRot.x, 1.0f, 0.0f, 0.0f );
CBBOX &S3D_MASTER::getBBox( )
{
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++ )
if( firstBBox )
{
m_parser->childs[idx]->openGL_RenderAllChilds( aIsRenderingJustNonTransparentObjects,
aIsRenderingJustTransparentObjects );
firstBBox = false;
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.
*
* 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) 2011 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
......@@ -34,54 +34,12 @@
#include <common.h>
#include <base_struct.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 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;
// Master structure for a 3D footprint shape description
......@@ -112,8 +70,10 @@ public:
bool m_use_modelfile_shininess;
private:
wxString m_Shape3DName; // the 3D shape filename in 3D library
FILE3D_TYPE m_ShapeType;
wxString m_Shape3DName; ///< The 3D shape filename in 3D library
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:
S3D_MASTER( EDA_ITEM* aParent );
......@@ -131,8 +91,9 @@ public:
* Function ReadData
* Select the parser to read the 3D data file (vrml, x3d ...)
* 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,
bool aIsRenderingJustTransparentObjects );
......@@ -177,6 +138,12 @@ public:
*/
const wxString GetShape3DFullFilename();
/**
* Function GetShape3DExtension
* @return the extension of the filename of the 3D shape,
*/
const wxString GetShape3DExtension();
/**
* Function SetShape3DName
* @param aShapeName = file name of the data file relative to the 3D shape
......@@ -185,6 +152,23 @@ public:
* (vrl, x3d, idf ) the type of file.
*/
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:
#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
......@@ -187,6 +187,10 @@ void EDA_3D_FRAME::CreateMenuBar()
_( "Render Material Properties" ),
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();
wxMenu * backgrounColorMenu = new wxMenu;
......@@ -300,6 +304,9 @@ void EDA_3D_FRAME::SetMenuBarOptionsState()
item = menuBar->FindItem( ID_MENU3D_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->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
ID_MENU3D_FL_RENDER_SMOOTH_NORMALS,
ID_MENU3D_FL_RENDER_USE_MODEL_NORMALS,
ID_MENU3D_FL_RENDER_MATERIAL,
ID_MENU3D_FL_RENDER_SHOW_MODEL_BBOX,
ID_END_COMMAND_3D,
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 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file CImage.cpp
* @brief one 8bit-channel image implementation
*/
#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;}
#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_width = xsize;
m_height = ysize;
m_wxh = xsize * ysize;
m_wxh = aXsize * aYsize;
m_pixels = (unsigned char*)malloc( m_wxh );
m_width = aXsize;
m_height = aYsize;
m_wraping = (E_WRAP)WRAP_CLAMP;
}
......@@ -43,10 +52,16 @@ CIMAGE::~CIMAGE()
}
bool CIMAGE::wrapCoords( int *xo, int *yo )
unsigned char* CIMAGE::GetBuffer() const
{
int x = *xo;
int y = *yo;
return m_pixels;
}
bool CIMAGE::wrapCoords( int *aXo, int *aYo ) const
{
int x = *aXo;
int y = *aYo;
switch(m_wraping)
{
......@@ -66,40 +81,41 @@ bool CIMAGE::wrapCoords( int *xo, int *yo )
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;
*xo = x;
*yo = y;
*aXo = x;
*aYo = y;
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 ) )
m_pixels[x + y * m_width] = value;
if( wrapCoords( &aX, &aY ) )
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 ) )
return m_pixels[x + y * m_width];
if( wrapCoords( &aX, &aY ) )
return m_pixels[aX + aY * m_width];
else
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];
}
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;
......@@ -117,8 +133,7 @@ void CIMAGE::copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOpe
switch(aOperation)
{
case COPY_RAW:
for( unsigned int it = 0;it < m_wxh; it++ )
m_pixels[it] = aImgA->m_pixels[it];
memcpy( m_pixels, aImgA->m_pixels, m_wxh );
break;
case COPY_ADD:
......@@ -189,6 +204,13 @@ void CIMAGE::copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOpe
break;
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;
case COPY_MIN:
......@@ -210,11 +232,16 @@ void CIMAGE::copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOpe
m_pixels[it] = (aV > bV)?aV:bV;
}
break;
default:
break;
}
}
S_FILTER FILTERS[9] = {
// TIP: If you want create or test filters you can use GIMP
// 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
{
{ { 0, -1, -1, -1, 0},
......@@ -230,17 +257,28 @@ S_FILTER FILTERS[9] = {
// Blur
{
{ { 3, 5, 7, 5, 3},
{ 4, 9, 12, 9, 5},
{ 5, 9, 12, 9, 5},
{ 7, 12, 20, 12, 7},
{ 4, 9, 12, 9, 5},
{ 5, 9, 12, 9, 5},
{ 3, 5, 7, 5, 3}
},
180,
182,
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},
{ 2, -2, 1, -2, 2},
......@@ -326,31 +364,41 @@ S_FILTER FILTERS[9] = {
};// 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];
aInImg->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 ix = 0; ix < (int)m_width; ix++ )
{
int v = filter.offset;
int v = 0;
for( int sy = 0; sy < 5; sy++ )
{
for( int sx = 0; sx < 5; sx++ )
{
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 /= filter.div;
v += filter.offset;
CLAMP(v, 0, 255);
m_pixels[ix + iy * m_width] = v;
......@@ -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++ )
{
......@@ -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* alphabuffer = (unsigned char*) malloc( m_width * aHeight );
wxImage image( m_width, m_height );
for( unsigned int i = 0; i < m_wxh; i++)
{
unsigned char v = m_pixels[i];
// Set RGB value with all same values intensities
pixelbuffer[i * 3 + 0] = v;
pixelbuffer[i * 3 + 1] = v;
pixelbuffer[i * 3 + 2] = v;
//alphabuffer[i * 1 + 0] = aRGBABufferImage[i * 4 + 3];
}
image.SetData( pixelbuffer );
//image.SetAlpha( alphabuffer );
image = image.Mirror( false );
image.SaveFile( aFileName + ".png", wxBITMAP_TYPE_PNG );
image.Destroy();
}
......@@ -22,11 +22,17 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file CImage.h
* @brief one 8bit-channel image definition
*/
#ifndef CImage_h
#define CImage_h
#include <wx/image.h>
#include <wx/string.h>
/// Image operation type
enum E_IMAGE_OP {
COPY_RAW,
COPY_ADD,
......@@ -41,17 +47,23 @@ enum E_IMAGE_OP {
COPY_MAX
};
/// Image wrap type enumeration
enum E_WRAP {
WRAP_ZERO, ///< Coords that wraps are not evaluated
WRAP_CLAMP,
WRAP_CLAMP, ///< Coords are clamped to image size
WRAP_WRAP ///< Coords are wrapped arround
};
/// Filter type enumeration
enum E_FILTER {
FILTER_HIPASS,
FILTER_BLUR
FILTER_GAUSSIAN_BLUR,
FILTER_INVERT_BLUR,
};
/// 5x5 Filter struct parameters
typedef struct {
signed char kernel[5][5];
unsigned char div;
......@@ -59,36 +71,120 @@ typedef struct {
}S_FILTER;
/**
* Class CIMAGE
* manages a 8-bit channel image
*/
class CIMAGE
{
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();
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:
bool wrapCoords( int *xo, int *yo );
public:
unsigned char* m_pixels;
unsigned int m_width;
unsigned int m_height;
unsigned int m_wxh;
E_WRAP m_wraping;
/**
* Function wrapCoords
* calculate the coordinates points in accord with the current clamping settings
* @param aXo X coordinate to be converted (output)
* @param aXo Y coordinate to be converted (output)
* @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
vrml_v2_modelparser.cpp
x3dmodelparser.cpp
CImage.cpp
CBBox.cpp
)
add_library(3d-viewer STATIC ${3D-VIEWER_SRCS})
......
......@@ -231,10 +231,19 @@ void INFO3D_VISU::InitSettings( BOARD* aBoard )
*/
double INFO3D_VISU::GetModulesZcoord3DIU( bool aIsFlipped )
{
// NOTE: Z position to display modules in top of Paste and near the shadow
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
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 {
FL_RENDER_SMOOTH_NORMALS,
FL_RENDER_USE_MODEL_NORMALS,
FL_RENDER_MATERIAL,
FL_RENDER_SHOW_MODEL_BBOX,
FL_LAST
};
......
......@@ -35,7 +35,6 @@
#include <3d_mesh_model.h>
class S3D_MASTER;
class S3D_MODEL_PARSER;
class X3D_MODEL_PARSER;
/**
......@@ -49,13 +48,7 @@ public:
master( aMaster )
{}
~S3D_MODEL_PARSER()
{
for( unsigned int idx = 0; idx < childs.size(); idx++ )
{
delete childs[idx];
}
}
virtual ~S3D_MODEL_PARSER(){}
S3D_MASTER* GetMaster()
{
......@@ -73,22 +66,14 @@ public:
static S3D_MODEL_PARSER* Create( S3D_MASTER* aMaster, const wxString aExtension );
/**
* pure virtual Function
* virtual Function
* Concrete parsers should implement this function
* @param aFilename = the full file name of the file to load
* @return true if as succeeded
*/
virtual bool Load( const wxString& aFilename ) = 0;
/**
* 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 );
virtual bool Load( const wxString& aFilename ) {
return false;
};
std::vector< S3D_MESH* > childs;
......@@ -158,6 +143,7 @@ private:
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
......@@ -171,6 +157,15 @@ public:
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
* Function Load must be called before this function, otherwise empty
......@@ -179,6 +174,7 @@ public:
wxString VRML2_representation();
private:
int loadFileModel( S3D_MESH *transformationModel );
int read_Transform();
int read_DEF();
int read_DEF_Coordinate();
......@@ -195,16 +191,33 @@ private:
int read_Color();
int read_coordIndex();
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 colorPerVertex;
S3D_MESH* m_model;
S3D_MESH* m_model; ///< It stores the current model that the parsing is adding data
FILE* m_file;
wxString m_Filename;
wxFileName m_Filename;
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_MASTER* m_Master;
wxString m_debugSpacer; ///< Used to give identation space
};
......@@ -267,7 +280,6 @@ public:
* by the vrml file data
*/
VRML_MODEL_PARSER( S3D_MASTER* aMaster );
~VRML_MODEL_PARSER();
/**
......@@ -279,11 +291,6 @@ public:
* to our internal units.
*/
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.
*
* 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.
*
* This program is free software; you can redistribute it and/or
......@@ -24,11 +24,58 @@
/**
* @file vrml_aux.cpp
* @brief implements auxiliar functions to parse VRML files
*/
#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 );
......@@ -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;
......@@ -150,12 +197,12 @@ int read_NotImplemented( FILE* File, char closeChar )
if( c == '{' )
{
// DBG( printf( "{\n") );
read_NotImplemented( File, '}' );
Read_NotImplemented( File, '}' );
}
else if( c == '[' )
{
// DBG( printf( "[\n") );
read_NotImplemented( File, ']' );
Read_NotImplemented( File, ']' );
}
else if( c == 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();
glm::vec3 vertex;
while( parseVertex( File, vertex ) == 3 )
while( ParseVertex( File, vertex ) == 3 )
{
dst_vector.push_back( vertex );
}
......@@ -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;
int ret = fscanf( File, "%e %e %e", &a, &b, &c );
......@@ -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;
int ret = fscanf( File, "%e", &value );
......
/*
* 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.
*
* This program is free software; you can redistribute it and/or
......@@ -24,6 +24,7 @@
/**
* @file vrml_aux.h
* @brief auxiliar functions to parse VRML files
*/
#ifndef _VRML_AUX_H
......@@ -48,10 +49,63 @@
#endif
#include <wx/glcanvas.h>
int read_NotImplemented( FILE* File, char closeChar);
int parseVertexList( FILE* File, std::vector< glm::vec3 > &dst_vector);
int parseVertex( FILE* File, glm::vec3 &dst_vertex );
int parseFloat( FILE* File, float *dst_float );
/**
* Function GetEpoxyThicknessBIU
* skip a VRML block and eventualy internal blocks until it find the close char
* @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 );
/**
* 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
......@@ -138,7 +138,7 @@ int VRML1_MODEL_PARSER::read_separator()
else if( ( *text != '}' ) )
{
// DBG( printf( "read_NotImplemented %s\n", text ) );
read_NotImplemented( m_file, '}' );
Read_NotImplemented( m_file, '}' );
}
else
break;
......@@ -272,7 +272,7 @@ int VRML1_MODEL_PARSER::readMaterial_ambientColor()
{
// 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()
{
// 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()
{
// 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 )
{
......@@ -303,7 +303,7 @@ int VRML1_MODEL_PARSER::readMaterial_specularColor()
{
// 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 )
{
......@@ -368,7 +368,7 @@ int VRML1_MODEL_PARSER::readCoordinate3_point()
{
// 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;
}
......
/*
* 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) 2012 Jean-Pierre Charras, jp.charras@wanadoo.fr
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
......@@ -39,7 +39,7 @@
#include "modelparsers.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.
......@@ -58,6 +58,7 @@ VRML2_MODEL_PARSER::VRML2_MODEL_PARSER( S3D_MODEL_PARSER* aModelParser )
m_file = NULL;
m_normalPerVertex = true;
colorPerVertex = true;
m_debugSpacer = "";
}
......@@ -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 )
{
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" ) );
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;
}
m_Filename = aFilename;
// Switch the locale to standard C (needed to print floating point numbers)
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) ) )
{
......@@ -95,49 +154,125 @@ bool VRML2_MODEL_PARSER::Load( const wxString& aFilename )
if( strcmp( text, "Transform" ) == 0 )
{
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() );
//wxLogTrace( traceVrmlV2Parser, wxT( " m_CoordIndex.size: %u" ), (unsigned int)m_model->m_CoordIndex.size() );
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, "DEF" ) == 0 )
{
m_model = new S3D_MESH();
m_ModelParser->childs.push_back( m_model );
S3D_MESH* save_ptr = m_model;
if( read_DEF() == 0 )
{
//wxLogTrace( traceVrmlV2Parser, wxT( " m_Point.size: %u" ), (unsigned int)m_model->m_Point.size() );
//wxLogTrace( traceVrmlV2Parser, wxT( " m_CoordIndex.size: %u" ), (unsigned int)m_model->m_CoordIndex.size() );
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( "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 )
{
//wxLogTrace( traceVrmlV2Parser, wxT( " Shape" ) );
m_model = new S3D_MESH();
m_ModelParser->childs.push_back( m_model );
S3D_MESH* save_ptr = m_model;
if( read_Shape() == 0 )
{
//wxLogTrace( traceVrmlV2Parser, wxT( " m_Point.size: %u" ), (unsigned int)m_model->m_Point.size() );
//wxLogTrace( traceVrmlV2Parser, wxT( " m_CoordIndex.size: %u" ), (unsigned int)m_model->m_CoordIndex.size() );
}
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( "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()
{
//wxLogTrace( traceVrmlV2Parser, wxT( " read_Transform" ) );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform" ) );
debug_enter();
char text[BUFLINE_SIZE];
......@@ -150,17 +285,50 @@ int VRML2_MODEL_PARSER::read_Transform()
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)" ),
// m_model->m_translation.x,
// m_model->m_translation.y,
// m_model->m_translation.z );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "translation (%f,%f,%f)" ),
m_model->m_translation.x,
m_model->m_translation.y,
m_model->m_translation.z );
}
else if( strcmp( text, "rotation" ) == 0 )
{
......@@ -174,39 +342,41 @@ int VRML2_MODEL_PARSER::read_Transform()
m_model->m_rotation[2] = 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
{
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)" ),
// m_model->m_rotation[0],
// m_model->m_rotation[1],
// m_model->m_rotation[2],
// m_model->m_rotation[3] );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "rotation (%f,%f,%f,%f)" ),
m_model->m_rotation[0],
m_model->m_rotation[1],
m_model->m_rotation[2],
m_model->m_rotation[3] );
}
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 )
{
// this m_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],
&m_model->m_scaleOrientation[2],
&m_model->m_scaleOrientation[3] ) != 4 )
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "scaleOrientation is not implemented, but it will be parsed" ) );
glm::vec4 vecDummy;
if( fscanf( m_file, "%f %f %f %f", &vecDummy[0],
&vecDummy[1],
&vecDummy[2],
&vecDummy[3] ) != 4 )
{
m_model->m_scaleOrientation[0] = 0.0f;
m_model->m_scaleOrientation[1] = 0.0f;
m_model->m_scaleOrientation[2] = 0.0f;
m_model->m_scaleOrientation[3] = 0.0f;
vecDummy[0] = 0.0f;
vecDummy[1] = 0.0f;
vecDummy[2] = 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)" ),
......@@ -217,9 +387,11 @@ int VRML2_MODEL_PARSER::read_Transform()
}
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 )
{
......@@ -244,21 +416,52 @@ int VRML2_MODEL_PARSER::read_Transform()
}
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 )
{
//wxLogTrace( traceVrmlV2Parser, wxT( " Shape" ) );
// Save the pointer
S3D_MESH* parent = m_model;
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;
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;
}
......@@ -266,26 +469,175 @@ int VRML2_MODEL_PARSER::read_Transform()
{
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
{
wxLogTrace( traceVrmlV2Parser, wxT( " %s NotImplemented" ), text );
read_NotImplemented( m_file, '}' );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Transform: USE %s Add child model with %lu points, %lu coordIndex, %lu childs." ),
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;
}
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()
{
//wxLogTrace( traceVrmlV2Parser, wxT( " read_DEF_Coordinate" ) );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF_Coordinate" ) );
debug_enter();
char text[BUFLINE_SIZE];
// Get the name of the definition.
if( !GetNextTag( m_file, text, sizeof(text) ) )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF_Coordinate failed to get next tag" ) );
return -1;
}
std::string coordinateName = text;
......@@ -295,7 +647,11 @@ int VRML2_MODEL_PARSER::read_DEF_Coordinate()
continue;
if( *text == '}' )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF_Coordinate exit" ) );
return 0;
}
if( strcmp( text, "Coordinate" ) == 0 )
{
......@@ -304,25 +660,29 @@ int VRML2_MODEL_PARSER::read_DEF_Coordinate()
if( retVal == 0 )
m_defCoordinateMap.insert( std::make_pair( coordinateName, m_model->m_Point ) );
debug_exit();
return retVal;
}
}
wxLogTrace( traceVrmlV2Parser, wxT( " read_DEF_Coordinate failed" ) );
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF_Coordinate failed" ) );
return -1;
}
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 tagName[BUFLINE_SIZE];
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;
}
......@@ -330,18 +690,23 @@ int VRML2_MODEL_PARSER::read_DEF()
{
if( *text == ']' )
{
wxLogTrace( traceVrmlV2Parser, wxT( " skipping %c" ), *text );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "skipping %c" ), *text );
continue;
}
if( *text == '}' )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_DEF exit" ) );
return 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 )
{
......@@ -361,37 +726,113 @@ int VRML2_MODEL_PARSER::read_DEF()
}
else if( strcmp( text, "Shape" ) == 0 )
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "Shape" ) );
// Save the pointer
S3D_MESH* parent = m_model;
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;
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;
}
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
{
wxLogTrace( traceVrmlV2Parser, wxT( " DEF %s %s NotImplemented, skipping." ), tagName, text );
read_NotImplemented( m_file, '}' );
delete m_model;
}
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;
}
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];
// Get the name of the definition.
if( !GetNextTag( m_file, text, sizeof(text) ) )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedFaceSet_USE failed to get next tag" ) );
return -1;
}
std::string coordinateName = text;
......@@ -402,19 +843,22 @@ int VRML2_MODEL_PARSER::read_USE()
// Not previously defined.
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 );
return -1;
}
m_model->m_Point = coordinate->second;
debug_exit();
return 0;
}
int VRML2_MODEL_PARSER::read_Shape()
{
//wxLogTrace( traceVrmlV2Parser, wxT( " read_Shape" ) );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Shape" ) );
debug_enter();
char text[BUFLINE_SIZE];
......@@ -427,6 +871,8 @@ int VRML2_MODEL_PARSER::read_Shape()
if( *text == '}' )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Shape exit" ) );
return 0;
}
......@@ -441,8 +887,7 @@ int VRML2_MODEL_PARSER::read_Shape()
}
else if( strcmp( text, "geometry" ) == 0 )
{
//wxLogTrace( traceVrmlV2Parser, wxT( " \"geometry\" key word not supported." ) );
// skip
read_geometry();
}
else if( strcmp( text, "IndexedFaceSet" ) == 0 )
{
......@@ -454,19 +899,76 @@ int VRML2_MODEL_PARSER::read_Shape()
}
else
{
wxLogTrace( traceVrmlV2Parser, wxT( " %s NotImplemented" ), text );
read_NotImplemented( m_file, '}' );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "%s NotImplemented" ), text );
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;
}
int VRML2_MODEL_PARSER::read_Appearance()
{
//wxLogTrace( traceVrmlV2Parser, wxT( " read_Appearance" ) );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Appearance" ) );
debug_enter();
char text[BUFLINE_SIZE];
......@@ -479,6 +981,8 @@ int VRML2_MODEL_PARSER::read_Appearance()
if( *text == '}' )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Appearance exit" ) );
return 0;
}
......@@ -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;
}
int VRML2_MODEL_PARSER::read_material()
{
//wxLogTrace( traceVrmlV2Parser, wxT( " read_material" ) );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_material" ) );
debug_enter();
S3D_MATERIAL* material = NULL;
char text[BUFLINE_SIZE];
......@@ -511,7 +1017,9 @@ int VRML2_MODEL_PARSER::read_material()
if( strcmp( text, "Material" ) == 0 )
{
return read_Material();
int ret = read_Material();
debug_exit();
return ret;
}
}
else if( strcmp( text, "DEF" ) == 0 )
......@@ -529,7 +1037,9 @@ int VRML2_MODEL_PARSER::read_material()
{
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()
if( material->m_Name == mat_name )
{
m_model->m_Materials = material;
debug_exit();
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;
}
int VRML2_MODEL_PARSER::read_Material()
{
//wxLogTrace( traceVrmlV2Parser, wxT( " read_Material" ) );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Material" ) );
debug_enter();
char text[BUFLINE_SIZE];
glm::vec3 vertex;
......@@ -576,17 +1089,19 @@ int VRML2_MODEL_PARSER::read_Material()
if( *text == '}' )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Material exit" ) );
return 0;
}
if( strcmp( text, "diffuseColor" ) == 0 )
{
parseVertex( m_file, vertex );
ParseVertex( m_file, vertex );
m_model->m_Materials->m_DiffuseColor.push_back( vertex );
}
else if( strcmp( text, "emissiveColor" ) == 0 )
{
parseVertex( m_file, vertex );
ParseVertex( m_file, vertex );
if( m_Master->m_use_modelfile_emissiveColor == true )
{
......@@ -595,7 +1110,7 @@ int VRML2_MODEL_PARSER::read_Material()
}
else if( strcmp( text, "specularColor" ) == 0 )
{
parseVertex( m_file, vertex );
ParseVertex( m_file, vertex );
if( m_Master->m_use_modelfile_specularColor == true )
{
......@@ -605,7 +1120,7 @@ int VRML2_MODEL_PARSER::read_Material()
else if( strcmp( text, "ambientIntensity" ) == 0 )
{
float ambientIntensity;
parseFloat( m_file, &ambientIntensity );
ParseFloat( m_file, &ambientIntensity );
if( m_Master->m_use_modelfile_ambientIntensity == true )
{
......@@ -616,7 +1131,7 @@ int VRML2_MODEL_PARSER::read_Material()
else if( strcmp( text, "transparency" ) == 0 )
{
float transparency;
parseFloat( m_file, &transparency );
ParseFloat( m_file, &transparency );
if( m_Master->m_use_modelfile_transparency == true )
{
......@@ -626,7 +1141,7 @@ int VRML2_MODEL_PARSER::read_Material()
else if( strcmp( text, "shininess" ) == 0 )
{
float shininess;
parseFloat( m_file, &shininess );
ParseFloat( m_file, &shininess );
// VRML value is normalized and openGL expects a value 0 - 128
if( m_Master->m_use_modelfile_shininess == true )
......@@ -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;
}
int VRML2_MODEL_PARSER::read_IndexedFaceSet()
{
//wxLogTrace( traceVrmlV2Parser, wxT( " read_IndexedFaceSet" ) );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedFaceSet" ) );
debug_enter();
char text[BUFLINE_SIZE];
......@@ -660,6 +1177,8 @@ int VRML2_MODEL_PARSER::read_IndexedFaceSet()
if( *text == '}' )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedFaceSet exit" ) );
return 0;
}
......@@ -712,18 +1231,20 @@ int VRML2_MODEL_PARSER::read_IndexedFaceSet()
}
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;
}
int VRML2_MODEL_PARSER::read_IndexedLineSet()
{
//wxLogTrace( traceVrmlV2Parser, wxT( " read_IndexedLineSet" ) );
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedLineSet" ) );
debug_enter();
char text[BUFLINE_SIZE];
......@@ -733,7 +1254,11 @@ int VRML2_MODEL_PARSER::read_IndexedLineSet()
continue;
if( *text == '}' )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedLineSet exit" ) );
return 0;
}
if( strcmp( text, "Coordinate" ) == 0 )
read_Coordinate();
......@@ -743,13 +1268,16 @@ int VRML2_MODEL_PARSER::read_IndexedLineSet()
read_DEF_Coordinate();
}
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_IndexedLineSet failed" ) );
return -1;
}
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();
......@@ -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;
}
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();
......@@ -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;
}
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();
......@@ -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;
}
int VRML2_MODEL_PARSER::read_Color()
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Color" ) );
debug_enter();
char text[BUFLINE_SIZE];
while( GetNextTag( m_file, text, sizeof(text) ) )
......@@ -864,22 +1397,28 @@ int VRML2_MODEL_PARSER::read_Color()
if( *text == '}' )
{
debug_exit();
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Color exit" ) );
return 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;
}
int VRML2_MODEL_PARSER::read_Normal()
{
wxLogTrace( traceVrmlV2Parser, m_debugSpacer + wxT( "read_Normal" ) );
debug_enter();
char text[BUFLINE_SIZE];
while( GetNextTag( m_file, text, sizeof(text) ) )
......@@ -891,11 +1430,14 @@ int VRML2_MODEL_PARSER::read_Normal()
if( *text == '}' )
{
// Debug
//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
// 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;
}
......@@ -903,22 +1445,25 @@ int VRML2_MODEL_PARSER::read_Normal()
{
if( m_normalPerVertex == false )
{
parseVertexList( m_file, m_model->m_PerFaceNormalsNormalized );
ParseVertexList( m_file, m_model->m_PerFaceNormalsNormalized );
}
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;
}
int VRML2_MODEL_PARSER::read_Coordinate()
{
debug_enter();
char text[BUFLINE_SIZE];
while( GetNextTag( m_file, text, sizeof(text) ) )
......@@ -930,17 +1475,20 @@ int VRML2_MODEL_PARSER::read_Coordinate()
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;
}
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;
}
......@@ -950,6 +1498,8 @@ int VRML2_MODEL_PARSER::read_Coordinate()
*/
int VRML2_MODEL_PARSER::read_CoordinateDef()
{
debug_enter();
char text[BUFLINE_SIZE];
while( GetNextTag( m_file, text, sizeof(text) ) )
......@@ -959,14 +1509,17 @@ int VRML2_MODEL_PARSER::read_CoordinateDef()
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;
}
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;
}
......@@ -41,17 +41,20 @@
VRML_MODEL_PARSER::VRML_MODEL_PARSER( S3D_MASTER* aMaster ) :
S3D_MODEL_PARSER( aMaster )
{
vrml1_parser = NULL;
vrml2_parser = NULL;
m_curr3DShape = NULL;
}
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 )
{
char line[11 + 1];
......@@ -72,20 +75,20 @@ bool VRML_MODEL_PARSER::Load( const wxString& aFilename )
fclose( file );
childs.clear();
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 );
delete vrml2_parser;
vrml2_parser = NULL;
return true;
}
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 );
delete vrml1_parser;
vrml1_parser = NULL;
return true;
}
......
......@@ -58,6 +58,14 @@ X3D_MODEL_PARSER::X3D_MODEL_PARSER( S3D_MASTER* aMaster ) :
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