Commit 64bae1cf authored by Brian Sidebotham's avatar Brian Sidebotham

Intermediate Changes

parents 24aa7aa5 0cf334a0
......@@ -151,7 +151,7 @@ void TransfertToGLlist( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUni
glEnd();
}
VERTEX_VALUE_CTRL::VERTEX_VALUE_CTRL( wxWindow* aParent, wxBoxSizer* aBoxSizer )
S3DPOINT_VALUE_CTRL::S3DPOINT_VALUE_CTRL( wxWindow* aParent, wxBoxSizer* aBoxSizer )
{
wxString text;
......@@ -187,15 +187,16 @@ VERTEX_VALUE_CTRL::VERTEX_VALUE_CTRL( wxWindow* aParent, wxBoxSizer* aBoxSizer )
}
VERTEX_VALUE_CTRL::~VERTEX_VALUE_CTRL()
S3DPOINT_VALUE_CTRL::~S3DPOINT_VALUE_CTRL()
{
// Nothing to delete: all items are managed by the parent window.
}
S3D_VERTEX VERTEX_VALUE_CTRL::GetValue()
S3DPOINT S3DPOINT_VALUE_CTRL::GetValue()
{
S3D_VERTEX value;
double dtmp;
S3DPOINT value;
double dtmp;
m_XValueCtrl->GetValue().ToDouble( &dtmp );
value.x = dtmp;
......@@ -207,7 +208,7 @@ S3D_VERTEX VERTEX_VALUE_CTRL::GetValue()
}
void VERTEX_VALUE_CTRL::SetValue( S3D_VERTEX vertex )
void S3DPOINT_VALUE_CTRL::SetValue( S3DPOINT vertex )
{
wxString text;
......@@ -225,7 +226,7 @@ void VERTEX_VALUE_CTRL::SetValue( S3D_VERTEX vertex )
}
void VERTEX_VALUE_CTRL::Enable( bool onoff )
void S3DPOINT_VALUE_CTRL::Enable( bool onoff )
{
m_XValueCtrl->Enable( onoff );
m_YValueCtrl->Enable( onoff );
......
This diff is collapsed.
......@@ -46,6 +46,7 @@
class BOARD_DESIGN_SETTINGS;
class EDA_3D_FRAME;
class CPOLYGONS_LIST;
class VIA;
class D_PAD;
......@@ -63,12 +64,12 @@ enum GL_LIST_ID
GL_ID_AUX_LAYERS, // List id for user layers (draw, eco, comment)
GL_ID_3DSHAPES_SOLID_FRONT, // List id for 3D shapes, non transparent entities
GL_ID_3DSHAPES_TRANSP_FRONT,// List id for 3D shapes, transparent entities
GL_ID_3DSHAPES_SOLID_BACK, // List id for 3D shapes, non transparent entities
GL_ID_3DSHAPES_TRANSP_BACK,// List id for 3D shapes, transparent entities
GL_ID_3DSHAPES_SOLID_BACK, // List id for 3D shapes, non transparent entities
GL_ID_3DSHAPES_TRANSP_BACK, // List id for 3D shapes, transparent entities
GL_ID_SHADOW_FRONT,
GL_ID_SHADOW_BACK,
GL_ID_SHADOW_BOARD,
GL_ID_BODY, // Body only list
GL_ID_BODY, // Body only list
GL_ID_END
};
......@@ -134,14 +135,72 @@ public:
void CreateDrawGL_List();
void InitGL();
void SetLights();
void SetOffset(double aPosX, double aPosY)
{
m_draw3dOffset.x = aPosX;
m_draw3dOffset.y = aPosY;
}
void SetGLTechLayersColor( LAYER_NUM aLayer );
void SetGLCopperColor();
void SetGLEpoxyColor( double aTransparency = 1.0 );
/** @return the INFO3D_VISU which contains the current parameters
* to draw the 3D view og the board
*/
INFO3D_VISU& GetPrm3DVisu() const;
private:
/**
* return true if we are in realistic mode render
*/
bool isRealisticMode() const;
/**
* @return true if aItem should be displayed
* @param aItem = an item of DISPLAY3D_FLG enum
*/
bool isEnabled( DISPLAY3D_FLG aItem ) const;
/** Helper function
* @return true if aLayer should be displayed, false otherwise
*/
bool is3DLayerEnabled( LAYER_ID aLayer ) const;
/**
* @return the size of the board in pcb units
*/
wxSize getBoardSize() const;
/**
* @return the position of the board center in pcb units
*/
wxPoint getBoardCenter() const;
/**
* 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
* Initialize the copper color to draw the board
* in realistic mode (a golden yellow color )
*/
void setGLCopperColor();
/**
* Helper function SetGLEpoxyColor
* Initialize the color to draw the epoxy body board in realistic mode.
*/
void setGLEpoxyColor( double aTransparency = 1.0 );
/**
* Helper function SetGLSolderMaskColor
* Initialize the color to draw the solder mask layers in realistic mode.
*/
void setGLSolderMaskColor( double aTransparency = 1.0 );
/**
* Function BuildBoard3DView
......@@ -187,7 +246,31 @@ public:
void Draw3DGrid( double aGriSizeMM );
void Draw3DAxis();
/**
* Helper function BuildPadShapeThickOutlineAsPolygon:
* Build a pad outline as non filled polygon, to draw pads on silkscreen layer
* with a line thickness = aWidth
* Used only to draw pads outlines on silkscreen layers.
*/
void BuildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
CPOLYGONS_LIST& aCornerBuffer,
int aWidth,
int aCircleToSegmentsCount,
double aCorrectionFactor );
/**
* 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 );
/**
* 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 GenerateFakeShadowsTextures();
......
......@@ -78,11 +78,11 @@ S3D_MASTER::S3D_MASTER( EDA_ITEM* aParent ) :
m_ShapeType = FILE3D_NONE;
m_use_modelfile_diffuseColor = true;
m_use_modelfile_emissiveColor = false;
m_use_modelfile_specularColor = false;
m_use_modelfile_ambientIntensity = false;
m_use_modelfile_emissiveColor = true;
m_use_modelfile_specularColor = true;
m_use_modelfile_ambientIntensity = true;
m_use_modelfile_transparency = true;
m_use_modelfile_shininess = false;
m_use_modelfile_shininess = true;
}
......
This diff is collapsed.
......@@ -42,6 +42,12 @@
#define CALLBACK
#endif
// Variables used to pass a value to call back openGL functions
static float s_textureScale;
static double s_currentZpos;
static double s_biuTo3Dunits;
bool s_useTextures;
// CALLBACK functions for GLU_TESS
static void CALLBACK tessBeginCB( GLenum which );
static void CALLBACK tessEndCB();
......@@ -121,22 +127,26 @@ static void Draw3D_VerticalPolygonalCylinder( const CPOLYGONS_LIST& aPolysList,
void SetGLColor( EDA_COLOR_T color, double alpha )
{
double red, green, blue;
const StructColors &colordata = g_ColorRefs[ColorGetBase( color )];
red = colordata.m_Red / 255.0;
blue = colordata.m_Blue / 255.0;
green = colordata.m_Green / 255.0;
double red = colordata.m_Red / 255.0;
double blue = colordata.m_Blue / 255.0;
double green = colordata.m_Green / 255.0;
glColor4f( red, green, blue, alpha );
}
static float m_texture_scale;
void SetGLColor( S3D_COLOR& aColor, float aTransparency )
{
glColor4f( aColor.m_Red, aColor.m_Green, aColor.m_Blue, aTransparency );
}
void SetGLTexture( GLuint text_id, float scale )
{
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, text_id );
m_texture_scale = scale;
s_textureScale = scale; // for Tess callback functions
}
......@@ -149,8 +159,13 @@ void SetGLTexture( GLuint text_id, float scale )
* The bottom side is located at aZpos - aThickness / 2
*/
void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
int aZpos, int aThickness, double aBiuTo3DUnits )
int aZpos, int aThickness, double aBiuTo3DUnits,
bool aUseTextures )
{
// for Tess callback functions:
s_biuTo3Dunits = aBiuTo3DUnits;
s_useTextures = aUseTextures;
GLUtesselator* tess = gluNewTess();
gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )tessBeginCB );
......@@ -160,10 +175,10 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
GLdouble v_data[3];
double zpos = ( aZpos + (aThickness / 2.0) ) * aBiuTo3DUnits;
g_Parm_3D_Visu.m_CurrentZpos = zpos;
s_currentZpos = zpos; // for Tess callback functions
v_data[2] = aZpos + (aThickness / 2.0);
// Set normal to toward positive Z axis, for a solid object only (to draw the top side)
// Set normal toward positive Z axis, for a solid object on the top side
if( aThickness )
SetNormalZpos();
......@@ -213,9 +228,9 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
// Prepare the bottom side of solid areas
zpos = ( aZpos - (aThickness / 2.0) ) * aBiuTo3DUnits;
g_Parm_3D_Visu.m_CurrentZpos = zpos;
s_currentZpos = zpos; // for Tess callback functions
v_data[2] = zpos;
// Now;, set normal to toward negative Z axis, for the solid object bottom side
// Set normal toward negative Z axis, for a solid object on bottom side
SetNormalZneg();
}
......@@ -243,12 +258,12 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
*/
void Draw3D_SolidHorizontalPolygonWithHoles( const CPOLYGONS_LIST& aPolysList,
int aZpos, int aThickness,
double aBiuTo3DUnits )
double aBiuTo3DUnits, bool aUseTextures )
{
CPOLYGONS_LIST polygon;
ConvertPolysListWithHolesToOnePolygon( aPolysList, polygon );
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, aThickness, aBiuTo3DUnits );
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, aThickness, aBiuTo3DUnits, aUseTextures );
}
......@@ -295,13 +310,13 @@ void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius,
ConvertPolysListWithHolesToOnePolygon( outer_cornerBuffer, polygon );
// draw top (front) horizontal ring
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits );
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits, false );
if( aHeight )
{
// draw bottom (back) horizontal ring
SetNormalZneg();
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits );
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits, false );
}
}
......@@ -355,13 +370,13 @@ void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos,
// draw top (front) horizontal side (ring)
SetNormalZpos();
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits );
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits, false );
if( aHeight )
{
// draw bottom (back) horizontal side (ring)
SetNormalZneg();
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits );
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits, false );
}
}
......@@ -383,7 +398,7 @@ void Draw3D_SolidSegment( const wxPoint& aStart, const wxPoint& aEnd,
TransformRoundedEndsSegmentToPolygon( cornerBuffer, aStart, aEnd, slice, aWidth );
Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits );
Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false );
}
......@@ -397,7 +412,7 @@ void Draw3D_ArcSegment( const wxPoint& aCenterPos, const wxPoint& aStartPoint,
TransformArcToPolygon( cornerBuffer, aCenterPos, aStartPoint, aArcAngle,
slice, aWidth );
Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits );
Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false );
}
......@@ -422,15 +437,13 @@ void CALLBACK tessCPolyPt2Vertex( const GLvoid* data )
// cast back to double type
const CPolyPt* ptr = (const CPolyPt*) data;
if( g_Parm_3D_Visu.IsRealisticMode() && g_Parm_3D_Visu.HightQualityMode() )
if( s_useTextures )
{
glTexCoord2f( ptr->x* g_Parm_3D_Visu.m_BiuTo3Dunits * m_texture_scale,
-ptr->y * g_Parm_3D_Visu.m_BiuTo3Dunits * m_texture_scale);
glTexCoord2f( ptr->x * s_biuTo3Dunits * s_textureScale,
-ptr->y * s_biuTo3Dunits * s_textureScale);
}
glVertex3d( ptr->x * g_Parm_3D_Visu.m_BiuTo3Dunits,
-ptr->y * g_Parm_3D_Visu.m_BiuTo3Dunits,
g_Parm_3D_Visu.m_CurrentZpos );
glVertex3d( ptr->x * s_biuTo3Dunits, -ptr->y * s_biuTo3Dunits, s_currentZpos );
}
......
......@@ -36,13 +36,15 @@
* @param aZpos = z position in board internal units
* @param aThickness = thickness in board internal units
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
* @param aUseTextures = true to use textxures for the polygons
* If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
* If aThickness > 0, a solid object is drawn.
* The top side is located at aZpos + aThickness / 2
* The bottom side is located at aZpos - aThickness / 2
*/
void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
int aZpos, int aThickness, double aBiuTo3DUnits );
int aZpos, int aThickness, double aBiuTo3DUnits,
bool aUseTextures );
/** draw the solid polygon found in aPolysList
* The first polygonj is the main polygon, others are holes
......@@ -50,13 +52,15 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
* @param aZpos = z position in board internal units
* @param aThickness = thickness in board internal units
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
* @param aUseTextures = true to use textxures for the polygons
* If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
* If aThickness > 0, a solid object is drawn.
* The top side is located at aZpos + aThickness / 2
* The bottom side is located at aZpos - aThickness / 2
*/
void Draw3D_SolidHorizontalPolygonWithHoles( const CPOLYGONS_LIST& aPolysList,
int aZpos, int aThickness, double aBiuTo3DUnits );
int aZpos, int aThickness, double aBiuTo3DUnits,
bool aUseTextures );
/** draw a thick segment using 3D primitives, in a XY plane
* @param aStart = YX position of start point in board units
......@@ -125,6 +129,13 @@ void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos,
*/
void SetGLColor( EDA_COLOR_T aColor, double aTransparency = 1.0 );
/**
* Set the current 3D color from a S3D_COLOR color, with optional transparency
* @param aColor = a S3D_COLOR RGB color index
* @param aTransparency = the color transparency (default = 1.0 = no transparency)
*/
void SetGLColor( S3D_COLOR& aColor, float aTransparency );
/**
* Set a texture id and a scale to apply when rendering the polygons
......
This diff is collapsed.
This diff is collapsed.
......@@ -28,6 +28,7 @@
#include <fctsys.h>
#include <3d_struct.h>
#include <3d_material.h>
#include <info3d_visu.h>
#ifdef __WXMAC__
# ifdef __DARWIN__
......@@ -54,83 +55,96 @@ S3D_MATERIAL::S3D_MATERIAL( S3D_MASTER* father, const wxString& name ) :
void SetOpenGlDefaultMaterial()
{
glm::vec4 ambient( 0.15, 0.15, 0.15, 1.0 );
glm::vec4 specular( 0.1, 0.1, 0.1, 1.0 );
glm::vec4 emissive( 0.1, 0.1, 0.1, 1.0 );
GLint shininess_value = 80;
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 );
GLint shininess_value = 0;
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
//glColor4f( 1.0, 1.0, 1.0, 1.0 );
glMateriali ( GL_FRONT_AND_BACK, GL_SHININESS, shininess_value );
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, &emissive.x );
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.x );
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.x );
glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.x );
}
void S3D_MATERIAL::SetOpenGLMaterial( unsigned int materialIndex )
void S3D_MATERIAL::SetOpenGLMaterial( unsigned int aMaterialIndex, bool aUseMaterial )
{
S3D_MASTER * s3dParent = (S3D_MASTER *) GetParent();
if( ! s3dParent->IsOpenGlAllowed() )
return;
float transparency_value = 0.0f;
if( m_Transparency.size() > materialIndex )
if( aUseMaterial )
{
transparency_value = m_Transparency[materialIndex];
s3dParent->SetLastTransparency( transparency_value );
}
float transparency_value = 0.0f;
if( m_Transparency.size() > aMaterialIndex )
{
transparency_value = m_Transparency[aMaterialIndex];
s3dParent->SetLastTransparency( transparency_value );
}
if( m_DiffuseColor.size() > materialIndex )
{
glm::vec3 color = m_DiffuseColor[materialIndex];
if( m_DiffuseColor.size() > aMaterialIndex )
{
glm::vec3 color = m_DiffuseColor[aMaterialIndex];
if( m_AmbientColor.size() == 0 )
{
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
}
if( m_AmbientColor.size() == 0 )
glColor4f( color.x, color.y, color.z, 1.0 - transparency_value );
}
if( m_Shininess.size() > aMaterialIndex )
{
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, m_Shininess[aMaterialIndex] );
}
glColor4f( color.x, color.y, color.z, 1.0 - transparency_value );
}
if( m_Shininess.size() > materialIndex )
{
glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, m_Shininess[materialIndex] );
}
// emissive
if( m_EmissiveColor.size() > aMaterialIndex )
{
glm::vec4 emissive;
emissive[0] = m_EmissiveColor[aMaterialIndex].x;
emissive[1] = m_EmissiveColor[aMaterialIndex].y;
emissive[2] = m_EmissiveColor[aMaterialIndex].z;
emissive[3] = 1.0f;
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, &emissive.x );
}
// emissive
if( m_EmissiveColor.size() > materialIndex )
{
glm::vec4 emissive;
emissive[0] = m_EmissiveColor[materialIndex].x;
emissive[1] = m_EmissiveColor[materialIndex].y;
emissive[2] = m_EmissiveColor[materialIndex].z;
emissive[3] = 1.0f;
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, &emissive.x );
}
// specular
if( m_SpecularColor.size() > aMaterialIndex )
{
glm::vec4 specular;
specular[0] = m_SpecularColor[aMaterialIndex].x;
specular[1] = m_SpecularColor[aMaterialIndex].y;
specular[2] = m_SpecularColor[aMaterialIndex].z;
specular[3] = 1.0f;
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.x );
}
// specular
if( m_SpecularColor.size() > materialIndex )
{
glm::vec4 specular;
specular[0] = m_SpecularColor[materialIndex].x;
specular[1] = m_SpecularColor[materialIndex].y;
specular[2] = m_SpecularColor[materialIndex].z;
specular[3] = 1.0f;
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.x );
// ambient
if( m_AmbientColor.size() > aMaterialIndex )
{
glm::vec4 ambient;
ambient[0] = m_AmbientColor[aMaterialIndex].x;
ambient[1] = m_AmbientColor[aMaterialIndex].y;
ambient[2] = m_AmbientColor[aMaterialIndex].z;
ambient[3] = 1.0f;
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.x );
}
}
// ambient
if( m_AmbientColor.size() > materialIndex )
else
{
glm::vec4 ambient;
ambient[0] = m_AmbientColor[materialIndex].x;
ambient[1] = m_AmbientColor[materialIndex].y;
ambient[2] = m_AmbientColor[materialIndex].z;
ambient[3] = 1.0f;
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.x );
}
if( m_DiffuseColor.size() > aMaterialIndex )
{
glm::vec3 color = m_DiffuseColor[aMaterialIndex];
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
glColor4f( color.x, color.y, color.z, 1.0 );
}
}
}
......@@ -35,11 +35,11 @@
class S3D_MASTER;
class S3D_MATERIAL : public EDA_ITEM /* openGL "material" data*/
class S3D_MATERIAL : public EDA_ITEM // openGL "material" data
{
public:
wxString m_Name;
// Material list
std::vector< glm::vec3 > m_AmbientColor;
std::vector< glm::vec3 > m_DiffuseColor;
......@@ -54,7 +54,13 @@ public:
S3D_MATERIAL* Next() const { return (S3D_MATERIAL*) Pnext; }
S3D_MATERIAL* Back() const { return (S3D_MATERIAL*) Pback; }
void SetOpenGLMaterial(unsigned int materialIndex);
/**
* Initialize the material prms.
* @param aMaterialIndex = the index in list of available materials
* @param aUseMaterial = true to use the values found in the available material
* = false to use only the color, and other prms are fixed
*/
void SetOpenGLMaterial(unsigned int aMaterialIndex, bool aUseMaterial);
#if defined(DEBUG)
void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override
......
......@@ -24,13 +24,17 @@
/**
* @file 3d_mesh_model.cpp
* @brief
* @brief
*/
#include <3d_mesh_model.h>
#include <boost/geometry/algorithms/area.hpp>
#ifdef USE_OPENMP
#include <omp.h>
#endif // USE_OPENMP
S3D_MESH::S3D_MESH()
{
isPerFaceNormalsComputed = false;
......@@ -85,10 +89,13 @@ void S3D_MESH::openGL_RenderAllChilds()
void S3D_MESH::openGL_Render()
{
//DBG( printf( "openGL_Render" ) );
bool useMaterial = g_Parm_3D_Visu.GetFlag( FL_RENDER_MATERIAL );
bool smoothShapes = g_Parm_3D_Visu.IsRealisticMode()
&& g_Parm_3D_Visu.GetFlag( FL_RENDER_SMOOTH );
if( m_Materials )
{
m_Materials->SetOpenGLMaterial( 0 );
m_Materials->SetOpenGLMaterial( 0, useMaterial );
}
if( m_CoordIndex.size() == 0)
......@@ -109,7 +116,7 @@ void S3D_MESH::openGL_Render()
if( m_PerVertexNormalsNormalized.size() == 0 )
{
if( g_Parm_3D_Visu.IsRealisticMode() && g_Parm_3D_Visu.HightQualityMode() )
if( smoothShapes )
{
calcPerPointNormals();
}
......@@ -118,21 +125,21 @@ void S3D_MESH::openGL_Render()
for( unsigned int idx = 0; idx < m_CoordIndex.size(); idx++ )
{
if( m_MaterialIndex.size() > 1 )
{
{
if( m_Materials )
{
m_Materials->SetOpenGLMaterial( m_MaterialIndex[idx] );
m_Materials->SetOpenGLMaterial( m_MaterialIndex[idx], useMaterial );
}
}
}
switch( m_CoordIndex[idx].size() )
{
case 3: glBegin( GL_TRIANGLES );break;
case 4: glBegin( GL_QUADS ); break;
default: glBegin( GL_POLYGON ); break;
case 3: glBegin( GL_TRIANGLES );break;
case 4: glBegin( GL_QUADS ); break;
default: glBegin( GL_POLYGON ); break;
}
if( m_PerVertexNormalsNormalized.size() > 0 )
{
......@@ -144,7 +151,8 @@ void S3D_MESH::openGL_Render()
glm::vec3 point = m_Point[m_CoordIndex[idx][ii]];
glVertex3fv( &point.x );
}
} else if( g_Parm_3D_Visu.IsRealisticMode() && g_Parm_3D_Visu.HightQualityMode() )
}
else if( smoothShapes )
{
std::vector< glm::vec3 > normals_list;
normals_list = m_PerFaceVertexNormals[idx];
......@@ -157,7 +165,8 @@ void S3D_MESH::openGL_Render()
glm::vec3 point = m_Point[m_CoordIndex[idx][ii]];
glVertex3fv( &point.x );
}
} else
}
else
{
// Flat
glm::vec3 normal = m_PerFaceNormalsNormalized[idx];
......@@ -167,7 +176,7 @@ void S3D_MESH::openGL_Render()
glNormal3fv( &normal.x );
glm::vec3 point = m_Point[m_CoordIndex[idx][ii]];
glVertex3fv( &point.x );
glVertex3fv( &point.x );
}
}
......@@ -258,7 +267,7 @@ void S3D_MESH::calcPerFaceNormals ()
//DBG( printf("m_CoordIndex.size %u\n", m_CoordIndex.size()) );
//DBG( printf("m_PointNormalized.size %u\n", m_PointNormalized.size()) );
for( unsigned int idx = 0; idx < m_CoordIndex.size(); idx++ )
{
......@@ -307,7 +316,7 @@ void S3D_MESH::calcPerFaceNormals ()
if( haveAlreadyNormals_from_model_file == false )
{
// normalize vertex normal
// normalize vertex normal
float l = glm::length( cross_prod );
if( l > FLT_EPSILON ) // avoid division by zero
......@@ -331,7 +340,7 @@ void S3D_MESH::calcPerFaceNormals ()
m_PerFaceNormalsNormalized.push_back( cross_prod );
}
}
}
......@@ -355,13 +364,18 @@ void S3D_MESH::calcPerPointNormals ()
m_PerFaceVertexNormals.clear();
// Pre-allocate space for the entire vector of vertex normals so we can do parallel writes
m_PerFaceVertexNormals.resize( m_CoordIndex.size() );
// for each face A in mesh
#ifdef USE_OPENMP
#pragma omp parallel for
#endif /* USE_OPENMP */
for( unsigned int each_face_A_idx = 0; each_face_A_idx < m_CoordIndex.size(); each_face_A_idx++ )
{
// n = face A facet normal
std::vector< glm::vec3 > face_A_normals;
face_A_normals.clear();
face_A_normals.resize(m_CoordIndex[each_face_A_idx].size());
std::vector< glm::vec3 >& face_A_normals = m_PerFaceVertexNormals[each_face_A_idx];
face_A_normals.resize( m_CoordIndex[each_face_A_idx].size() );
// loop through all 3 vertices
// for each vert in face A
......@@ -393,16 +407,14 @@ void S3D_MESH::calcPerPointNormals ()
}
}
// normalize vertex normal
// normalize vertex normal
float l = glm::length( face_A_normals[each_vert_A_idx] );
if( l > FLT_EPSILON ) // avoid division by zero
{
face_A_normals[each_vert_A_idx] /= l;
}
}
m_PerFaceVertexNormals.push_back( face_A_normals );
}
}
}
......@@ -77,7 +77,7 @@ const wxString S3D_MASTER::GetShape3DFullFilename()
return shapeName;
wxString default_path;
wxGetEnv( wxT( KISYS3DMOD ), &default_path );
wxGetEnv( KISYS3DMOD, &default_path );
if( default_path.IsEmpty() )
return shapeName;
......@@ -119,7 +119,7 @@ int S3D_MASTER::ReadData()
if( parser )
{
parser->Load( filename );
parser->Load( filename, g_Parm_3D_Visu.m_BiuTo3Dunits * UNITS3D_TO_UNITSPCB );
delete parser;
return 0;
}
......
......@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014 Mario Luzeiro <mrluzeiro@gmail.com>
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.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.
*
......@@ -35,9 +35,10 @@
#include <base_struct.h>
#include <3d_material.h>
#include <gal/opengl/glm/glm.hpp>
/* 3D modeling units -> PCB units conversion scale:
* 1 "3D model unit" wings3d = 1 unit = 2.54 mm = 0.1 inch = 100 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)
......@@ -45,19 +46,42 @@
class S3D_MASTER;
class STRUCT_3D_SHAPE;
/* S3D_VERTEX manages a 3D coordinate (3 float numbers: x,y,z coordinates)*/
// 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;
}
};
/* Master structure for a 3D item description */
// Master structure for a 3D footprint shape description
class S3D_MASTER : public EDA_ITEM
{
public:
S3D_VERTEX m_MatScale;
S3D_VERTEX m_MatRotation;
S3D_VERTEX m_MatPosition;
STRUCT_3D_SHAPE* m_3D_Drawings;
S3D_MATERIAL* m_Materials;
S3DPOINT m_MatScale; ///< a scaling factor for the entire 3D footprint shape
S3DPOINT m_MatRotation; ///< a grotation for the entire 3D footprint shape
S3DPOINT m_MatPosition; ///< an offset for the entire 3D footprint shape
STRUCT_3D_SHAPE* m_3D_Drawings; ///< the list of basic shapes
S3D_MATERIAL* m_Materials; ///< the list of materiels used by the shapes
enum FILE3D_TYPE
{
......@@ -76,9 +100,9 @@ public:
bool m_use_modelfile_shininess;
private:
wxString m_Shape3DName; /* 3D shape name in 3D library */
wxString m_Shape3DName; // the 3D shape filename in 3D library
FILE3D_TYPE m_ShapeType;
double m_lastTransparency; // last transparency value from
double m_lastTransparency; // last transparency value from
// last material in use
bool m_loadTransparentObjects;
bool m_loadNonTransparentObjects;
......@@ -185,26 +209,26 @@ public:
/**
* Class VERTEX_VALUE_CTRL
* displays a vertex for editing. A vertex is a triplet of values
* 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 VERTEX_VALUE_CTRL
class S3DPOINT_VALUE_CTRL
{
private:
wxTextCtrl* m_XValueCtrl, * m_YValueCtrl, * m_ZValueCtrl;
public:
VERTEX_VALUE_CTRL( wxWindow* parent, wxBoxSizer* BoxSizer );
S3DPOINT_VALUE_CTRL( wxWindow* parent, wxBoxSizer* BoxSizer );
~VERTEX_VALUE_CTRL();
~S3DPOINT_VALUE_CTRL();
/**
* Function GetValue
* @return the vertex in internal units.
* @return the 3D point in internal units.
*/
S3D_VERTEX GetValue();
void SetValue( S3D_VERTEX vertex );
S3DPOINT GetValue();
void SetValue( S3DPOINT a3Dpoint );
void Enable( bool enbl );
void SetToolTip( const wxString& text );
};
......
......@@ -156,16 +156,46 @@ void EDA_3D_FRAME::CreateMenuBar()
_( "Realistic Mode" ),
KiBitmap( use_3D_copper_thickness_xpm ), wxITEM_CHECK );
AddMenuItem( prefsMenu, ID_MENU3D_MAX_QUALITY_FOR_REALISTIC_MODE,
_( "Max Quality in Realistic Mode" ),
_( "When using max quality, holes are removed from copper zones, "
"but the calculation time is longer" ),
KiBitmap( green_xpm ), wxITEM_CHECK );
wxMenu * renderOptionsMenu = new wxMenu;
AddMenuItem( prefsMenu, renderOptionsMenu, ID_MENU3D_COLOR,
_( "Render Options" ), KiBitmap( tools_xpm ) );
AddMenuItem( renderOptionsMenu, ID_MENU3D_FL_RENDER_SHADOWS,
_( "Render Shadows" ),
KiBitmap( green_xpm ), wxITEM_CHECK );
AddMenuItem( renderOptionsMenu, ID_MENU3D_FL_RENDER_SHOW_HOLES_IN_ZONES,
_( "Show Holes in Zones" ),
_( "Holes inside a copper layer copper zones are shown, "
"but the calculation time is longer" ),
KiBitmap( green_xpm ), wxITEM_CHECK );
AddMenuItem( renderOptionsMenu, ID_MENU3D_FL_RENDER_TEXTURES,
_( "Render Textures" ),
_( "Apply a grid/cloud textures to Board, Solder Mask and Silkscreen" ),
KiBitmap( green_xpm ), wxITEM_CHECK );
AddMenuItem( renderOptionsMenu, ID_MENU3D_FL_RENDER_SMOOTH,
_( "Render Smooth Normals" ),
KiBitmap( green_xpm ), wxITEM_CHECK );
AddMenuItem( renderOptionsMenu, ID_MENU3D_FL_RENDER_MATERIAL,
_( "Render Material Properties" ),
KiBitmap( green_xpm ), wxITEM_CHECK );
prefsMenu->AppendSeparator();
AddMenuItem( prefsMenu, ID_MENU3D_BGCOLOR_SELECTION,
_( "Choose Background Color" ), KiBitmap( palette_xpm ) );
wxMenu * backgrounColorMenu = new wxMenu;
// Add submenu Choose Colors
AddMenuItem( prefsMenu, backgrounColorMenu, ID_MENU3D_COLOR,
_( "Choose Colors" ), KiBitmap( palette_xpm ) );
AddMenuItem( backgrounColorMenu, ID_MENU3D_BGCOLOR_TOP_SELECTION,
_( "Background Top Color" ), KiBitmap( palette_xpm ) );
AddMenuItem( backgrounColorMenu, ID_MENU3D_BGCOLOR_SELECTION,
_( "Background Bottom Color" ), KiBitmap( palette_xpm ) );
AddMenuItem( prefsMenu, ID_MENU3D_AXIS_ONOFF,
_( "Show 3D &Axis" ), KiBitmap( axis3d_front_xpm ), wxITEM_CHECK );
......@@ -174,19 +204,19 @@ void EDA_3D_FRAME::CreateMenuBar()
wxMenu * gridlistMenu = new wxMenu;
AddMenuItem( prefsMenu, gridlistMenu, ID_MENU3D_GRID,
_( "3D Grid" ), KiBitmap( grid_xpm ) );
gridlistMenu->Append( ID_MENU3D_GRID_NOGRID, _( "No 3D Grid" ), wxEmptyString, true );
gridlistMenu->Append( ID_MENU3D_GRID_10_MM, _( "3D Grid 10 mm" ), wxEmptyString, true );
gridlistMenu->Append( ID_MENU3D_GRID_5_MM, _( "3D Grid 5 mm" ), wxEmptyString, true );
gridlistMenu->Append( ID_MENU3D_GRID_2P5_MM, _( "3D Grid 2.5 mm" ), wxEmptyString, true );
gridlistMenu->Append( ID_MENU3D_GRID_1_MM, _( "3D Grid 1 mm" ), wxEmptyString, true );
gridlistMenu->AppendCheckItem( ID_MENU3D_GRID_NOGRID, _( "No 3D Grid" ), wxEmptyString );
gridlistMenu->AppendCheckItem( ID_MENU3D_GRID_10_MM, _( "3D Grid 10 mm" ), wxEmptyString );
gridlistMenu->AppendCheckItem( ID_MENU3D_GRID_5_MM, _( "3D Grid 5 mm" ), wxEmptyString );
gridlistMenu->AppendCheckItem( ID_MENU3D_GRID_2P5_MM, _( "3D Grid 2.5 mm" ), wxEmptyString );
gridlistMenu->AppendCheckItem( ID_MENU3D_GRID_1_MM, _( "3D Grid 1 mm" ), wxEmptyString );
// If the grid is on, check the corresponding menuitem showing the grid size
if( g_Parm_3D_Visu.GetFlag( FL_GRID ) )
if( IsEnabled( FL_GRID ) )
{
gridlistMenu->Check( ID_MENU3D_GRID_10_MM, g_Parm_3D_Visu.m_3D_Grid == 10.0 );
gridlistMenu->Check( ID_MENU3D_GRID_5_MM, g_Parm_3D_Visu.m_3D_Grid == 5.0 );
gridlistMenu->Check( ID_MENU3D_GRID_2P5_MM, g_Parm_3D_Visu.m_3D_Grid == 2.5 );
gridlistMenu->Check( ID_MENU3D_GRID_1_MM, g_Parm_3D_Visu.m_3D_Grid == 1.0 );
gridlistMenu->Check( ID_MENU3D_GRID_10_MM, GetPrm3DVisu().m_3D_Grid == 10.0 );
gridlistMenu->Check( ID_MENU3D_GRID_5_MM, GetPrm3DVisu().m_3D_Grid == 5.0 );
gridlistMenu->Check( ID_MENU3D_GRID_2P5_MM, GetPrm3DVisu().m_3D_Grid == 2.5 );
gridlistMenu->Check( ID_MENU3D_GRID_1_MM, GetPrm3DVisu().m_3D_Grid == 1.0 );
}
else
gridlistMenu->Check( ID_MENU3D_GRID_NOGRID, true );
......@@ -194,10 +224,10 @@ void EDA_3D_FRAME::CreateMenuBar()
prefsMenu->AppendSeparator();
AddMenuItem( prefsMenu, ID_MENU3D_SHOW_BOARD_BODY,
_( "Show Board Body" ), KiBitmap( use_3D_copper_thickness_xpm ), wxITEM_CHECK );
_( "Show Board Bod&y" ), KiBitmap( use_3D_copper_thickness_xpm ), wxITEM_CHECK );
AddMenuItem( prefsMenu, ID_MENU3D_USE_COPPER_THICKNESS,
_( "Show Copper Thickness" ), KiBitmap( use_3D_copper_thickness_xpm ), wxITEM_CHECK );
_( "Show Copper &Thickness" ), KiBitmap( use_3D_copper_thickness_xpm ), wxITEM_CHECK );
AddMenuItem( prefsMenu, ID_MENU3D_MODULE_ONOFF,
_( "Show 3D F&ootprints" ), KiBitmap( shape_3d_xpm ), wxITEM_CHECK );
......@@ -207,22 +237,26 @@ void EDA_3D_FRAME::CreateMenuBar()
prefsMenu->AppendSeparator();
AddMenuItem( prefsMenu, ID_MENU3D_ADHESIVE_ONOFF,
wxMenu * layersMenu = new wxMenu;
AddMenuItem( prefsMenu, layersMenu, ID_MENU3D_LAYERS,
_( "Show &Layers" ), KiBitmap( tools_xpm ) );
AddMenuItem( layersMenu, ID_MENU3D_ADHESIVE_ONOFF,
_( "Show &Adhesive Layers" ), KiBitmap( tools_xpm ), wxITEM_CHECK );
AddMenuItem( prefsMenu, ID_MENU3D_SILKSCREEN_ONOFF,
AddMenuItem( layersMenu, ID_MENU3D_SILKSCREEN_ONOFF,
_( "Show &Silkscreen Layer" ), KiBitmap( add_text_xpm ), wxITEM_CHECK );
AddMenuItem( prefsMenu, ID_MENU3D_SOLDER_MASK_ONOFF,
AddMenuItem( layersMenu, ID_MENU3D_SOLDER_MASK_ONOFF,
_( "Show Solder &Mask Layers" ), KiBitmap( pads_mask_layers_xpm ), wxITEM_CHECK );
AddMenuItem( prefsMenu, ID_MENU3D_SOLDER_PASTE_ONOFF,
AddMenuItem( layersMenu, ID_MENU3D_SOLDER_PASTE_ONOFF,
_( "Show Solder &Paste Layers" ), KiBitmap( pads_mask_layers_xpm ), wxITEM_CHECK );
AddMenuItem( prefsMenu, ID_MENU3D_COMMENTS_ONOFF,
AddMenuItem( layersMenu, ID_MENU3D_COMMENTS_ONOFF,
_( "Show &Comments and Drawings Layer" ), KiBitmap( edit_sheet_xpm ), wxITEM_CHECK );
AddMenuItem( prefsMenu, ID_MENU3D_ECO_ONOFF,
AddMenuItem( layersMenu, ID_MENU3D_ECO_ONOFF,
_( "Show &Eco Layers" ), KiBitmap( edit_sheet_xpm ), wxITEM_CHECK );
SetMenuBar( menuBar );
......@@ -239,43 +273,58 @@ void EDA_3D_FRAME::SetMenuBarOptionsState()
wxMenuItem* item;
// Set the state of toggle menus according to the current display options
item = menuBar->FindItem( ID_MENU3D_REALISTIC_MODE );
item->Check( g_Parm_3D_Visu.IsRealisticMode() );
item->Check( GetPrm3DVisu().IsRealisticMode() );
item = menuBar->FindItem( ID_MENU3D_FL_RENDER_SHADOWS );
item->Check( GetPrm3DVisu().GetFlag( FL_RENDER_SHADOWS ) );
item = menuBar->FindItem( ID_MENU3D_FL_RENDER_SHADOWS );
item->Check( GetPrm3DVisu().GetFlag( FL_RENDER_SHADOWS ) );
item = menuBar->FindItem( ID_MENU3D_FL_RENDER_SHOW_HOLES_IN_ZONES );
item->Check( GetPrm3DVisu().GetFlag( FL_RENDER_SHOW_HOLES_IN_ZONES ) );
item = menuBar->FindItem( ID_MENU3D_FL_RENDER_TEXTURES );
item->Check( GetPrm3DVisu().GetFlag( FL_RENDER_TEXTURES ) );
item = menuBar->FindItem( ID_MENU3D_FL_RENDER_SMOOTH );
item->Check( GetPrm3DVisu().GetFlag( FL_RENDER_SMOOTH ) );
item = menuBar->FindItem( ID_MENU3D_MAX_QUALITY_FOR_REALISTIC_MODE );
item->Check( g_Parm_3D_Visu.HightQualityMode() );
item = menuBar->FindItem( ID_MENU3D_FL_RENDER_MATERIAL );
item->Check( GetPrm3DVisu().GetFlag( FL_RENDER_MATERIAL ) );
item = menuBar->FindItem( ID_MENU3D_SHOW_BOARD_BODY );
item->Check( g_Parm_3D_Visu.GetFlag( FL_SHOW_BOARD_BODY ) );
item->Check( GetPrm3DVisu().GetFlag( FL_SHOW_BOARD_BODY ) );
item = menuBar->FindItem( ID_MENU3D_USE_COPPER_THICKNESS );
item->Check( g_Parm_3D_Visu.GetFlag( FL_USE_COPPER_THICKNESS ) );
item->Check( GetPrm3DVisu().GetFlag( FL_USE_COPPER_THICKNESS ) );
item = menuBar->FindItem( ID_MENU3D_MODULE_ONOFF );
item->Check( g_Parm_3D_Visu.GetFlag( FL_MODULE ) );
item->Check( GetPrm3DVisu().GetFlag( FL_MODULE ) );
item = menuBar->FindItem( ID_MENU3D_ZONE_ONOFF );
item->Check( g_Parm_3D_Visu.GetFlag( FL_ZONE ) );
item->Check( GetPrm3DVisu().GetFlag( FL_ZONE ) );
item = menuBar->FindItem( ID_MENU3D_AXIS_ONOFF );
item->Check( g_Parm_3D_Visu.GetFlag( FL_AXIS ) );
item->Check( GetPrm3DVisu().GetFlag( FL_AXIS ) );
item = menuBar->FindItem( ID_MENU3D_ADHESIVE_ONOFF );
item->Check( g_Parm_3D_Visu.GetFlag( FL_ADHESIVE ) );
item->Check( GetPrm3DVisu().GetFlag( FL_ADHESIVE ) );
item = menuBar->FindItem( ID_MENU3D_SILKSCREEN_ONOFF );
item->Check( g_Parm_3D_Visu.GetFlag( FL_SILKSCREEN ) );
item->Check( GetPrm3DVisu().GetFlag( FL_SILKSCREEN ) );
item = menuBar->FindItem( ID_MENU3D_SOLDER_MASK_ONOFF );
item->Check( g_Parm_3D_Visu.GetFlag( FL_SOLDERMASK ) );
item->Check( GetPrm3DVisu().GetFlag( FL_SOLDERMASK ) );
item = menuBar->FindItem( ID_MENU3D_SOLDER_PASTE_ONOFF );
item->Check( g_Parm_3D_Visu.GetFlag( FL_SOLDERPASTE ) );
item->Check( GetPrm3DVisu().GetFlag( FL_SOLDERPASTE ) );
item = menuBar->FindItem( ID_MENU3D_COMMENTS_ONOFF );
item->Check( g_Parm_3D_Visu.GetFlag( FL_COMMENTS ) );
item->Check( GetPrm3DVisu().GetFlag( FL_COMMENTS ) );
item = menuBar->FindItem( ID_MENU3D_ECO_ONOFF );
item->Check( g_Parm_3D_Visu.GetFlag( FL_ECO ));
item->Check( GetPrm3DVisu().GetFlag( FL_ECO ));
}
void EDA_3D_FRAME::SetToolbars()
......
......@@ -38,14 +38,20 @@
#include <wx/glcanvas.h>
#include <3d_struct.h>
#include <info3d_visu.h>
#define KISYS3DMOD "KISYS3DMOD"
/// A variable name whose value holds the path of 3D shape files.
/// Currently an environment variable, eventually a project variable.
#define KISYS3DMOD wxT( "KISYS3DMOD" )
/// All 3D files are expected to be stored in LIB3D_FOLDER, or one of
/// its subdirectory.
#define LIB3D_FOLDER wxT( "packages3d" )
class EDA_3D_CANVAS;
class PCB_BASE_FRAME;
#define KICAD_DEFAULT_3D_DRAWFRAME_STYLE (wxDEFAULT_FRAME_STYLE | wxWANTS_CHARS)
#define LIB3D_PATH wxT( "packages3d" )
class EDA_3D_FRAME : public KIWAY_PLAYER
......@@ -97,9 +103,21 @@ public:
/// Toggles orthographic projection on and off
void ToggleOrtho(){ m_ortho = !m_ortho ; Refresh(true);};
/// Returns the orthographic projection flag
/// @return the orthographic projection flag
bool ModeIsOrtho() { return m_ortho ;};
/** @return the INFO3D_VISU which contains the current parameters
* to draw the 3D view og the board
*/
INFO3D_VISU& GetPrm3DVisu() const;
/**
* @return true if aItem must be displayed
* @param aItem = an item of DISPLAY3D_FLG enum
*/
bool IsEnabled( DISPLAY3D_FLG aItem ) const;
private:
// Event handlers:
void Exit3DFrame( wxCommandEvent& event );
......@@ -127,7 +145,10 @@ private:
double BestZoom();
void RedrawActiveWindow( wxDC* DC, bool EraseBg );
void Set3DBgColor();
// Get a S3D_COLOR from a wx colour dialog
// return true if a new color is chosen, false if
// no change or aborted by user
bool Get3DColorFromUser( S3D_COLOR &color );
DECLARE_EVENT_TABLE()
};
......
......@@ -8,13 +8,15 @@
* Please add IDs that are unique to the 3D viewer here and not in the global
* id.h file. This will prevent the entire project from being rebuilt when
* adding new commands to the 3D viewer.
* However the number of IDs should be < ROOM_FOR_3D_VIEWER, defined in id.h
* Please change the value of ROOM_FOR_3D_VIEWER if too small.
*/
#include <id.h> // Generic Id.
#include <id.h> // Generic Id.
enum id_3dview_frm
{
ID_START_COMMAND_3D = ID_END_LIST,
ID_START_COMMAND_3D = ID_KICAD_3D_VIEWER_START,
ID_ROTATE3D_X_NEG,
ID_ROTATE3D_X_POS,
ID_ROTATE3D_Y_NEG,
......@@ -28,11 +30,14 @@ enum id_3dview_frm
ID_MOVE3D_UP,
ID_MOVE3D_DOWN,
ID_ORTHO,
ID_MENU3D_COLOR,
ID_MENU3D_BGCOLOR_SELECTION,
ID_MENU3D_BGCOLOR_TOP_SELECTION,
ID_MENU3D_USE_COPPER_THICKNESS,
ID_MENU3D_AXIS_ONOFF,
ID_MENU3D_MODULE_ONOFF,
ID_MENU3D_ZONE_ONOFF,
ID_MENU3D_LAYERS,
ID_MENU3D_ADHESIVE_ONOFF,
ID_MENU3D_SILKSCREEN_ONOFF,
ID_MENU3D_SOLDER_PASTE_ONOFF,
......@@ -41,7 +46,11 @@ enum id_3dview_frm
ID_MENU3D_ECO_ONOFF,
ID_MENU3D_SHOW_BOARD_BODY,
ID_MENU3D_REALISTIC_MODE,
ID_MENU3D_MAX_QUALITY_FOR_REALISTIC_MODE,
ID_MENU3D_FL_RENDER_SHADOWS,
ID_MENU3D_FL_RENDER_SHOW_HOLES_IN_ZONES,
ID_MENU3D_FL_RENDER_TEXTURES,
ID_MENU3D_FL_RENDER_SMOOTH,
ID_MENU3D_FL_RENDER_MATERIAL,
ID_END_COMMAND_3D,
ID_TOOL_SET_VISIBLE_ITEMS,
......
......@@ -17,6 +17,7 @@ set(3D-VIEWER_SRCS
3d_class.cpp
3d_draw.cpp
3d_draw_basic_functions.cpp
3d_draw_helper_functions.cpp
3d_frame.cpp
3d_material.cpp
3d_mesh_model.cpp
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2014 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
......@@ -65,14 +65,42 @@ INFO3D_VISU::INFO3D_VISU()
m_copperThickness = 0;
m_epoxyThickness = 0;
m_nonCopperLayerThickness = 0;
m_BiuTo3Dunits = 1.0;
// Set copper color, in realistic mode
#define LUMINANCE 0.7/255.0
m_CopperColor.m_Red = 255.0*LUMINANCE;
m_CopperColor.m_Green = 223.0*LUMINANCE;
m_CopperColor.m_Blue = 0.0*LUMINANCE;
// Set the solder mask color, in realistic mode
#undef LUMINANCE
#define LUMINANCE 0.2/255.0
m_SolderMaskColor.m_Red = 100.0*LUMINANCE;
m_SolderMaskColor.m_Green = 255.0*LUMINANCE;
m_SolderMaskColor.m_Blue = 180.0*LUMINANCE;
// Set the silk screen mask color, in realistic mode
#undef LUMINANCE
#define LUMINANCE 0.9
m_SilkScreenColor.m_Red = 1.0*LUMINANCE;
m_SilkScreenColor.m_Green = 1.0*LUMINANCE;
m_SilkScreenColor.m_Blue = 1.0*LUMINANCE;
// Set the body board (FR4) color, in realistic mode
#undef LUMINANCE
#define LUMINANCE 0.2/255.0
m_BoardBodyColor.m_Red = 255.0*LUMINANCE;
m_BoardBodyColor.m_Green = 218.0*LUMINANCE;
m_BoardBodyColor.m_Blue = 110.0*LUMINANCE;
// default all special item layers Visible
for( ii = 0; ii < FL_LAST; ii++ )
m_drawFlags[ii] = true;
m_drawFlags.set();
SetFlag( FL_GRID, false );
SetFlag( FL_USE_COPPER_THICKNESS, false );
SetFlag( FL_USE_MAXQUALITY_IN_REALISTIC_MODE, false );
SetFlag( FL_RENDER_SHADOWS, false );
SetFlag( FL_RENDER_SHOW_HOLES_IN_ZONES, false );
}
......@@ -85,14 +113,17 @@ INFO3D_VISU::~INFO3D_VISU()
*/
void INFO3D_VISU::InitSettings( BOARD* aBoard )
{
// Calculates the board bounding box
// First, use only the board outlines
EDA_RECT bbbox = aBoard->ComputeBoundingBox( true );
// If no outlines, use the board with items
if( bbbox.GetWidth() == 0 && bbbox.GetHeight() == 0 )
{
bbbox.SetWidth( Millimeter2iu( 100 ) );
bbbox.SetHeight( Millimeter2iu( 100 ) );
}
bbbox = aBoard->ComputeBoundingBox( false );
// Gives a non null size to avoid issues in zoom / scale calculations
if( bbbox.GetWidth() == 0 && bbbox.GetHeight() == 0 )
bbbox.Inflate( Millimeter2iu( 10 ) );
m_BoardSettings = &aBoard->GetDesignSettings();
......@@ -199,9 +230,10 @@ 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 ); //B_Cu NOTE: in order to display modules in top of Paste and near the shadow
return m_layerZcoord[B_Paste] - ( m_copperThickness / 2 );
else
return m_layerZcoord[F_Paste] + ( m_copperThickness / 2 ); //F_Cu
return m_layerZcoord[F_Paste] + ( m_copperThickness / 2 );
}
......@@ -52,7 +52,9 @@
class BOARD_DESIGN_SETTINGS;
class S3D_COLOR /* 3D color (R, G, B) 3 floats range 0 to 1.0*/
/** Minor class to store a 3D color (R, G, B) 3 floats range 0 to 1.0
*/
class S3D_COLOR
{
public:
double m_Red, m_Green, m_Blue;
......@@ -62,7 +64,6 @@ public: S3D_COLOR()
}
};
/* information needed to display 3D board */
enum DISPLAY3D_FLG {
FL_AXIS=0, FL_MODULE, FL_ZONE,
FL_ADHESIVE, FL_SILKSCREEN, FL_SOLDERMASK, FL_SOLDERPASTE,
......@@ -71,10 +72,16 @@ enum DISPLAY3D_FLG {
FL_USE_COPPER_THICKNESS,
FL_SHOW_BOARD_BODY,
FL_USE_REALISTIC_MODE,
FL_USE_MAXQUALITY_IN_REALISTIC_MODE,
FL_RENDER_SHADOWS,
FL_RENDER_SHOW_HOLES_IN_ZONES,
FL_RENDER_TEXTURES,
FL_RENDER_SMOOTH,
FL_RENDER_MATERIAL,
FL_LAST
};
/** Helper class to handle information needed to display 3D board
*/
class INFO3D_VISU
{
public:
......@@ -84,6 +91,11 @@ public:
double m_Zoom; // 3D zoom value
double m_3D_Grid; // 3D grid value, in mm
S3D_COLOR m_BgColor;
S3D_COLOR m_BgColor_Top;
S3D_COLOR m_BoardBodyColor; // in realistic mode: FR4 board color
S3D_COLOR m_SolderMaskColor; // in realistic mode: solder mask color
S3D_COLOR m_SilkScreenColor; // in realistic mode: SilkScreen color
S3D_COLOR m_CopperColor; // in realistic mode: copper color
wxPoint m_BoardPos; // center board actual position in board units
wxSize m_BoardSize; // board actual size in board units
int m_CopperLayersCount; // Number of copper layers actually used by the board
......@@ -92,38 +104,34 @@ public:
double m_BiuTo3Dunits; // Normalization scale to convert board
// internal units to 3D units
// to scale 3D units between -1.0 and +1.0
double m_CurrentZpos; // temporary storage of current value of Z position,
// used in some calculation
// to normalize 3D units between -1.0 and +1.0
double zpos_offset;
private:
double m_layerZcoord[LAYER_ID_COUNT]; // Z position of each layer (normalized)
double m_copperThickness; // Copper thickness (normalized)
double m_epoxyThickness; // Epoxy thickness (normalized)
double m_nonCopperLayerThickness; // Non copper layers thickness
bool m_drawFlags[FL_LAST]; // Enable/disable flags (see DISPLAY3D_FLG list)
std::bitset<FL_LAST> m_drawFlags; // Enable/disable flags (see DISPLAY3D_FLG list)
public: INFO3D_VISU();
~INFO3D_VISU();
// Accessors
bool GetFlag( DISPLAY3D_FLG aFlag ) const { return m_drawFlags[aFlag]; }
bool SetFlag( DISPLAY3D_FLG aFlag, bool aState )
void SetFlag( DISPLAY3D_FLG aFlag, bool aState )
{
return m_drawFlags[aFlag] = aState;
m_drawFlags[aFlag] = aState;
}
/**
* Function InitSettings
* Initialize info 3D Parameters from aBoard
* Initialize 3D Parameters depending on aBoard
* @param aBoard: the board to display
*/
void InitSettings( BOARD* aBoard );
/**
* function GetModulesZcoord3DIU
* @return the Z position of 3D shapes, in 3D Units
* @param aIsFlipped: true for modules on Front (top) layer, false
* if on back (bottom) layer
......@@ -131,7 +139,6 @@ public: INFO3D_VISU();
double GetModulesZcoord3DIU( bool aIsFlipped );
/**
* function GetLayerZcoordBIU
* @return the Z coordinate of the layer aLayer, in Board Internal Units
* @param aLayerId: the layer number
*/
......@@ -141,7 +148,6 @@ public: INFO3D_VISU();
}
/**
* function GetCopperThicknessBIU
* @return the thickness (Z size) of the copper, in Board Internal Units
* note: the thickness (Z size) of the copper is not the thickness
* of the layer (the thickness of the layer is the epoxy thickness / layer count)
......@@ -200,7 +206,6 @@ public: INFO3D_VISU();
}
bool IsRealisticMode() { return GetFlag( FL_USE_REALISTIC_MODE ); }
bool HightQualityMode() { return GetFlag( FL_USE_MAXQUALITY_IN_REALISTIC_MODE ); }
};
extern INFO3D_VISU g_Parm_3D_Visu;
......
......@@ -66,12 +66,15 @@ public:
* @param aExtension is file extension of the file you are going to parse.
*/
static S3D_MODEL_PARSER* Create( S3D_MASTER* aMaster, const wxString aExtension );
/**
* Function Load
*
* pure virtual Function
* Concrete parsers should implement this function
* @param aFilename = the full file name of the file to load
* @param aVrmlunits_to_3Dunits = the scaling factor, i.e. the
* convertion from file unit to internal 3D units
*/
virtual void Load( const wxString aFilename ) = 0;
virtual void Load( const wxString& aFilename, double aVrmlunits_to_3Dunits ) = 0;
private:
S3D_MASTER* master;
......@@ -89,7 +92,8 @@ class X3D_MODEL_PARSER: public S3D_MODEL_PARSER
public:
X3D_MODEL_PARSER( S3D_MASTER* aMaster );
~X3D_MODEL_PARSER();
void Load( const wxString aFilename );
void Load( const wxString& aFilename, double aVrmlunits_to_3Dunits );
typedef std::map< wxString, wxString > PROPERTY_MAP;
typedef std::vector< wxXmlNode* > NODE_LIST;
......@@ -148,7 +152,8 @@ class VRML2_MODEL_PARSER: public S3D_MODEL_PARSER
public:
VRML2_MODEL_PARSER( S3D_MASTER* aMaster );
~VRML2_MODEL_PARSER();
void Load( const wxString aFilename );
void Load( const wxString& aFilename, double aVrmlunits_to_3Dunits );
/**
* Return string representing VRML2 file in vrml2 format
......@@ -191,7 +196,8 @@ class VRML1_MODEL_PARSER: public S3D_MODEL_PARSER
public:
VRML1_MODEL_PARSER( S3D_MASTER* aMaster );
~VRML1_MODEL_PARSER();
void Load( const wxString aFilename );
void Load( const wxString& aFilename, double aVrmlunits_to_3Dunits );
/**
* Return string representing VRML2 file in vrml2 format
......@@ -236,7 +242,8 @@ class VRML_MODEL_PARSER: public S3D_MODEL_PARSER
public:
VRML_MODEL_PARSER( S3D_MASTER* aMaster );
~VRML_MODEL_PARSER();
void Load( const wxString aFilename );
void Load( const wxString& aFilename, double aVrmlunits_to_3Dunits );
private:
VRML1_MODEL_PARSER *vrml1_parser;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -28,65 +28,63 @@
#include "vrml_aux.h"
char SkipGetChar ( FILE* File )
char SkipGetChar( FILE* File )
{
char c;
bool re_parse;
char c;
bool re_parse;
if( (c = fgetc( File )) == EOF )
if( ( c = fgetc( File ) ) == EOF )
{
//DBG( printf( "EOF\n" ) );
// DBG( printf( "EOF\n" ) );
return EOF;
}
//DBG( printf( "c %c 0x%02X\n", c, c ) );
// DBG( printf( "c %c 0x%02X\n", c, c ) );
do
{
re_parse = false;
if ((c == ' ') || (c == '\t') || (c == '{') || (c == '['))
if( (c == ' ') || (c == '\t') || (c == '{') || (c == '[') )
{
//DBG( printf( "Skipping space \\t or { or [\n" ) );
// DBG( printf( "Skipping space \\t or { or [\n" ) );
do
{
if( (c = fgetc( File )) == EOF )
if( ( c = fgetc( File ) ) == EOF )
{
//DBG( printf( "EOF\n" ) );
// DBG( printf( "EOF\n" ) );
return EOF;
}
}
while((c == ' ') || (c == '\t') || (c == '{') || (c == '['));
} while( (c == ' ') || (c == '\t') || (c == '{') || (c == '[') );
}
if ((c == '#') || (c == '\n') || (c == '\r') || (c == 0) || (c == ','))
if( (c == '#') || (c == '\n') || (c == '\r') || (c == 0) || (c == ',') )
{
if (c == '#')
if( c == '#' )
{
//DBG( printf( "Skipping # \\n or \\r or 0, 0x%02X\n", c ) );
// DBG( printf( "Skipping # \\n or \\r or 0, 0x%02X\n", c ) );
do
{
if( (c = fgetc( File )) == EOF )
if( ( c = fgetc( File ) ) == EOF )
{
//DBG( printf( "EOF\n" ) );
// DBG( printf( "EOF\n" ) );
return EOF;
}
}
while((c != '\n') && (c != '\r') && (c != 0) && (c != ','));
} while( (c != '\n') && (c != '\r') && (c != 0) && (c != ',') );
}
else
{
if( (c = fgetc( File )) == EOF )
if( ( c = fgetc( File ) ) == EOF )
{
//DBG( printf( "EOF\n" ) );
// DBG( printf( "EOF\n" ) );
return EOF;
}
}
re_parse = true;
}
}while(re_parse == true);
} while( re_parse == true );
return c;
}
......@@ -94,34 +92,38 @@ char SkipGetChar ( FILE* File )
char* GetNextTag( FILE* File, char* tag )
{
char c = SkipGetChar( File );
if (c == EOF)
if( c == EOF )
{
return NULL;
}
tag[0] = c;
tag[1] = 0;
//DBG( printf( "tag[0] %c\n", tag[0] ) );
tag[0] = c;
tag[1] = 0;
// DBG( printf( "tag[0] %c\n", tag[0] ) );
if( (c != '}') && (c != ']') )
{
char *dst = &tag[1];
while (fscanf( File, "%c", dst))
char* dst = &tag[1];
while( fscanf( File, "%c", dst ) )
{
if( (*dst == ' ') || (*dst == '[') || (*dst == '{') || (*dst == '\t') || (*dst == '\n')|| (*dst == '\r') )
if( (*dst == ' ') || (*dst == '[') || (*dst == '{')
|| (*dst == '\t') || (*dst == '\n')|| (*dst == '\r') )
{
*dst = 0;
break;
}
dst++;
}
//DBG( printf( "tag %s\n", tag ) );
// DBG( printf( "tag %s\n", tag ) );
c = SkipGetChar( File );
if (c != EOF)
if( c != EOF )
{
// Puts again the read char in the buffer
ungetc( c, File );
......@@ -132,40 +134,44 @@ char* GetNextTag( FILE* File, char* tag )
}
int read_NotImplemented( FILE* File, char closeChar)
int read_NotImplemented( FILE* File, char closeChar )
{
char c;
//DBG( printf( "look for %c\n", closeChar) );
while( (c = fgetc( File )) != EOF )
// DBG( printf( "look for %c\n", closeChar) );
while( ( c = fgetc( File ) ) != EOF )
{
if( c == '{' )
{
//DBG( printf( "{\n") );
// DBG( printf( "{\n") );
read_NotImplemented( File, '}' );
} else if( c == '[' )
}
else if( c == '[' )
{
//DBG( printf( "[\n") );
// DBG( printf( "[\n") );
read_NotImplemented( File, ']' );
} else if( c == closeChar )
}
else if( c == closeChar )
{
//DBG( printf( "%c\n", closeChar) );
// DBG( printf( "%c\n", closeChar) );
return 0;
}
}
DBG( printf( " NotImplemented failed\n" ) );
// DBG( printf( " NotImplemented failed\n" ) );
return -1;
}
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 );
}
......@@ -174,32 +180,34 @@ 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 );
float a, b, c;
int ret = fscanf( File, "%e %e %e", &a, &b, &c );
dst_vertex.x = a;
dst_vertex.y = b;
dst_vertex.z = c;
dst_vertex.x = a;
dst_vertex.y = b;
dst_vertex.z = c;
char s = SkipGetChar( File );
if (s != EOF)
if( s != EOF )
{
// Puts again the read char in the buffer
ungetc( s, File );
}
//DBG( printf( "ret%d(%.9f,%.9f,%.9f)", ret, a,b,c) );
// DBG( printf( "ret%d(%.9f,%.9f,%.9f)", ret, a,b,c) );
return ret;
}
int parseFloat( FILE* File, float *dst_float )
int parseFloat( FILE* File, float* dst_float )
{
float value;
int ret = fscanf( File, "%e", &value );
float value;
int ret = fscanf( File, "%e", &value );
*dst_float = value;
return ret;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -219,6 +219,8 @@ ExternalProject_Add( boost
COMMAND ${PATCH_STR_CMD} "${PROJECT_SOURCE_DIR}/patches/boost_macosx_older_openssl.patch" #https://svn.boost.org/trac/boost/ticket/9273
COMMAND ${PATCH_STR_CMD} "${PROJECT_SOURCE_DIR}/patches/boost_mingw.patch" #https://svn.boost.org/trac/boost/ticket/7262
COMMAND ${PATCH_STR_CMD} "${PROJECT_SOURCE_DIR}/patches/boost_mingw64_interlocked.patch"
# tell bzr about "added" files by last patch:
COMMAND bzr add libs/context/src/asm/make_i386_ms_pe_gas.S
COMMAND bzr add libs/context/src/asm/jump_i386_ms_pe_gas.S
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment