kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #08453
New 3d-viewer features
Hi,
the attached patch (against rev 3615) contains more additional features for
the kicad 3d-viewer.
The goal was to visualize a PCB good enough to verify drilling, copper,
solder mask and silk screen.
In addition to that, the virtual flag is interpreted to allow optional
rendering of assembly modules.
Most layer flags and colors (from pcbnew) are used in a useful way (according
to my opinion).
Changing a flag in pcbnew usually requires manual refresh.
The render flags Values & Reference are also evaluated.
Values activated results in the tags on top of a 3d shape.
References gets the Ref tags printed in rendering mode and silk screen
visible.
True zone rendering is only enabled in rendering mode with both mask layers
visible.
Burried vias are also rendered correctly (that was one of the features I
needed recently).Use rendered mode with PCB_Edges disabled.
PTH drills are rendered 2 mils bigger than the plated drill size.
Pblong and offset drills are also handled correctly.
Rendered mode changes all copper layers to sort of NiAu color.
An optional mm grid is also available.
The Preferences menu has three more entries:
Show Render Mode
Show Grid
Show Virtual Modules
The stuff is a heap of hacks I've done over the last 10 years or so to solve
some issues in a quick and dirty way.
The code is only tested on linux (64bit), but should also run on other
supported kicad platforms.
Good luck,
Thomas
PS:
be prepared, rendering takes time...
=== modified file '3d-viewer/3d_aux.cpp'
--- 3d-viewer/3d_aux.cpp 2012-04-27 14:15:11 +0000
+++ 3d-viewer/3d_aux.cpp 2012-06-15 14:42:26 +0000
@@ -192,6 +192,11 @@
// default all special item layers Visible
for (ii=0; ii< FL_LAST; ii++)
m_DrawFlags[ii]=true;
+ m_DrawFlags[g_Parm_3D_Visu.FL_ZONE]=false; // TSP_20120614
+ m_DrawFlags[g_Parm_3D_Visu.FL_AXIS]=false; // TSP_20120603
+ m_DrawFlags[g_Parm_3D_Visu.FL_RENDER]=false;
+ m_DrawFlags[g_Parm_3D_Visu.FL_GRID]=false;
+ m_DrawFlags[g_Parm_3D_Visu.FL_VIRT]=false;
}
=== modified file '3d-viewer/3d_draw.cpp'
--- 3d-viewer/3d_draw.cpp 2012-06-09 17:00:13 +0000
+++ 3d-viewer/3d_draw.cpp 2012-06-15 16:08:37 +0000
@@ -25,7 +25,7 @@
/**
* @file 3d_draw.cpp
-*/
+ */
#include <fctsys.h>
#include <common.h>
@@ -49,30 +49,113 @@
#include <3d_viewer.h>
#include <trackball.h>
+#include <collectors.h>
+#include <richio.h>
+
#if !wxUSE_GLCANVAS
#error Please set wxUSE_GLCANVAS to 1 in setup.h.
#endif
extern void CheckGLError();
-static void Draw3D_FilledCircle( double posx, double posy, double rayon,
- double hole_rayon, double zpos );
-static void Draw3D_FilledSegment( double startx, double starty,
+static void Draw3D_FilledCircle( double posx, double posy, double radius,
+ double holeradius, double zpos );
+static void Draw3D_FilledSegment( double startx, double starty,
+ double endx, double endy,
+ double width, double zpos );
+static void Draw3D_FilledSegmentMask( double startx,
+ double starty,
+ double endx,
+ double endy,
+ double width,
+ double zpos,
+ GLUtesselator* tess,
+ int orient );
+static void Draw3D_FilledSegmentMask( double startx,
+ double starty,
+ double endx,
+ double endy,
+ double width,
+ double zpos,
+ std::vector<CPolyPt>* e_data,
+ int orient );
+
+static void Draw3D_FilledCylinder( double posx, double posy, double radius,
+ double height, double zpos );
+static void Draw3D_FilledPolyWithHole( wxPoint* coord,
+ int n,
+ double x,
+ double y,
+ double offX,
+ double offY,
+ double holeX,
+ double holeY,
+ double zpos,
+ double oang );
+static void Draw3D_FilledSegmentWithHole( double startx,
+ double starty,
+ double endx,
+ double endy,
+ double width,
+ double holex,
+ double holey,
+ double holeradius,
+ double zpos,
+ double offX,
+ double offY,
+ double holeX,
+ double holeY,
+ double odx,
+ double ody,
+ double oang );
+static void Draw3D_ArcSegment( double startx, double starty, double centrex,
+ double centrey, double arc_angle, double width, double zpos );
+static void Draw3D_CircleSegment( double startx, double starty, double endx,
+ double endy, double width, double zpos );
+static int Get3DLayerEnable( int act_layer );
+static GLfloat Get3DLayerSide( int act_layer );
+static void Draw3D_FilledOblong( double startx, double starty,
double endx, double endy,
- double width, double zpos );
-static void Draw3D_FilledCylinder( double posx, double posy, double rayon,
- double height, double zpos );
-static void Draw3D_FilledSegmentWithHole( double startx, double starty,
- double endx, double endy,
- double width, double holex,
- double holey, double holeradius,
- double zpos );
-static void Draw3D_ArcSegment( double startx, double starty, double centrex,
- double centrey, double arc_angle, double width, double zpos );
-static void Draw3D_CircleSegment( double startx, double starty, double endx,
- double endy, double width, double zpos );
-static int Get3DLayerEnable( int act_layer );
-static GLfloat Get3DLayerSide( int act_layer );
+ double holex,
+ double holey, double holeradius,
+ double height, double zpos );
+static void Draw3D_FilledOblongMask( double startx, double starty,
+ double endx, double endy,
+ double holex,
+ double holey, double holeradius,
+ double height, double zpos );
+static void Draw3D_Mask( double startx, double starty, double endx,
+ double endy, double width, double zpos );
+static void Draw3D_ArcSegmentMask( double startx, double starty, double centrex,
+ double centrey, double arc_angle, double width,
+ double zpos );
+static void Draw3D_ArcSegmentMask( double startx, double starty, double centrex,
+ double centrey, double arc_angle, double width,
+ double zpos, std::vector<CPolyPt>* e_data );
+static void Draw3D_CircleSegmentMask( double startx, double starty, double endx,
+ double endy, double width, double zpos );
+static void Draw3D_CircleSegmentMask( double startx,
+ double starty,
+ double endx,
+ double endy,
+ double width,
+ double zpos,
+ std::vector<CPolyPt>* e_data );
+static void Draw3D_FilledSegmentWithHoleMask( double startx,
+ double starty,
+ double endx,
+ double endy,
+ double width,
+ double holex,
+ double holey,
+ double holeradius,
+ double zpos,
+ double offX,
+ double offY,
+ double oang );
+static void Draw3D_FilledCylinderMask( double posx, double posy, double radius,
+ double height, double zpos );
+void MySetGLColor( int color, int layer, double alpha );
#ifndef CALLBACK
@@ -80,16 +163,115 @@
#endif
// CALLBACK functions for GLU_TESS
-static void CALLBACK tessBeginCB( GLenum which );
-static void CALLBACK tessEndCB();
-static void CALLBACK tessErrorCB( GLenum errorCode );
-static void CALLBACK tessCPolyPt2Vertex( const GLvoid* data );
-static void CALLBACK tesswxPoint2Vertex( const GLvoid* data );
-
+static void CALLBACK tessErrorCB( GLenum errorCode );
+static void CALLBACK tessCPolyPt2Vertex( const GLvoid* data );
+static void CALLBACK tesswxPoint2Vertex( const GLvoid* data );
+
+static void CALLBACK mytessErrorCB( GLenum errorCode );
+static void CALLBACK mytessCPolyPt2Vertex( const GLvoid* data );
+static void CALLBACK mytessCombineCB( GLdouble coords[3],
+ void* vertex_data[4],
+ GLfloat weight[4],
+ void** outData );
+
+static void CALLBACK my2tessBeginCB( GLenum which );
+static void CALLBACK my2tessEndCB();
+static void CALLBACK my2tessErrorCB( GLenum errorCode );
+static void CALLBACK my2tessCPolyPt2Vertex( const GLvoid* data );
+static void CALLBACK my2tessCombineCB( GLdouble coords[3],
+ void* vertex_data[4],
+ GLfloat weight[4],
+ void** outData );
+
+static void CALLBACK my3tessBeginCB( GLenum which );
+static void CALLBACK my3tessEndCB();
+static void CALLBACK my3tessErrorCB( GLenum errorCode );
+static void CALLBACK my3tessCPolyPt2Vertex( const GLvoid* data );
+static void CALLBACK my3tessCombineCB( GLdouble coords[3],
+ void* vertex_data[4],
+ GLfloat weight[4],
+ void** outData );
+
+#define MAGIC_RESERVE 10000000
+#define MAGIC_CONT 0x80000000
+
+#ifdef USE_PCBNEW_NANOMETRES
+#warning "Tweak Edge export by 100 µ"
+#define DLIM 100000
+#warning "Copper extend by 50 µ"
+#define COPPER_EXTEND 50000
+#else
+#warning "Tweak Edge export by 10 mil"
+#define DLIM 100
+#warning "Copper extend by 2 mil"
+#define COPPER_EXTEND 20
+#endif // USE_PCBNEW_NANOMETRES
+
+/*
+ * circle & arc smoothness...
+ */
+#define C_SLICE 8
+
+#define _SEG2( x ) ( 1800.0 / (x) )
+#define _SEG( x ) ( 3600.0 / (x) )
+
+#define ATAN2( dx, dy ) atan2( ( dx ), ( dy ) ) * 1800.0 / M_PI
+
+std::vector<CPolyPt> e_data;
+std::vector<CPolyPt> p_data;
+std::vector<CPolyPt> edge_data;
+std::vector<CPolyPt> xe_data;
+std::vector<CPolyPt> se_data;
+std::vector<CPolyPt> miss_data;
+int tmonly = 0;
+int do_values = 0;
+int do_ref = 0;
+
+GLUtesselator* tess = gluNewTess();
+GLUtesselator* gtess;
+
+// define RAW_TIMING
+#ifdef RAW_TIMING
+double st0 = 0.0;
+double* t0p = NULL;
+char temps[1024];
+#include <sys/time.h>
+char* DTS( const char* s )
+{
+ struct timeval t;
+ double ot;
+
+ gettimeofday( &t, NULL );
+
+ if( s == NULL )
+ {
+ t0p = NULL;
+ st0 = t.tv_sec * 1.0 + t.tv_usec / 1000000.0;
+ temps[0] = 0;
+ }
+ else if( t0p == NULL )
+ {
+ t0p = &st0;
+ st0 = t.tv_sec * 1.0 + t.tv_usec / 1000000.0;
+ sprintf( temps, "%.2lf %s", st0, s );
+ }
+ else
+ {
+ ot = t.tv_sec * 1.0 + t.tv_usec / 1000000.0;
+ sprintf( temps, "%.2lf %s", ot - st0, s );
+ }
+
+ return temps;
+}
+
+
+#else
+#define DTS( s ) ""
+#endif // RAW_TIMING
void EDA_3D_CANVAS::Redraw( bool finish )
{
- // SwapBuffer requires the window to be shown before calling
+// SwapBuffer requires the window to be shown before calling
if( !IsShown() )
return;
@@ -99,12 +281,12 @@
SetCurrent();
#endif
- // Set the OpenGL viewport according to the client size of this canvas.
- // This is done here rather than in a wxSizeEvent handler because our
- // OpenGL rendering context (and thus viewport setting) is used with
- // multiple canvases: If we updated the viewport in the wxSizeEvent
- // handler, changing the size of one canvas causes a viewport setting that
- // is wrong when next another canvas is repainted.
+// Set the OpenGL viewport according to the client size of this canvas.
+// This is done here rather than in a wxSizeEvent handler because our
+// OpenGL rendering context (and thus viewport setting) is used with
+// multiple canvases: If we updated the viewport in the wxSizeEvent
+// handler, changing the size of one canvas causes a viewport setting that
+// is wrong when next another canvas is repainted.
const wxSize ClientSize = GetClientSize();
// *MUST* be called *after* SetCurrent( ):
@@ -136,34 +318,231 @@
}
glFlush();
- if( finish );
- glFinish();
+
+ if( finish )
+ ;
+
+ glFinish();
SwapBuffers();
}
+int orient( std::vector<CPolyPt> poly )
+{
+ double a = 0;
+
+ for( unsigned i = 0; i < poly.size() - 1; i++ )
+ {
+ a += (double) poly[i].x *
+ (double) poly[i + 1].y - (double) poly[i + 1].x * (double) poly[i].y;
+ }
+
+ a +=
+ (double) poly[poly.size() -
+ 1].x * (double) poly[0].y - (double) poly[0].x *
+ (double) poly[poly.size() - 1].y;
+ return (a >= 0) ? 1 : -1;
+}
+
+
+/**
+ * Function findPoint
+ * searches for a DRAWSEGMENT with an end point or start point of aPoint, and
+ * if found, removes it from the TYPE_COLLECTOR and returns it, else returns NULL.
+ * @param aPoint The starting or ending point to search for.
+ * @param items The list to remove from.
+ * @return DRAWSEGMENT* - The first DRAWSEGMENT that has a start or end point matching
+ * aPoint, otherwise NULL if none.
+ */
+static DRAWSEGMENT* findPoint( const wxPoint& aPoint, TYPE_COLLECTOR* items )
+{
+ int mind = 0x7fffffff;
+ int mindi = 0;
+ int d, xa, ya, xe, ye;
+
+ for( int i = 0; i<items->GetCount(); ++i )
+ {
+ DRAWSEGMENT* graphic = (DRAWSEGMENT*) (*items)[i];
+
+ wxASSERT( graphic->Type() == PCB_LINE_T );
+
+ switch( graphic->GetShape() )
+ {
+ case S_ARC:
+
+ if( aPoint == graphic->GetArcStart() || aPoint == graphic->GetArcEnd() )
+ {
+ items->Remove( i );
+ return graphic;
+ }
+
+ d = abs( aPoint.x - graphic->GetArcStart().x ) + abs(
+ aPoint.y - graphic->GetArcStart().y );
+
+ if( d < mind )
+ {
+ mind = d;
+ mindi = i;
+ xa = graphic->GetArcStart().x;
+ ya = graphic->GetArcStart().y;
+ xe = graphic->GetArcEnd().x;
+ ye = graphic->GetArcEnd().y;
+ }
+
+ d =
+ abs( aPoint.x -
+ graphic->GetArcEnd().x ) + abs( aPoint.y - graphic->GetArcEnd().y );
+
+ if( d < mind )
+ {
+ mind = d;
+ mindi = i;
+ xe = graphic->GetArcStart().x;
+ ye = graphic->GetArcStart().y;
+ xa = graphic->GetArcEnd().x;
+ ya = graphic->GetArcEnd().y;
+ }
+
+ break;
+
+ default:
+
+ if( aPoint == graphic->GetStart() || aPoint == graphic->GetEnd() )
+ {
+ items->Remove( i );
+ return graphic;
+ }
+
+ d = abs( aPoint.x - graphic->GetStart().x ) + abs( aPoint.y - graphic->GetStart().y );
+
+ if( d < mind )
+ {
+ mind = d;
+ mindi = i;
+ xa = graphic->GetStart().x;
+ ya = graphic->GetStart().y;
+ xe = graphic->GetEnd().x;
+ ye = graphic->GetEnd().y;
+ }
+
+ d = abs( aPoint.x - graphic->GetEnd().x ) + abs( aPoint.y - graphic->GetEnd().y );
+
+ if( d < mind )
+ {
+ mind = d;
+ mindi = i;
+ xe = graphic->GetStart().x;
+ ye = graphic->GetStart().y;
+ xa = graphic->GetEnd().x;
+ ya = graphic->GetEnd().y;
+ }
+ }
+ }
+
+ if( mind > DLIM )
+ return NULL;
+
+ for( int i = 0; i<items->GetCount(); ++i )
+ {
+ DRAWSEGMENT* graphic = (DRAWSEGMENT*) (*items)[i];
+
+ wxASSERT( graphic->Type() == PCB_LINE_T );
+
+ switch( graphic->GetShape() )
+ {
+ case S_ARC:
+ d = abs( aPoint.x - graphic->GetArcStart().x ) + abs(
+ aPoint.y - graphic->GetArcStart().y );
+
+ if( d == mind )
+ {
+ items->Remove( i );
+ return graphic;
+ }
+
+ d =
+ abs( aPoint.x -
+ graphic->GetArcEnd().x ) + abs( aPoint.y - graphic->GetArcEnd().y );
+
+ if( d == mind )
+ {
+ items->Remove( i );
+ return graphic;
+ }
+
+ break;
+
+ default:
+ d = abs( aPoint.x - graphic->GetStart().x ) + abs( aPoint.y - graphic->GetStart().y );
+
+ if( d == mind )
+ {
+ items->Remove( i );
+ return graphic;
+ }
+
+ d = abs( aPoint.x - graphic->GetEnd().x ) + abs( aPoint.y - graphic->GetEnd().y );
+
+ if( d == mind )
+ {
+ items->Remove( i );
+ return graphic;
+ }
+ }
+ }
+
+#if defined(DEBUG)
+ printf( "Unable to find segment matching point (%d,%d)\n",
+ aPoint.x, aPoint.y );
+
+ for( int i = 0; i<items->GetCount(); ++i )
+ {
+ DRAWSEGMENT* graphic = (DRAWSEGMENT*) (*items)[i];
+
+ printf( "type=%s, GetStart()=%d,%d GetEnd()=%d,%d\n",
+ TO_UTF8( BOARD_ITEM::ShowShape( (STROKE_T) graphic->GetShape() ) ),
+ graphic->GetStart().x,
+ graphic->GetStart().y,
+ graphic->GetEnd().x,
+ graphic->GetEnd().y );
+ }
+
+#endif
+
+ return NULL;
+}
+
+
GLuint EDA_3D_CANVAS::CreateDrawGL_List()
{
PCB_BASE_FRAME* pcbframe = Parent()->Parent();
- BOARD* pcb = pcbframe->GetBoard();
- TRACK* track;
- SEGZONE* segzone;
- int ii;
-
- wxBusyCursor dummy;
-
+ BOARD* pcb = pcbframe->GetBoard();
+ TRACK* track;
+ SEGZONE* segzone;
+ int ii;
+
+ wxBusyCursor dummy;
+ int bpii = 0;
+
+ do_values = pcb->IsElementVisible( MOD_VALUES_VISIBLE );
+ do_ref = pcb->IsElementVisible( MOD_REFERENCES_VISIBLE );
+ tmonly = 0;
+ e_data.reserve( MAGIC_RESERVE );
+ e_data.clear();
+ p_data.reserve( MAGIC_RESERVE );
+ p_data.clear();
m_gllist = glGenLists( 1 );
- EDA_RECT bbbox = pcbframe->GetBoardBoundingBox();
+ EDA_RECT bbbox = pcbframe->GetBoardBoundingBox();
g_Parm_3D_Visu.m_BoardSettings = &pcb->GetDesignSettings();
- g_Parm_3D_Visu.m_BoardSize = bbbox.GetSize();
- g_Parm_3D_Visu.m_BoardPos = bbbox.Centre();
+ g_Parm_3D_Visu.m_BoardSize = bbbox.GetSize();
+ g_Parm_3D_Visu.m_BoardPos = bbbox.Centre();
- g_Parm_3D_Visu.m_BoardPos.y = -g_Parm_3D_Visu.m_BoardPos.y;
- g_Parm_3D_Visu.m_Layers = pcb->GetCopperLayerCount();
+ g_Parm_3D_Visu.m_BoardPos.y = -g_Parm_3D_Visu.m_BoardPos.y;
+ g_Parm_3D_Visu.m_Layers = pcb->GetCopperLayerCount();
// Ensure the board has 2 sides for 3D views, because it is hard to find
// a *really* single side board in the true life...
@@ -184,32 +563,60 @@
for( ii = 0; ii < 32; ii++ )
{
if( ii < g_Parm_3D_Visu.m_Layers )
+ {
g_Parm_3D_Visu.m_LayerZcoord[ii] = g_Parm_3D_Visu.m_Epoxy_Width
* ii / (g_Parm_3D_Visu.m_Layers - 1);
- else
+ }
+ else if( ii < 16 )
+ {
g_Parm_3D_Visu.m_LayerZcoord[ii] = g_Parm_3D_Visu.m_Epoxy_Width;
+ }
+ else
+ {
+ if( ii <= SOLDERMASK_N_FRONT )
+ {
+ double offs = g_Parm_3D_Visu.m_Epoxy_Width * ( 4 - ( (ii >> 1) & 7 ) ) / 100.0;
+ g_Parm_3D_Visu.m_LayerZcoord[ii] =
+ (ii & 1) ? (g_Parm_3D_Visu.m_Epoxy_Width + offs) : -offs;
+ }
+ else
+ {
+ g_Parm_3D_Visu.m_LayerZcoord[ii] = g_Parm_3D_Visu.m_Epoxy_Width;
+ }
+ }
}
- GLfloat zpos_cu = 10 * g_Parm_3D_Visu.m_BoardScale;
- GLfloat zpos_cmp = g_Parm_3D_Visu.m_Epoxy_Width + zpos_cu;
- g_Parm_3D_Visu.m_LayerZcoord[ADHESIVE_N_BACK] = -zpos_cu * 2;
- g_Parm_3D_Visu.m_LayerZcoord[ADHESIVE_N_FRONT] = zpos_cmp + zpos_cu;
- g_Parm_3D_Visu.m_LayerZcoord[SILKSCREEN_N_BACK] = -zpos_cu;
- g_Parm_3D_Visu.m_LayerZcoord[SILKSCREEN_N_FRONT] = zpos_cmp;
- g_Parm_3D_Visu.m_LayerZcoord[DRAW_N] = zpos_cmp + zpos_cu;
- g_Parm_3D_Visu.m_LayerZcoord[COMMENT_N] = zpos_cmp + zpos_cu;
- g_Parm_3D_Visu.m_LayerZcoord[ECO1_N] = zpos_cmp + zpos_cu;
- g_Parm_3D_Visu.m_LayerZcoord[ECO2_N] = zpos_cmp + zpos_cu;
+ GLfloat zpos_cu = 0;
+ GLfloat zpos_cmp = g_Parm_3D_Visu.m_Epoxy_Width;
+ g_Parm_3D_Visu.m_LayerZcoord[ADHESIVE_N_BACK] = -4 * g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[ADHESIVE_N_FRONT] = zpos_cmp + 4 *
+ g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[SOLDERPASTE_N_BACK] = -3 * g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[SOLDERPASTE_N_FRONT] = zpos_cmp + 3 *
+ g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[SOLDERMASK_N_BACK] = -1 * g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[SOLDERMASK_N_FRONT] = zpos_cmp + 1 *
+ g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[SILKSCREEN_N_BACK] = -2 * g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[SILKSCREEN_N_FRONT] = zpos_cmp + 2 *
+ g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[DRAW_N] = zpos_cmp + 5 * g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[COMMENT_N] = zpos_cmp + 6 * g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[ECO1_N] = zpos_cmp + 7 * g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[ECO2_N] = zpos_cmp + 8 * g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[UNUSED_LAYER_29] = zpos_cmp + 9 * g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[UNUSED_LAYER_30] = zpos_cu - 11 * g_Parm_3D_Visu.m_BoardScale;
+ g_Parm_3D_Visu.m_LayerZcoord[UNUSED_LAYER_31] = zpos_cmp + 11 * g_Parm_3D_Visu.m_BoardScale;
glNewList( m_gllist, GL_COMPILE_AND_EXECUTE );
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
// draw axis
- if (g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_AXIS])
+ if( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_AXIS] )
{
glEnable( GL_COLOR_MATERIAL );
- SetGLColor( WHITE );
+ MySetGLColor( WHITE, -1, 1 );
glBegin( GL_LINES );
glNormal3f( 0.0f, 0.0f, 1.0f ); // Normal is Z axis
glVertex3f( 0.0f, 0.0f, 0.0f );
@@ -223,31 +630,693 @@
}
// Draw epoxy limits (do not use, works and test in progress)
- // TODO
// move the board in order to draw it with its center at 0,0 3D coordinates
glTranslatef( -g_Parm_3D_Visu.m_BoardPos.x * g_Parm_3D_Visu.m_BoardScale,
-g_Parm_3D_Visu.m_BoardPos.y * g_Parm_3D_Visu.m_BoardScale,
0.0F );
- glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
-
- // draw tracks and vias :
- for( track = pcb->m_Track; track != NULL; track = track->Next() )
+ glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
+
+ // draw tracks and vias (and text) :
+ MODULE* Module;
+
+ for( int llay = 0; llay < 16; llay++ )
{
- if( track->Type() == PCB_VIA_T )
- Draw3D_Via( (SEGVIA*) track );
- else
- Draw3D_Track( track );
+ if( !g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( llay ) )
+ continue;
+
+ tess = gluNewTess();
+ tmonly = 1;
+ GLUtesselator* jtess = gluNewTess();
+ g_Parm_3D_Visu.m_ActZpos = g_Parm_3D_Visu.m_LayerZcoord[llay];
+ GLdouble v_data[3];
+ int color = g_ColorsSettings.GetLayerColor( llay );
+ MySetGLColor( color, llay, 1 );
+ glNormal3f( 0.0, 0.0, (llay) ? 1.0 : -1.0 );
+ gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )glBegin );
+ gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )glEnd );
+ gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )mytessErrorCB );
+ gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )mytessCPolyPt2Vertex );
+ gluTessCallback( tess, GLU_TESS_COMBINE, ( void (CALLBACK*) () )mytessCombineCB );
+ gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
+
+ gluTessCallback( jtess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )my2tessBeginCB );
+ gluTessCallback( jtess, GLU_TESS_END, ( void (CALLBACK*) () )my2tessEndCB );
+ gluTessCallback( jtess, GLU_TESS_ERROR, ( void (CALLBACK*) () )my2tessErrorCB );
+ gluTessCallback( jtess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )my2tessCPolyPt2Vertex );
+ gluTessCallback( jtess, GLU_TESS_COMBINE, ( void (CALLBACK*) () )my2tessCombineCB );
+ gluTessProperty( jtess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE );
+ gluTessProperty( jtess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO );
+
+ gluTessBeginPolygon( jtess, NULL );
+
+ gluTessBeginPolygon( tess, NULL );
+
+ gluTessNormal( jtess, 0, 0, 1 );
+
+ // all tracks on layer....
+ for( track = pcb->m_Track; track != NULL; track = track->Next() )
+ {
+ if( ( track->GetLayer() == llay ) && ( track->Type() == PCB_TRACE_T) )
+ {
+ double w, ox, oy, fx, fy;
+ w = track->m_Width * g_Parm_3D_Visu.m_BoardScale;
+ ox = track->m_Start.x * g_Parm_3D_Visu.m_BoardScale;
+ oy = track->m_Start.y * g_Parm_3D_Visu.m_BoardScale;
+ fx = track->m_End.x * g_Parm_3D_Visu.m_BoardScale;
+ fy = track->m_End.y * g_Parm_3D_Visu.m_BoardScale;
+ Draw3D_FilledSegmentMask( ox, -oy, fx, -fy, w, g_Parm_3D_Visu.m_ActZpos, jtess,
+ 1 );
+ }
+ else if( track->Type() == PCB_VIA_T )
+ {
+ double x, y, r, hole;
+ int lpii, ii;
+ int top_layer;
+ int bottom_layer;
+ ( (SEGVIA*) track )->ReturnLayerPair( &top_layer, &bottom_layer );
+
+ if( ( llay >= bottom_layer) && ( llay <= top_layer ) )
+ {
+// fprintf(temps, "%s %d\n", DTS( "Via" ), llay);
+
+ r = track->m_Width * g_Parm_3D_Visu.m_BoardScale / 2;
+ hole = track->GetWidth();
+ hole *= g_Parm_3D_Visu.m_BoardScale / 2;
+ x = track->m_Start.x * g_Parm_3D_Visu.m_BoardScale;
+ y = track->m_Start.y * g_Parm_3D_Visu.m_BoardScale;
+
+ gluTessBeginContour( jtess );
+ lpii = p_data.size();
+ Draw3D_FilledSegmentWithHoleMask( x,
+ -y,
+ x,
+ -y,
+ hole * 2,
+ x,
+ -y,
+ hole,
+ g_Parm_3D_Visu.m_ActZpos,
+ 0,
+ 0, 0 );
+
+ for( ii = lpii; ii < (int) p_data.size(); ii++ )
+ {
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+ v_data[0] = (double) p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;;
+ v_data[1] = -(double) p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;;
+ gluTessVertex( jtess, v_data, &p_data[ii] );
+ }
+
+ gluTessEndContour( jtess );
+ }
+ }
+ }
+
+ if( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ZONE]
+ && g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER]
+ && g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( SOLDERMASK_N_FRONT )
+ && g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( SOLDERMASK_N_BACK )
+ && ( (llay == 0) || (llay == 15) ) )
+ {
+ for( segzone = pcb->m_Zone; segzone != NULL; segzone = segzone->Next() )
+ {
+ if( segzone->Type() == PCB_ZONE_T )
+ {
+ if( segzone->GetLayer() == llay )
+ {
+ double w, ox, oy, fx, fy;
+ w = segzone->m_Width * g_Parm_3D_Visu.m_BoardScale;
+ ox = segzone->m_Start.x * g_Parm_3D_Visu.m_BoardScale;
+ oy = segzone->m_Start.y * g_Parm_3D_Visu.m_BoardScale;
+ fx = segzone->m_End.x * g_Parm_3D_Visu.m_BoardScale;
+ fy = segzone->m_End.y * g_Parm_3D_Visu.m_BoardScale;
+ Draw3D_FilledSegmentMask( ox,
+ -oy,
+ fx,
+ -fy,
+ w,
+ g_Parm_3D_Visu.m_ActZpos,
+ jtess,
+ 1 );
+ }
+ }
+ }
+
+ // Draw new segments
+ for( ii = 0; ii < pcb->GetAreaCount(); ii++ )
+ {
+ ZONE_CONTAINER* curr_zone = pcb->GetArea( ii );
+
+ if( curr_zone->GetLayer() == llay )
+ {
+ if( curr_zone->m_FillMode == 0 )
+ {
+ // solid polygons only are used to fill areas
+ if( curr_zone->GetFilledPolysList().size() > 2 /*3*/ ) // TSP_20120608
+ {
+ // Draw solid areas contained in this zone
+ int StartContour = 1;
+
+ std::vector<CPolyPt> polysList = curr_zone->GetFilledPolysList();
+
+ for( unsigned ii = 0; ii < polysList.size(); ii++ )
+ {
+ if( StartContour == 1 )
+ {
+ gluTessBeginContour( jtess );
+ StartContour = 0;
+ }
+
+ p_data.push_back( CPolyPt( polysList[ii].x, polysList[ii].y ) );
+ v_data[0] =
+ p_data[p_data.size() - 1].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] =
+ -p_data[p_data.size() - 1].y * g_Parm_3D_Visu.m_BoardScale;
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+ gluTessVertex( jtess, v_data, &p_data[p_data.size() - 1] );
+
+ if( polysList[ii].end_contour == 1 )
+ {
+ gluTessEndContour( tess );
+ StartContour = 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ // segments are used to fill areas
+ for( unsigned iseg = 0; iseg < curr_zone->m_FillSegmList.size(); iseg++ )
+ {
+ double w, ox, oy, fx, fy;
+ w = curr_zone->m_ZoneMinThickness * g_Parm_3D_Visu.m_BoardScale;
+ ox = curr_zone->m_FillSegmList[iseg].m_Start.x *
+ g_Parm_3D_Visu.m_BoardScale;
+ oy = curr_zone->m_FillSegmList[iseg].m_Start.y *
+ g_Parm_3D_Visu.m_BoardScale;
+ fx = curr_zone->m_FillSegmList[iseg].m_End.x *
+ g_Parm_3D_Visu.m_BoardScale;
+ fy = curr_zone->m_FillSegmList[iseg].m_End.y *
+ g_Parm_3D_Visu.m_BoardScale;
+
+ Draw3D_FilledSegmentMask( ox,
+ -oy,
+ fx,
+ -fy,
+ w,
+ g_Parm_3D_Visu.m_ActZpos,
+ jtess,
+ 1 );
+ }
+ }
+ }
+ }
+
+ // Draw copper areas outlines
+ for( ii = 0; ii < pcb->GetAreaCount(); ii++ )
+ {
+ ZONE_CONTAINER* zone = pcb->GetArea( ii );
+
+ if( zone->GetLayer() == llay )
+ {
+ std::vector<CPolyPt> polysList = zone->GetFilledPolysList();
+
+ if( polysList.size() == 0 )
+ continue;
+
+ if( zone->m_ZoneMinThickness <= 1 )
+ continue;
+
+ int imax = polysList.size() - 1;
+ CPolyPt* firstcorner = &polysList[0];
+ CPolyPt* begincorner = firstcorner;
+ SEGZONE dummysegment( pcb );
+
+ for( int ic = 1; ic <= imax; ic++ )
+ {
+ CPolyPt* endcorner = &polysList[ic];
+
+ if( begincorner->utility == 0 )
+ {
+ // Draw only basic outlines, not extra segments
+ double w, ox, oy, fx, fy;
+ w = zone->m_ZoneMinThickness * g_Parm_3D_Visu.m_BoardScale;
+ ox = begincorner->x * g_Parm_3D_Visu.m_BoardScale;
+ oy = begincorner->y * g_Parm_3D_Visu.m_BoardScale;
+ fx = endcorner->x * g_Parm_3D_Visu.m_BoardScale;
+ fy = endcorner->y * g_Parm_3D_Visu.m_BoardScale;
+
+ Draw3D_FilledSegmentMask( ox,
+ -oy,
+ fx,
+ -fy,
+ w,
+ g_Parm_3D_Visu.m_ActZpos,
+ jtess,
+ 1 );
+ }
+
+ if( (endcorner->end_contour) || (ic == imax) )
+ {
+ // the last corner of a filled area is found: draw it
+ if( endcorner->utility == 0 )
+ {
+ // Draw only basic outlines, not extra segments
+ double w, ox, oy, fx, fy;
+ w = zone->m_ZoneMinThickness * g_Parm_3D_Visu.m_BoardScale;
+ ox = endcorner->x * g_Parm_3D_Visu.m_BoardScale;
+ oy = endcorner->y * g_Parm_3D_Visu.m_BoardScale;
+ fx = begincorner->x * g_Parm_3D_Visu.m_BoardScale;
+ fy = begincorner->y * g_Parm_3D_Visu.m_BoardScale;
+
+ Draw3D_FilledSegmentMask( ox,
+ -oy,
+ fx,
+ -fy,
+ w,
+ g_Parm_3D_Visu.m_ActZpos,
+ jtess,
+ 1 );
+ }
+
+ ic++;
+
+ if( ic < imax - 1 )
+ begincorner = firstcorner = &polysList[ic];
+ }
+ else
+ {
+ begincorner = endcorner;
+ }
+ }
+ }
+ }
+ }
+
+ // draw pads...
+ for( Module = pcb->m_Modules; Module != NULL; Module = Module->Next() )
+ {
+ D_PAD* pad;
+ int lpii;
+
+ for( pad = Module->m_Pads; pad != NULL; pad = pad->Next() )
+ {
+ int lm = pad->GetLayerMask();
+
+ if( lm & (1 << llay) )
+ {
+ lpii = p_data.size();
+ int ii, ll;
+ int ux0, uy0,
+ dx, dx0, dy, dy0,
+ delta_cx, delta_cy,
+ xc, yc;
+ int angle;
+ double scale;
+ double zpos = 0;
+ wxPoint shape_pos;
+ double w, hole, holeX, holeY;
+ double drillx, drilly;
+ double offX, offY;
+
+ scale = g_Parm_3D_Visu.m_BoardScale;
+ holeX = (double) pad->GetDrillSize().x * scale / 2;
+ holeY = (double) pad->GetDrillSize().y * scale / 2;
+ offX = (double) pad->GetOffset().x * scale;
+ offY = (double) pad->GetOffset().y * scale;
+ hole = fmin( holeX, holeY );
+
+ // Calculate the center of the pad.
+ shape_pos = pad->GetPosition();
+ ux0 = shape_pos.x;
+ uy0 = shape_pos.y;
+ xc = ux0;
+ yc = uy0;
+
+ dx = dx0 = pad->GetSize().x / 2;
+ dy = dy0 = pad->GetSize().y / 2;
+
+ angle = pad->GetOrientation();
+ drillx = pad->GetPosition().x * scale;
+ drilly = pad->GetPosition().y * scale;
+
+ switch( pad->GetShape() & 0x7F )
+ {
+ case PAD_CIRCLE:
+ case PAD_OVAL:
+
+ if( dx > dy ) // Horizontal ellipse
+ {
+ delta_cx = dx - dy;
+ delta_cy = 0;
+ w = pad->GetSize().y * scale;
+ }
+ else // Vertical ellipse
+ {
+ delta_cx = 0;
+ delta_cy = dy - dx;
+ w = pad->GetSize().x * scale;
+ }
+
+ RotatePoint( &delta_cx, &delta_cy, angle );
+
+ {
+ double ox, oy, fx, fy;
+ ox = (double) ( ux0 + delta_cx ) * scale;
+ oy = (double) ( uy0 + delta_cy ) * scale;
+ fx = (double) ( ux0 - delta_cx ) * scale;
+ fy = (double) ( uy0 - delta_cy ) * scale;
+
+ if( ( (1 << llay) & pad->GetLayerMask() ) != 0 )
+ {
+ Draw3D_FilledSegmentWithHoleMask( ox,
+ -oy,
+ fx,
+ -fy,
+ w,
+ drillx,
+ -drilly,
+ hole,
+ zpos,
+ offX,
+ offY, angle );
+ }
+ }
+ break;
+
+ case PAD_RECT:
+ case PAD_TRAPEZOID:
+ {
+ wxPoint coord[5];
+ wxRealPoint fcoord[8], f_hole_coord[8];
+
+ if( ( (1 << llay) & pad->GetLayerMask() ) != 0 )
+ {
+ wxSize lrp;
+ lrp.x = 0;
+ lrp.y = 0;
+ pad->BuildPadPolygon( coord, lrp, angle );
+
+ RotatePoint( &offX, &offY, angle );
+
+ for( ii = 0; ii < 4; ii++ )
+ {
+ coord[ii].x += ux0 + offX / scale; // TSP_20120604
+ coord[ii].y += uy0 + offY / scale;
+ ll = ii * 2;
+ fcoord[ll].x = coord[ii].x * scale;
+ fcoord[ll].y = coord[ii].y * scale;
+ }
+
+ for( ii = 0; ii < 7; ii += 2 )
+ {
+ ll = ll + 2;
+
+ if( ll > 7 )
+ ll -= 8;
+
+ fcoord[ii + 1].x = (fcoord[ii].x + fcoord[ll].x) / 2;
+ fcoord[ii + 1].y = (fcoord[ii].y + fcoord[ll].y) / 2;
+ }
+
+ for( ii = 0; ii < 8; ii++ )
+ {
+ f_hole_coord[ii].x = -hole * 0.707;
+ f_hole_coord[ii].y = hole * 0.707;
+ RotatePoint( &f_hole_coord[ii].x, &f_hole_coord[ii].y, angle -
+ (ii * 450) );
+ f_hole_coord[ii].x += drillx;
+ f_hole_coord[ii].y += drilly;
+ }
+
+ for( ii = 0; ii < 4; ii++ )
+ {
+ p_data.push_back( CPolyPt( (int) (coord[ii].x),
+ (int) (coord[ii].y) ) );
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if( (int) p_data.size() > lpii )
+ {
+ gluTessBeginContour( jtess );
+
+ for( ii = lpii; ii < (int) p_data.size(); ii++ )
+ {
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+ v_data[0] = p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( jtess, v_data, &p_data[ii] );
+ }
+
+ gluTessEndContour( jtess );
+ }
+ }
+ }
+
+ BOARD_ITEM* Struct;
+
+ for( Struct = Module->m_Drawings; Struct != NULL; Struct = Struct->Next() )
+ {
+ if( ( (DRAWSEGMENT*) Struct )->GetLayer() == llay )
+ {
+ {
+ double w = ( (DRAWSEGMENT*) Struct )->GetWidth() *
+ g_Parm_3D_Visu.m_BoardScale;
+
+ double x = ( (DRAWSEGMENT*) Struct )->GetStart().x *
+ g_Parm_3D_Visu.m_BoardScale;
+ double y = ( (DRAWSEGMENT*) Struct )->GetStart().y *
+ g_Parm_3D_Visu.m_BoardScale;
+
+ double xf = ( (DRAWSEGMENT*) Struct )->GetEnd().x *
+ g_Parm_3D_Visu.m_BoardScale;
+ double yf = ( (DRAWSEGMENT*) Struct )->GetEnd().y *
+ g_Parm_3D_Visu.m_BoardScale;
+ int ii, lpii = p_data.size();
+
+ switch( ( (DRAWSEGMENT*) Struct )->GetShape() )
+ {
+ case S_ARC:
+ {
+ Draw3D_ArcSegmentMask( x,
+ -y,
+ xf,
+ -yf,
+ ( (DRAWSEGMENT*) Struct )->GetAngle(),
+ w,
+ 0,
+ &p_data );
+ }
+
+ break;
+
+ case S_CIRCLE:
+ {
+ Draw3D_CircleSegmentMask( x, -y, xf, -yf, w, 0, &p_data );
+ }
+
+ break;
+
+ case S_POLYGON:
+ {
+ // We must compute true coordinates from m_PolyPoints
+ // which are relative to module position and module orientation = 0
+ EDGE_MODULE* edge =
+ (EDGE_MODULE*) ( (DRAWSEGMENT*) Struct );
+ std::vector<wxPoint> points = edge->GetPolyPoints();
+ MODULE* module = (MODULE*) edge->GetParent();
+
+ if( Module == NULL )
+ {
+ break;
+ }
+
+ for( int ii = points.size() - 1; ii >= 0; ii-- )
+ {
+ wxPoint& pt = points[ii];
+
+ RotatePoint( &pt.x, &pt.y, module->GetOrientation() );
+ pt += module->m_Pos;
+ p_data.push_back( CPolyPt( (int) pt.x, (int) pt.y ) );
+ }
+ }
+
+ default:
+ {
+ Draw3D_FilledSegmentMask( x, -y, xf, -yf, w, 0, &p_data, 1 );
+ }
+
+ break;
+ }
+
+ gluTessBeginContour( jtess );
+
+ for( ii = p_data.size() - 1; ii >= lpii; ii-- )
+ {
+ if( p_data[ii].x == (int) MAGIC_CONT )
+ {
+ gluTessEndContour( jtess );
+ gluTessBeginContour( jtess );
+ }
+ else
+ {
+ v_data[0] = p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( jtess, v_data, &p_data[ii] );
+ }
+ }
+
+ gluTessEndContour( jtess );
+ }
+ }
+ }
+ }
+
+ // render shape stuff...
+ EDA_ITEM* Struct;
+
+ for( Struct = pcb->m_Drawings; Struct != NULL; Struct = Struct->Next() )
+ {
+ if( ( (DRAWSEGMENT*) Struct )->GetLayer() == llay )
+ {
+ int ii, lpii = p_data.size();
+
+ switch( Struct->Type() )
+ {
+ case PCB_LINE_T:
+ Draw3D_DrawSegmentMask( (DRAWSEGMENT*) Struct,
+ ( (DRAWSEGMENT*) Struct )->GetLayer(), &p_data );
+ gluTessBeginContour( jtess );
+
+ for( ii = p_data.size() - 1; ii >= lpii; ii-- )
+ {
+ if( p_data[ii].x == (int) MAGIC_CONT )
+ {
+ gluTessEndContour( jtess );
+ gluTessBeginContour( jtess );
+ }
+ else
+ {
+ v_data[0] = p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( jtess, v_data, &p_data[ii] );
+ }
+ }
+
+ gluTessEndContour( jtess );
+ break;
+
+ case PCB_TEXT_T:
+ Draw3D_DrawTextMask( (TEXTE_PCB*) Struct,
+ ( (DRAWSEGMENT*) Struct )->GetLayer(), jtess );
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ gluTessEndPolygon( jtess );
+
+ gluTessNormal( tess, 0, 0, 1 );
+
+ // subtract via holes
+ for( track = pcb->m_Track; track != NULL; track = track->Next() )
+ {
+ if( track->Type() == PCB_VIA_T )
+ {
+ double x, y, r, hole;
+ double height = 0;
+ int lpii, ii;
+ int top_layer;
+ int bottom_layer;
+ ( (SEGVIA*) track )->ReturnLayerPair( &top_layer, &bottom_layer );
+
+ if( ( bottom_layer == 0 ) || ( top_layer == 15 ) )
+ {
+ r = track->m_Width * g_Parm_3D_Visu.m_BoardScale / 2;
+ hole = track->GetDrillValue();
+ hole *= g_Parm_3D_Visu.m_BoardScale / 2;
+ x = track->m_Start.x * g_Parm_3D_Visu.m_BoardScale;
+ y = track->m_Start.y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessBeginContour( tess );
+ lpii = p_data.size();
+ Draw3D_FilledCylinderMask( x, -y, hole, height, g_Parm_3D_Visu.m_ActZpos );
+
+ for( ii = lpii; ii < (int) p_data.size(); ii++ )
+ {
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+ v_data[0] = (double) p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;;
+ v_data[1] = -(double) p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;;
+ gluTessVertex( tess, v_data, &p_data[ii] );
+ }
+
+ gluTessEndContour( tess );
+ }
+ else
+ {
+ }
+ }
+ }
+
+ // subtract pad holes
+ tmonly = 2;
+ gluTessNormal( tess, 0, 0, 1 );
+
+ for( Module = pcb->m_Modules; Module != NULL; Module = Module->Next() )
+ {
+ D_PAD* pad;
+ int lpii;
+
+ for( pad = Module->m_Pads; pad != NULL; pad = pad->Next() )
+ {
+ lpii = p_data.size();
+ pad->Draw3D( this );
+
+ if( (int) p_data.size() > lpii )
+ {
+ gluTessBeginContour( tess );
+
+ for( ii = lpii; ii < (int) p_data.size(); ii++ )
+ {
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+ v_data[0] = p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &p_data[ii] );
+ }
+
+ gluTessEndContour( tess );
+ }
+ }
+ }
+
+ gluTessEndPolygon( tess );
+ gluDeleteTess( tess );
+ gluDeleteTess( jtess );
+ p_data.clear();
+ tmonly = 0;
}
- if (g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ZONE])
+ if( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ZONE]
+ && !g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] )
{
+ // primitive zone stuff
// Draw segments used to fill copper areas. outdated!
for( segzone = pcb->m_Zone; segzone != NULL; segzone = segzone->Next() )
{
if( segzone->Type() == PCB_ZONE_T )
+ {
Draw3D_Track( segzone );
+ }
}
// Draw new segments
@@ -258,7 +1327,7 @@
if( curr_zone->m_FillMode == 0 )
{
// solid polygons only are used to fill areas
- if( curr_zone->GetFilledPolysList().size() > 3 )
+ if( curr_zone->GetFilledPolysList().size() > 2 /*3*/ ) // TSP_20120608
{
Draw3D_SolidPolygonsInZones( curr_zone );
}
@@ -269,13 +1338,14 @@
for( unsigned iseg = 0; iseg < curr_zone->m_FillSegmList.size(); iseg++ )
{
SEGZONE dummysegment( pcb );
+
dummysegment.SetLayer( curr_zone->GetLayer() );
dummysegment.m_Width = curr_zone->m_ZoneMinThickness;
- dummysegment.m_Start.x = curr_zone->m_FillSegmList[iseg].m_Start.x;
- dummysegment.m_Start.y = curr_zone->m_FillSegmList[iseg].m_Start.y;
- dummysegment.m_End.x = curr_zone->m_FillSegmList[iseg].m_End.x;
- dummysegment.m_End.y = curr_zone->m_FillSegmList[iseg].m_End.y;
+ dummysegment.m_Start.x = curr_zone->m_FillSegmList[iseg].m_Start.x;
+ dummysegment.m_Start.y = curr_zone->m_FillSegmList[iseg].m_Start.y;
+ dummysegment.m_End.x = curr_zone->m_FillSegmList[iseg].m_End.x;
+ dummysegment.m_End.y = curr_zone->m_FillSegmList[iseg].m_End.y;
Draw3D_Track( &dummysegment );
}
}
@@ -284,9 +1354,9 @@
// Draw copper areas outlines
for( ii = 0; ii < pcb->GetAreaCount(); ii++ )
{
- ZONE_CONTAINER* zone = pcb->GetArea( ii );
+ ZONE_CONTAINER* zone = pcb->GetArea( ii );
- std::vector<CPolyPt> polysList = zone->GetFilledPolysList();
+ std::vector<CPolyPt> polysList = zone->GetFilledPolysList();
if( polysList.size() == 0 )
continue;
@@ -294,10 +1364,11 @@
if( zone->m_ZoneMinThickness <= 1 )
continue;
- int imax = polysList.size() - 1;
- CPolyPt* firstcorner = &polysList[0];
- CPolyPt* begincorner = firstcorner;
- SEGZONE dummysegment( pcb );
+ int imax = polysList.size() - 1;
+ CPolyPt* firstcorner = &polysList[0];
+ CPolyPt* begincorner = firstcorner;
+ SEGZONE dummysegment( pcb );
+
dummysegment.SetLayer( zone->GetLayer() );
dummysegment.m_Width = zone->m_ZoneMinThickness;
@@ -308,10 +1379,10 @@
if( begincorner->utility == 0 )
{
// Draw only basic outlines, not extra segments
- dummysegment.m_Start.x = begincorner->x;
- dummysegment.m_Start.y = begincorner->y;
- dummysegment.m_End.x = endcorner->x;
- dummysegment.m_End.y = endcorner->y;
+ dummysegment.m_Start.x = begincorner->x;
+ dummysegment.m_Start.y = begincorner->y;
+ dummysegment.m_End.x = endcorner->x;
+ dummysegment.m_End.y = endcorner->y;
Draw3D_Track( &dummysegment );
}
@@ -321,10 +1392,10 @@
if( endcorner->utility == 0 )
{
// Draw only basic outlines, not extra segments
- dummysegment.m_Start.x = endcorner->x;
- dummysegment.m_Start.y = endcorner->y;
- dummysegment.m_End.x = firstcorner->x;
- dummysegment.m_End.y = firstcorner->y;
+ dummysegment.m_Start.x = endcorner->x;
+ dummysegment.m_Start.y = endcorner->y;
+ dummysegment.m_End.x = firstcorner->x;
+ dummysegment.m_End.y = firstcorner->y;
Draw3D_Track( &dummysegment );
}
@@ -342,32 +1413,2062 @@
}
}
- // draw graphic items
- EDA_ITEM* PtStruct;
-
- for( PtStruct = pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() )
- {
- switch( PtStruct->Type() )
- {
- case PCB_LINE_T:
- Draw3D_DrawSegment( (DRAWSEGMENT*) PtStruct );
- break;
-
- case PCB_TEXT_T:
- Draw3D_DrawText( (TEXTE_PCB*) PtStruct );
- break;
-
- default:
- break;
- }
- }
-
- // draw footprints
- MODULE* Module = pcb->m_Modules;
-
- for( ; Module != NULL; Module = Module->Next() )
- {
- Module->Draw3D( this );
+ MySetGLColor( g_ColorsSettings.GetLayerColor( LAYER_N_FRONT ), LAYER_N_FRONT,
+ ( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] ) ? 1.0 : 0.5 );
+
+ for( track = pcb->m_Track; track != NULL; track = track->Next() )
+ {
+ // Vias just for the first layer....
+ if( track->Type() == PCB_VIA_T )
+ {
+ double x, y, r, hole;
+ double height = 0;
+ int top_layer;
+ int bottom_layer;
+ ( (SEGVIA*) track )->ReturnLayerPair( &top_layer, &bottom_layer );
+ height = g_Parm_3D_Visu.m_LayerZcoord[top_layer] -
+ g_Parm_3D_Visu.m_LayerZcoord[bottom_layer];
+ r = track->m_Width * g_Parm_3D_Visu.m_BoardScale / 2;
+ hole = track->GetDrillValue();
+ hole *= g_Parm_3D_Visu.m_BoardScale / 2;
+ x = track->m_Start.x * g_Parm_3D_Visu.m_BoardScale;
+ y = track->m_Start.y * g_Parm_3D_Visu.m_BoardScale;
+
+ Draw3D_FilledCylinder( x, -y, hole, height,
+ g_Parm_3D_Visu.m_LayerZcoord[bottom_layer] );
+ }
+ }
+
+ if( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] )
+ {
+ // draw graphic items
+ EDA_ITEM* PtStruct;
+
+ for( PtStruct = pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() )
+ {
+ if( ( ( (BOARD_ITEM*) PtStruct )->GetLayer() == SILKSCREEN_N_FRONT )
+ || ( ( (BOARD_ITEM*) PtStruct )->GetLayer() == SILKSCREEN_N_BACK ) )
+ continue; // TSP_20120606
+
+ if( ( ( (BOARD_ITEM*) PtStruct )->GetLayer() == SOLDERMASK_N_BACK )
+ || ( ( (BOARD_ITEM*) PtStruct )->GetLayer() == SOLDERMASK_N_FRONT ) )
+ continue; // TSP_20120606
+
+ if( ( (BOARD_ITEM*) PtStruct )->GetLayer() == EDGE_N )
+ {
+ switch( PtStruct->Type() )
+ {
+ case PCB_LINE_T:
+ Draw3D_DrawSegment( (DRAWSEGMENT*) PtStruct );
+ break;
+
+ case PCB_TEXT_T:
+ Draw3D_DrawText( (TEXTE_PCB*) PtStruct );
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // draw graphic items
+ EDA_ITEM* PtStruct;
+
+ for( PtStruct = pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() )
+ {
+ if( ( ( (BOARD_ITEM*) PtStruct )->GetLayer() <= LAST_COPPER_LAYER ) )
+ continue; // TSP_20120606
+
+ {
+ switch( PtStruct->Type() )
+ {
+ case PCB_LINE_T:
+ Draw3D_DrawSegment( (DRAWSEGMENT*) PtStruct );
+ break;
+
+ case PCB_TEXT_T:
+ Draw3D_DrawText( (TEXTE_PCB*) PtStruct );
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ std::vector<vector<CPolyPt> > paths;
+ std::vector<vector<CPolyPt> > vpaths;
+ std::vector<vector<CPolyPt> > dpaths;
+ {
+ edge_data.reserve( MAGIC_RESERVE / 10 );
+ edge_data.clear();
+ xe_data.reserve( MAGIC_RESERVE / 10 );
+ xe_data.clear();
+ se_data.reserve( MAGIC_RESERVE / 10 );
+ se_data.clear();
+ {
+ TYPE_COLLECTOR items;
+ static const KICAD_T scanDRAWSEGMENTS[] = { PCB_LINE_T, EOT };
+
+ items.Collect( pcb, scanDRAWSEGMENTS );
+
+ bool haveEdges = false;
+
+ for( int i = 0; i<items.GetCount(); )
+ {
+ DRAWSEGMENT* item = (DRAWSEGMENT*) items[i];
+
+ wxASSERT( item->Type() == PCB_LINE_T );
+
+ if( item->GetLayer() != EDGE_N )
+ {
+ items.Remove( i );
+ }
+ else
+ {
+ haveEdges = true;
+ ++i;
+ D( item->Show( 0, std::cout ); )
+ }
+ }
+
+ if( haveEdges )
+ {
+ std::vector<CPolyPt> path;
+
+ wxPoint prevPt;
+
+ DRAWSEGMENT* graphic;
+
+ // get outer polygon (xmin defines it, assume only "valid" edges
+ // find edge point wit minimal x
+ // emit this polygon...
+ wxPoint xmin = wxPoint( 0x7fffffff, 0 );
+ int xmini = 0;
+
+ for( int i = 0; i < items.GetCount(); i++ )
+ {
+ graphic = (DRAWSEGMENT*) items[i];
+
+ switch( graphic->GetShape() )
+ {
+ case S_SEGMENT:
+ {
+ if( graphic->GetStart().x < xmin.x )
+ {
+ xmin = graphic->GetStart();
+ xmini = i;
+ }
+
+ if( graphic->GetEnd().x < xmin.x )
+ {
+ xmin = graphic->GetEnd();
+ xmini = i;
+ }
+ }
+ break;
+
+ case S_ARC:
+ // freerouter does not yet understand arcs, so approximate
+ // an arc with a series of short lines and put those
+ // line segments into the !same! PATH.
+ {
+ const int STEPS = 9; // in an arc of 90 degrees
+
+ wxPoint start = graphic->GetArcStart();
+ wxPoint end = graphic->GetArcEnd();
+ wxPoint center = graphic->GetCenter();
+ double angle = -graphic->GetAngle();
+
+ wxPoint aPt;
+
+ for( int step = 1; step<=STEPS; ++step )
+ {
+ double rotation = ( angle * step ) / STEPS;
+
+ aPt = start;
+
+ RotatePoint( &aPt.x, &aPt.y, center.x, center.y, rotation );
+
+ if( aPt.x < xmin.x )
+ {
+ xmin = aPt;
+ xmini = i;
+ }
+ }
+ }
+ break;
+
+ case S_CIRCLE:
+ // do not output a circle, freerouter does not understand it.
+ // this might be a mounting hole or something, ignore it without error
+ // because some of our demo boards have used the edges pcb layer to
+ // hold islanded circles, rather than simply using holes.
+ break;
+
+ default:
+ {
+ wxString error;
+
+ error.Printf( _( "Unsupported DRAWSEGMENT type %s" ),
+ GetChars( BOARD_ITEM::ShowShape(
+ (STROKE_T) graphic->GetShape() ) ) );
+
+ THROW_IO_ERROR( error );
+ }
+ break;
+ }
+ }
+
+ // collect all enclosed sub polygons
+#define TWEAKER( a, b ) ( ( abs( a.x - b.x ) + abs( a.y - b.y ) ) < DLIM )
+ // the first DRAWSEGMENT is in 'graphic*', ok to remove it from 'items'
+ graphic = (DRAWSEGMENT*) items[xmini];
+ items.Remove( xmini );
+ #define mapPt( x ) x
+ wxPoint startPt = wxPoint( graphic->GetEnd() );
+ prevPt = graphic->GetEnd();
+ path.clear();
+ path.push_back( mapPt( prevPt ) );
+
+ // do not append the other end point yet, this first 'graphic' might be an arc
+ for( ; ; )
+ {
+ switch( graphic->GetShape() )
+ {
+ case S_SEGMENT:
+ {
+ wxPoint nextPt;
+
+ if( !TWEAKER( prevPt, graphic->GetStart() ) )
+ {
+ wxASSERT( TWEAKER( prevPt, graphic->GetEnd() ) );
+ nextPt = graphic->GetStart();
+ }
+ else
+ {
+ wxASSERT( TWEAKER( prevPt, graphic->GetStart() ) );
+ nextPt = graphic->GetEnd();
+ }
+
+ path.push_back( mapPt( nextPt ) );
+ prevPt = nextPt;
+ }
+ break;
+
+ case S_ARC:
+ // freerouter does not yet understand arcs, so approximate
+ // an arc with a series of short lines and put those
+ // line segments into the !same! PATH.
+ {
+ const int STEPS = 9; // in an arc of 90 degrees
+
+ wxPoint start = graphic->GetArcStart();
+ wxPoint end = graphic->GetArcEnd();
+ wxPoint center = graphic->GetCenter();
+ double angle = -graphic->GetAngle();
+
+ if( !TWEAKER( prevPt, start ) )
+ {
+ wxASSERT( TWEAKER( prevPt, graphic->GetArcEnd() ) );
+
+ angle = -angle;
+ EXCHG( start, end );
+ }
+
+ wxPoint nextPt;
+
+ for( int step = 1; step<=STEPS; ++step )
+ {
+ double rotation = ( angle * step ) / STEPS;
+
+ nextPt = start;
+
+ RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y, rotation );
+
+ path.push_back( mapPt( nextPt ) );
+ }
+
+ prevPt = nextPt;
+ }
+ break;
+
+ case S_CIRCLE:
+ // Do not output a circle, freerouter does not understand it.
+ // tell user his board has a problem, this is better than silently
+ // ignoring the error. "edges pcb" layer should not be used
+ // to hold islanded circles which could or should be better done
+ // as simple holes. (Some of our demo boards have this problem.)
+ // fall thru here to report the error.
+
+ default:
+ {
+ wxString error;
+
+ error.Printf( _( "Unsupported DRAWSEGMENT type %s" ),
+ GetChars( BOARD_ITEM::ShowShape(
+ (STROKE_T) graphic->GetShape() ) ) );
+
+ THROW_IO_ERROR( error );
+ }
+ break;
+ }
+
+ if( TWEAKER( startPt, prevPt ) )
+ break;
+
+ graphic = findPoint( prevPt, &items );
+
+ if( !graphic )
+ {
+ wxString error;
+
+ error << _( "Unable to find the next segment with an endpoint of " );
+ error << prevPt.x;
+ error << wxChar( ',' );
+ error << prevPt.y;
+ error << wxChar( '\n' );
+ error << _( "Edit Edges_Pcb segments, making them contiguous." );
+ THROW_IO_ERROR( error );
+ }
+ }
+
+ paths.push_back( path );
+
+ while( items.GetCount() )
+ {
+ // emit a signal layers keepout for every sub-polygon left...
+ graphic = (DRAWSEGMENT*) items[0];
+ items.Remove( 0 );
+
+ wxPoint startPt = wxPoint( graphic->GetEnd() );
+ prevPt = graphic->GetEnd();
+ path.clear();
+ path.push_back( mapPt( prevPt ) );
+
+ // do not append the other end point yet, this first 'graphic' might be an arc
+ for( ; ; )
+ {
+ switch( graphic->GetShape() )
+ {
+ case S_SEGMENT:
+ {
+ wxPoint nextPt;
+
+ if( !TWEAKER( prevPt, graphic->GetStart() ) )
+ {
+ wxASSERT( TWEAKER( prevPt, graphic->GetEnd() ) );
+ nextPt = graphic->GetStart();
+ }
+ else
+ {
+ wxASSERT( TWEAKER( prevPt, graphic->GetStart() ) );
+ nextPt = graphic->GetEnd();
+ }
+
+ prevPt = nextPt;
+ path.push_back( mapPt( prevPt ) );
+ }
+ break;
+
+ case S_ARC:
+ // freerouter does not yet understand arcs, so approximate
+ // an arc with a series of short lines and put those
+ // line segments into the !same! PATH.
+ {
+ const int STEPS = 9; // in an arc of 90 degrees
+
+ wxPoint start = graphic->GetArcStart();
+ wxPoint end = graphic->GetArcEnd();
+ wxPoint center = graphic->GetCenter();
+ double angle = -graphic->GetAngle();
+
+ if( !TWEAKER( prevPt, start ) )
+ {
+ wxASSERT( TWEAKER( prevPt, graphic->GetArcEnd() ) );
+
+ angle = -angle;
+ EXCHG( start, end );
+ }
+
+ wxPoint nextPt;
+
+ for( int step = 1; step<=STEPS; ++step )
+ {
+ double rotation = ( angle * step ) / STEPS;
+
+ nextPt = start;
+
+ RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y,
+ rotation );
+
+ path.push_back( mapPt( nextPt ) );
+ }
+
+ prevPt = nextPt;
+ }
+ break;
+
+ case S_CIRCLE:
+ // do a circle segmentation
+ {
+ const int STEPS = 9 * 4; // in an arc of 90 degrees
+
+ wxPoint start;
+ wxPoint center = graphic->GetCenter();
+ int iradius = graphic->GetRadius();
+ double angle = 3600.0;
+
+ start = center;
+ start.x += iradius;
+
+ wxPoint nextPt;
+
+ for( int step = 1; step<=STEPS; ++step )
+ {
+ double rotation = ( angle * step ) / STEPS;
+
+ nextPt = start;
+
+ RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y,
+ rotation );
+
+ path.push_back( mapPt( nextPt ) );
+ }
+
+ prevPt = startPt;
+ }
+ break;
+
+ default:
+ {
+ wxString error;
+
+ error.Printf( _( "Unsupported DRAWSEGMENT type %s" ),
+ GetChars( BOARD_ITEM::ShowShape(
+ (STROKE_T) graphic->GetShape() ) ) );
+
+ THROW_IO_ERROR( error );
+ }
+ break;
+ }
+
+ if( TWEAKER( startPt, prevPt ) )
+ break;
+
+ graphic = findPoint( prevPt, &items );
+
+ if( !graphic )
+ {
+ wxString error;
+
+ error << _( "Unable to find the next segment with an endpoint of " );
+ error << prevPt.x;
+ error << wxChar( ',' );
+ error << prevPt.y;
+ error << wxChar( '\n' );
+ error << _( "Edit Edges_Pcb segments, making them contiguous." );
+ THROW_IO_ERROR( error );
+ }
+ }
+
+ paths.push_back( path );
+ }
+
+ for( unsigned int i = 0; i < paths.size(); i++ )
+ {
+ int ori = orient( paths[i] );
+
+ if( ori >= 0 )
+ {
+ for( int j = 0; j < (int) paths[i].size(); j++ )
+ {
+ edge_data.push_back( paths[i][j] );
+ }
+
+ edge_data.push_back( CPolyPt( (int) MAGIC_CONT, 0, true, 0 ) );
+ }
+ else
+ {
+ std::vector<CPolyPt> hpath;
+
+ for( int j = (int) paths[i].size() - 1; j >= 0; j-- )
+ {
+ hpath.push_back( paths[i][j] );
+ edge_data.push_back( paths[i][j] );
+ }
+
+ edge_data.push_back( CPolyPt( (int) MAGIC_CONT, 0, true, 0 ) );
+ paths[i] = hpath;
+ }
+ }
+
+ // now paths holds splitted edge (+)polygons, paths[0] is outer edge...
+ TYPE_COLLECTOR drill_items;
+ wxSize noDrill = wxSize( 0, 0 );
+ bool haveDrills = false;
+ static const KICAD_T scanDRILLSEGMENTS[] = { PCB_PAD_T, EOT };
+
+ drill_items.Collect( pcb, scanDRILLSEGMENTS );
+
+ for( int i = 0; i<drill_items.GetCount(); )
+ {
+ wxSize sz = ( (D_PAD*) drill_items[i] )->GetDrillSize();
+
+ if( (sz.x + sz.y) <= 0 )
+ {
+ drill_items.Remove( i );
+ }
+ else
+ {
+ haveDrills = true;
+ ++i;
+ D( drill_item->Show( 0, std::cout ); )
+ }
+ }
+
+ for( int i = 0; i < drill_items.GetCount(); i++ )
+ {
+ D_PAD* pad = ( (D_PAD*) drill_items[i] );
+ wxSize sz = ( (D_PAD*) drill_items[i] )->GetDrillSize();
+ wxPoint pos = ( (D_PAD*) drill_items[i] )->GetPosition();
+ double ang = ( (D_PAD*) drill_items[i] )->GetOrientation();
+ MODULE* parent = ( (D_PAD*) drill_items[i] )->GetParent();
+ double pang = -1;
+ double tang;
+ int iradius;
+ int xoff;
+ std::vector<CPolyPt> lpath;
+
+ // if PTH --> increase size by 100 µ
+ if( pad->GetAttribute() == PAD_STANDARD )
+ {
+ // XXX
+ sz.x += 2 * COPPER_EXTEND;
+ sz.y += 2 * COPPER_EXTEND;
+ }
+
+ if( parent != NULL )
+ {
+ pang = parent->GetOrientation();
+ }
+
+ tang = ang;
+
+ if( sz.x < sz.y )
+ {
+ // more y --> flip and add 90 deg
+ tang += 900;
+ iradius = sz.x / 2;
+ xoff = (sz.y - sz.x) / 2;
+ }
+ else
+ {
+ iradius = sz.y / 2;
+ xoff = (sz.x - sz.y) / 2;
+ }
+
+ for( int j = 0; j < 18; j++ )
+ {
+ int x = 0;
+ int y = -iradius;
+ RotatePoint( &x, &y, 0, 0, -j * 200 );
+ x += (j < 9) ? xoff : -xoff;
+ RotatePoint( &x, &y, 0, 0, tang );
+ edge_data.push_back( CPolyPt( pos.x + x, pos.y + y, false, 0 ) );
+ lpath.push_back( CPolyPt( pos.x + x, pos.y + y ) );
+ }
+
+ if( 0 )
+ {
+ vpaths.push_back( lpath );
+ }
+ else
+ {
+ dpaths.push_back( lpath );
+ }
+
+ edge_data.push_back( CPolyPt( (int) MAGIC_CONT, 0, true, 0 ) );
+
+ if( sz.x != sz.y )
+ {
+ }
+ }
+
+ TYPE_COLLECTOR via_items;
+ static const KICAD_T scanVIASEGMENTS[] = { PCB_VIA_T, EOT };
+ bool haveVias = false;
+
+ via_items.Collect( pcb, scanVIASEGMENTS );
+
+ for( int i = 0; i<via_items.GetCount(); )
+ {
+ wxSize sz;
+ int top_layer;
+ int bottom_layer;
+ ( (SEGVIA*) via_items[i] )->ReturnLayerPair( &top_layer, &bottom_layer );
+ sz.x = ( (SEGVIA*) via_items[i] )->GetDrillValue();
+ sz.y = sz.x;
+
+ if( (sz.x + sz.y) <= 0 )
+ {
+ via_items.Remove( i );
+ }
+ else if( ( bottom_layer > 0 ) && ( top_layer < 15 ) )
+ {
+ via_items.Remove( i );
+ }
+ else
+ {
+ haveVias = true;
+ ++i;
+ D( drill_item->Show( 0, std::cout ); )
+ }
+ }
+
+ for( int i = 0; i < via_items.GetCount(); i++ )
+ {
+ wxSize sz;
+ wxPoint pos;
+ int iradius;
+ std::vector<CPolyPt> lpath;
+
+ sz.x = ( (SEGVIA*) via_items[i] )->GetDrillValue() + 2 * COPPER_EXTEND;
+ sz.y = sz.x;
+ iradius = sz.x / 2;
+ pos = ( (SEGVIA*) via_items[i] )->GetStart();
+
+ // if PTH --> increase size by 100 µ
+ for( int j = 0; j < 2 * C_SLICE; j++ )
+ {
+ int x = 0;
+ int y = -iradius;
+ RotatePoint( &x, &y, 0, 0, -j * _SEG2( C_SLICE ) );
+ edge_data.push_back( CPolyPt( pos.x + x, pos.y + y, false, 0 ) );
+ lpath.push_back( CPolyPt( pos.x + x, pos.y + y ) );
+ }
+
+ vpaths.push_back( lpath );
+ edge_data.push_back( CPolyPt( (int) MAGIC_CONT, 0, true, 0 ) );
+ }
+ }
+ else
+ {
+ wxString error;
+ error << _( "No Edges, create some..." );
+ }
+ }
+
+ if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( EDGE_N ) )
+ {
+ GLdouble v_data[3];
+
+ // top face...
+ if( paths.size() )
+ {
+ tess = gluNewTess();
+ g_Parm_3D_Visu.m_ActZpos =
+ g_Parm_3D_Visu.m_LayerZcoord[(g_Parm_3D_Visu.m_Layers -
+ 1)] - 1.0 * g_Parm_3D_Visu.m_BoardScale; // TSP_20120610
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+ MySetGLColor( g_ColorsSettings.GetLayerColor( EDGE_N ), EDGE_N,
+ ( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] ) ? 1.0 : 0.5 );
+ glNormal3f( 0.0, 0.0, 1.0 );
+ gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )glBegin );
+ gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )glEnd );
+ gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )mytessErrorCB );
+ gluTessCallback( tess, GLU_TESS_VERTEX,
+ ( void (CALLBACK*) () )mytessCPolyPt2Vertex );
+ gluTessCallback( tess, GLU_TESS_COMBINE, ( void (CALLBACK*) () )mytessCombineCB );
+ gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD );
+ GLUtesselator* jtess = gluNewTess();
+ gluTessCallback( jtess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )my2tessBeginCB );
+ gluTessCallback( jtess, GLU_TESS_END, ( void (CALLBACK*) () )my2tessEndCB );
+ gluTessCallback( jtess, GLU_TESS_ERROR, ( void (CALLBACK*) () )my2tessErrorCB );
+ gluTessCallback( jtess, GLU_TESS_VERTEX,
+ ( void (CALLBACK*) () )my2tessCPolyPt2Vertex );
+ gluTessCallback( jtess, GLU_TESS_COMBINE,
+ ( void (CALLBACK*) () )my2tessCombineCB );
+ gluTessProperty( jtess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE );
+ gluTessProperty( jtess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
+
+ gluTessBeginPolygon( jtess, NULL );
+ gluTessNormal( jtess, 0, 0, -1 );
+ gluTessBeginPolygon( tess, NULL );
+
+ int fpol = 1;
+ gluTessBeginContour( tess );
+ gluTessBeginContour( jtess );
+
+ for( ii = 0; ii < (int) edge_data.size(); ii++ )
+ {
+ if( edge_data[ii].x != (int) MAGIC_CONT )
+ {
+ v_data[0] = edge_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -edge_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+
+ if( fpol )
+ {
+ gluTessVertex( tess, v_data, &edge_data[ii] );
+ }
+ else
+ {
+ gluTessVertex( jtess, v_data, &edge_data[ii] );
+ }
+ }
+ else
+ {
+ if( fpol )
+ {
+ fpol = 0;
+ gluTessEndContour( tess );
+ gluTessBeginContour( tess );
+ }
+ else
+ {
+ gluTessEndContour( jtess );
+ gluTessBeginContour( jtess );
+ }
+ }
+ }
+
+ gluTessEndContour( jtess );
+ gluTessEndPolygon( jtess );
+
+ bpii = p_data.size();
+ gluTessEndPolygon( tess );
+ gluDeleteTess( tess );
+ }
+
+ // back face...
+ if( paths.size() )
+ {
+ tess = gluNewTess();
+ g_Parm_3D_Visu.m_ActZpos =
+ g_Parm_3D_Visu.m_LayerZcoord[0] + 1.0 * g_Parm_3D_Visu.m_BoardScale; // TSP_20120610
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+ MySetGLColor( g_ColorsSettings.GetLayerColor( EDGE_N ), EDGE_N,
+ ( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] ) ? 1.0 : 0.5 );
+ glNormal3f( 0.0, 0.0, -1.0 );
+ gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )glBegin );
+ gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )glEnd );
+ gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )mytessErrorCB );
+ gluTessCallback( tess, GLU_TESS_VERTEX,
+ ( void (CALLBACK*) () )mytessCPolyPt2Vertex );
+ gluTessCallback( tess, GLU_TESS_COMBINE, ( void (CALLBACK*) () )mytessCombineCB );
+ gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD );
+ gluTessBeginPolygon( tess, NULL );
+
+ gluTessBeginContour( tess );
+
+ for( ii = 0; ii < (int) edge_data.size(); ii++ )
+ {
+ if( edge_data[ii].x == (int) MAGIC_CONT )
+ break;
+
+ v_data[0] = edge_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -edge_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &edge_data[ii] );
+ }
+
+ int need_c = 1;
+
+ for( ii = 0; ii < (int) xe_data.size(); ii++ )
+ {
+ if( xe_data[ii].x == (int) MAGIC_CONT )
+ {
+ need_c = 1;
+ }
+ else
+ {
+ if( need_c )
+ {
+ need_c = 0;
+ gluTessEndContour( tess );
+ gluTessBeginContour( tess );
+ }
+
+ v_data[0] = xe_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -xe_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &xe_data[ii] );
+ }
+ }
+
+ gluTessEndContour( tess );
+ gluTessEndPolygon( tess );
+ gluDeleteTess( tess );
+ }
+ }
+
+ // draw pcb edges...
+ if( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] && paths.size() )
+ {
+ std::vector<S3D_Vertex> coords;
+ coords.resize( 4 );
+ int si = 0;
+ double tmp = DataScale3D;
+ DataScale3D = 1.0; // Coordinate is already in range for Set_Object_Data();
+ MySetGLColor( g_ColorsSettings.GetLayerColor( EDGE_N ), EDGE_N,
+ ( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] ) ? 1.0 : 0.2 );
+
+ for( ii = 0; ii < (int) edge_data.size(); ii++ )
+ {
+ if( edge_data[ii].x == (int) MAGIC_CONT )
+ {
+ if( si < ii - 1 )
+ {
+ coords[0].x = coords[1].x =
+ (double) edge_data[ii -
+ 1].x * g_Parm_3D_Visu.m_BoardScale;
+ coords[0].y = coords[1].y =
+ -(double) edge_data[ii -
+ 1].y * g_Parm_3D_Visu.m_BoardScale;
+ coords[2].x = coords[3].x = (double) edge_data[si].x *
+ g_Parm_3D_Visu.m_BoardScale;
+ coords[2].y = coords[3].y = -(double) edge_data[si].y *
+ g_Parm_3D_Visu.m_BoardScale;
+ coords[0].z = coords[3].z = g_Parm_3D_Visu.m_LayerZcoord[0] + 1.0 *
+ g_Parm_3D_Visu.m_BoardScale; // TSP_20120610
+ coords[1].z = coords[2].z =
+ g_Parm_3D_Visu.m_LayerZcoord[(g_Parm_3D_Visu.m_Layers -
+ 1)] - 1.0 *
+ g_Parm_3D_Visu.m_BoardScale; // TSP_20120610
+ {
+ Set_Object_Data( coords );
+ }
+
+ for( int jj = si + 1; jj < ii; jj++ )
+ {
+ coords[0].x = coords[2].x;
+ coords[0].y = coords[2].y;
+ coords[1].x = coords[3].x;
+ coords[1].y = coords[3].y;
+ coords[2].x = coords[3].x = (double) edge_data[jj].x *
+ g_Parm_3D_Visu.m_BoardScale;
+ coords[2].y = coords[3].y = -(double) edge_data[jj].y *
+ g_Parm_3D_Visu.m_BoardScale;
+ {
+ Set_Object_Data( coords );
+ }
+ }
+ }
+
+ si = ii + 1;
+ break;
+ }
+ }
+
+ si = 0;
+
+ for( ii = 0; ii < (int) xe_data.size(); ii++ )
+ {
+ if( xe_data[ii].x == (int) MAGIC_CONT )
+ {
+ if( si < ii - 1 )
+ {
+ coords[0].x = coords[1].x =
+ (double) xe_data[ii - 1].x * g_Parm_3D_Visu.m_BoardScale;
+ coords[0].y = coords[1].y =
+ -(double) xe_data[ii -
+ 1].y * g_Parm_3D_Visu.m_BoardScale;
+ coords[2].x = coords[3].x = (double) xe_data[si].x *
+ g_Parm_3D_Visu.m_BoardScale;
+ coords[2].y = coords[3].y = -(double) xe_data[si].y *
+ g_Parm_3D_Visu.m_BoardScale;
+
+ if( (xe_data[ii - 1].utility) && (xe_data[si].utility) )
+ {
+ Set_Object_Data( coords );
+ }
+
+ for( int jj = si + 1; jj < ii; jj++ )
+ {
+ coords[0].x = coords[2].x;
+ coords[0].y = coords[2].y;
+ coords[1].x = coords[3].x;
+ coords[1].y = coords[3].y;
+ coords[2].x = coords[3].x = (double) xe_data[jj].x *
+ g_Parm_3D_Visu.m_BoardScale;
+ coords[2].y = coords[3].y = -(double) xe_data[jj].y *
+ g_Parm_3D_Visu.m_BoardScale;
+
+ if( (xe_data[jj - 1].utility) && (xe_data[jj].utility) )
+ {
+ Set_Object_Data( coords );
+ }
+ }
+ }
+
+ si = ii + 1;
+ }
+ }
+
+ DataScale3D = tmp; // Coordinate is already in range for Set_Object_Data();
+ }
+
+ // draw footprints...
+ tmonly = 0; // TSP_20120605
+
+ for( Module = pcb->m_Modules; Module != NULL; Module = Module->Next() )
+ {
+ Module->Draw3D( this ); // TSP_20120605
+ }
+
+ tmonly = 0; // TSP_20120605
+
+ // draw top mask (if in rendering mode)
+ if( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER]
+ && g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( SOLDERMASK_N_FRONT )
+ && paths.size() )
+ {
+ GLdouble v_data[3];
+ p_data.erase( p_data.begin() + bpii, p_data.end() );
+ tess = gluNewTess();
+ g_Parm_3D_Visu.m_ActZpos =
+ g_Parm_3D_Visu.m_LayerZcoord[SOLDERMASK_N_FRONT];
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+ MySetGLColor( g_ColorsSettings.GetLayerColor(
+ SOLDERMASK_N_FRONT ), SOLDERMASK_N_FRONT,
+ ( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] ) ? 0.8 : 0 );
+ glNormal3f( 0.0, 0.0, 1.0 );
+ gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )glBegin );
+ gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )glEnd );
+ gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )mytessErrorCB );
+ gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )mytessCPolyPt2Vertex );
+ gluTessCallback( tess, GLU_TESS_COMBINE, ( void (CALLBACK*) () )mytessCombineCB );
+ gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
+ gluTessBeginPolygon( tess, NULL );
+
+ gluTessBeginContour( tess );
+
+ for( ii = 0; ii < (int) paths[0].size(); ii++ )
+ {
+ v_data[0] = paths[0][ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -paths[0][ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &paths[0][ii] );
+ }
+
+ gluTessEndContour( tess );
+
+ for( unsigned i = 1; i < paths.size(); i++ )
+ {
+ gluTessBeginContour( tess );
+
+ for( int j = (int) paths[i].size() - 1; j >= 0; j-- )
+ {
+ v_data[0] = paths[i][j].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -paths[i][j].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &paths[i][j] );
+ }
+
+ gluTessEndContour( tess );
+ }
+
+ for( unsigned i = 0; i < dpaths.size(); i++ )
+ {
+ gluTessBeginContour( tess );
+
+ for( int j = (int) dpaths[i].size() - 1; j >= 0; j-- )
+ {
+ v_data[0] = dpaths[i][j].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -dpaths[i][j].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &dpaths[i][j] );
+ }
+
+ gluTessEndContour( tess );
+ }
+
+ // redo for top mask....
+ tmonly = 1;
+
+ // pad mask
+ for( Module = pcb->m_Modules; Module != NULL; Module = Module->Next() )
+ {
+ D_PAD* pad;
+ int lpii;
+
+ for( pad = Module->m_Pads; pad != NULL; pad = pad->Next() )
+ {
+ lpii = p_data.size();
+ pad->Draw3D( this );
+
+ if( (int) p_data.size() > lpii )
+ {
+ gluTessBeginContour( tess );
+
+ for( ii = (int) p_data.size() - 1; ii >= lpii; ii-- )
+ {
+ v_data[0] = p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &p_data[ii] );
+ }
+
+ gluTessEndContour( tess );
+ }
+ }
+
+ // draw rest of module mask
+ EDA_ITEM* Struct = Module->m_Drawings;
+
+ for( ; Struct != NULL; Struct = Struct->Next() )
+ {
+ if( ( ( (BOARD_ITEM*) Struct )->GetLayer() == SOLDERMASK_N_FRONT ) )
+ {
+ int ii, lpii = p_data.size();
+
+ switch( Struct->Type() )
+ {
+ case PCB_MODULE_TEXT_T:
+ break;
+
+ case PCB_MODULE_EDGE_T:
+ {
+ // Draw module edges when no 3d shape exists.
+ // Always draw pcb edges.
+ /* if( !As3dShape || edge->GetLayer() == EDGE_N ) */
+ {
+ Draw3D_DrawSegmentMask( (DRAWSEGMENT*) Struct,
+ SOLDERMASK_N_FRONT, &p_data );
+ gluTessBeginContour( tess );
+
+ for( ii = (int) p_data.size() - 1; ii >= lpii; ii-- )
+ {
+ if( p_data[ii].x == (int) MAGIC_CONT )
+ {
+ gluTessEndContour( tess );
+ gluTessBeginContour( tess );
+ }
+ else
+ {
+ v_data[0] = p_data[ii].x *
+ g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y *
+ g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &p_data[ii] );
+ }
+ }
+
+ gluTessEndContour( tess );
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ // draw mask graphic items
+ EDA_ITEM* PtStruct;
+
+ for( PtStruct = pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() )
+ {
+ if( ( ( (BOARD_ITEM*) PtStruct )->GetLayer() == SOLDERMASK_N_FRONT ) )
+ {
+ int ii, lpii = p_data.size();
+
+ switch( PtStruct->Type() )
+ {
+ case PCB_LINE_T:
+ Draw3D_DrawSegmentMask( (DRAWSEGMENT*) PtStruct, SOLDERMASK_N_FRONT,
+ &p_data );
+ break;
+
+ case PCB_TEXT_T:
+ Draw3D_DrawTextMask( (TEXTE_PCB*) PtStruct, SOLDERMASK_N_FRONT, NULL );
+ break;
+
+ default:
+ break;
+ }
+
+ gluTessBeginContour( tess );
+
+ for( ii = lpii; ii < (int) p_data.size(); ii++ )
+ {
+ if( p_data[ii].x == (int) MAGIC_CONT )
+ {
+ gluTessEndContour( tess );
+ gluTessBeginContour( tess );
+ }
+ else
+ {
+ v_data[0] = p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &p_data[ii] );
+ }
+ }
+
+ gluTessEndContour( tess );
+ }
+ }
+
+ // draw mask zone items
+ {
+ // Draw segments used to fill copper areas. outdated!
+ for( segzone = pcb->m_Zone; segzone != NULL; segzone = segzone->Next() )
+ {
+ if( segzone->GetLayer() == SOLDERMASK_N_FRONT )
+ if( segzone->Type() == PCB_ZONE_T )
+ {
+ Draw3D_Track( segzone );
+ }
+
+
+ }
+
+ // Draw new segments
+ for( ii = 0; ii < pcb->GetAreaCount(); ii++ )
+ {
+ ZONE_CONTAINER* curr_zone = pcb->GetArea( ii );
+
+ if( curr_zone->GetLayer() == SOLDERMASK_N_FRONT )
+ {
+ if( curr_zone->m_FillMode == 0 )
+ {
+ // solid polygons only are used to fill areas
+ if( curr_zone->GetFilledPolysList().size() > 2 )
+ {
+ GLdouble v_data[3];
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+
+ // Draw solid areas contained in this zone
+ int lpii = 0;
+
+ std::vector<CPolyPt> polysList = curr_zone->GetFilledPolysList();
+
+ for( unsigned ii = 0; ii < polysList.size(); ii++ )
+ {
+ if( polysList[ii].end_contour == 1 )
+ {
+ int jj;
+ // reverse last polygon
+ gluTessBeginContour( tess );
+
+ for( jj = lpii; jj <= (int) ii; jj++ )
+ {
+ p_data.push_back( polysList[jj] );
+ v_data[0] = polysList[jj].x *
+ g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -polysList[jj].y *
+ g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data,
+ &p_data[p_data.size() - 1] );
+ }
+
+ gluTessEndContour( tess );
+ lpii = ii + 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ // segments are used to fill areas
+ for( unsigned iseg = 0;
+ iseg < curr_zone->m_FillSegmList.size();
+ iseg++ )
+ {
+ SEGZONE dummysegment( pcb );
+
+ dummysegment.SetLayer( curr_zone->GetLayer() );
+ dummysegment.m_Width = curr_zone->m_ZoneMinThickness;
+
+ dummysegment.m_Start.x =
+ curr_zone->m_FillSegmList[iseg].m_Start.x;
+ dummysegment.m_Start.y =
+ curr_zone->m_FillSegmList[iseg].m_Start.y;
+ dummysegment.m_End.x = curr_zone->m_FillSegmList[iseg].m_End.x;
+ dummysegment.m_End.y = curr_zone->m_FillSegmList[iseg].m_End.y;
+ Draw3D_Track( &dummysegment );
+ }
+ }
+ }
+ }
+
+ // Draw copper areas outlines
+ for( ii = 0; ii < pcb->GetAreaCount(); ii++ )
+ {
+ ZONE_CONTAINER* zone = pcb->GetArea( ii );
+
+ if( zone->GetLayer() == SOLDERMASK_N_FRONT )
+ {
+ std::vector<CPolyPt> polysList = zone->GetFilledPolysList();
+
+ if( polysList.size() == 0 )
+ continue;
+
+ if( zone->m_ZoneMinThickness <= 1 )
+ continue;
+
+ int imax = polysList.size() - 1;
+ CPolyPt* firstcorner = &polysList[0];
+ CPolyPt* begincorner = firstcorner;
+ SEGZONE dummysegment( pcb );
+
+ dummysegment.SetLayer( zone->GetLayer() );
+ dummysegment.m_Width = zone->m_ZoneMinThickness;
+
+ for( int ic = 1; ic <= imax; ic++ )
+ {
+ CPolyPt* endcorner = &polysList[ic];
+
+ if( begincorner->utility == 0 )
+ {
+ // Draw only basic outlines, not extra segments
+ dummysegment.m_Start.x = begincorner->x;
+ dummysegment.m_Start.y = begincorner->y;
+ dummysegment.m_End.x = endcorner->x;
+ dummysegment.m_End.y = endcorner->y;
+ Draw3D_Track( &dummysegment );
+ }
+
+ if( (endcorner->end_contour) || (ic == imax) )
+ {
+ // the last corner of a filled area is found: draw it
+ if( endcorner->utility == 0 )
+ {
+ // Draw only basic outlines, not extra segments
+ dummysegment.m_Start.x = endcorner->x;
+ dummysegment.m_Start.y = endcorner->y;
+ dummysegment.m_End.x = firstcorner->x;
+ dummysegment.m_End.y = firstcorner->y;
+
+ Draw3D_Track( &dummysegment );
+ }
+
+ ic++;
+
+ if( ic < imax - 1 )
+ begincorner = firstcorner = &polysList[ic];
+ }
+ else
+ {
+ begincorner = endcorner;
+ }
+ }
+ }
+ }
+ }
+
+ gluTessEndPolygon( tess );
+ gluDeleteTess( tess );
+ }
+
+ // draw back mask
+ if( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER]
+ && g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( SOLDERMASK_N_BACK )
+ && paths.size() )
+ {
+ GLdouble v_data[3];
+ p_data.erase( p_data.begin() + bpii, p_data.end() );
+ // bottom mask
+ tess = gluNewTess();
+ g_Parm_3D_Visu.m_ActZpos =
+ g_Parm_3D_Visu.m_LayerZcoord[SOLDERMASK_N_BACK];
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+ MySetGLColor( g_ColorsSettings.GetLayerColor( SOLDERMASK_N_BACK ), SOLDERMASK_N_BACK,
+ ( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] ) ? 0.8 : 0 );
+ glNormal3f( 0.0, 0.0, -1.0 );
+ gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )glBegin );
+ gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )glEnd );
+ gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )mytessErrorCB );
+ gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )mytessCPolyPt2Vertex );
+ gluTessCallback( tess, GLU_TESS_COMBINE, ( void (CALLBACK*) () )mytessCombineCB );
+ gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
+ gluTessBeginPolygon( tess, NULL );
+ gluTessBeginContour( tess );
+
+ for( ii = 0; ii < (int) paths[0].size(); ii++ )
+ {
+ v_data[0] = paths[0][ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -paths[0][ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &paths[0][ii] );
+ }
+
+ gluTessEndContour( tess );
+
+ for( unsigned i = 1; i < paths.size(); i++ )
+ {
+ gluTessBeginContour( tess );
+
+ for( int j = (int) paths[i].size() - 1; j >= 0; j-- )
+ {
+ v_data[0] = paths[i][j].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -paths[i][j].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &paths[i][j] );
+ }
+
+ gluTessEndContour( tess );
+ }
+
+ for( unsigned i = 0; i < dpaths.size(); i++ )
+ {
+ gluTessBeginContour( tess );
+
+ for( int j = (int) dpaths[i].size() - 1; j >= 0; j-- )
+ {
+ v_data[0] = dpaths[i][j].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -dpaths[i][j].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &dpaths[i][j] );
+ }
+
+ gluTessEndContour( tess );
+ }
+
+ // redo for back mask....
+ tmonly = 3;
+
+ for( Module = pcb->m_Modules; Module != NULL; Module = Module->Next() )
+ {
+ D_PAD* pad;
+ int lpii;
+
+ for( pad = Module->m_Pads; pad != NULL; pad = pad->Next() )
+ {
+ lpii = p_data.size();
+ pad->Draw3D( this );
+
+ if( (int) p_data.size() > lpii )
+ {
+ gluTessBeginContour( tess );
+
+ for( ii = (int) p_data.size() - 1; ii >= lpii; ii-- )
+ {
+ v_data[0] = p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &p_data[ii] );
+ }
+
+ gluTessEndContour( tess );
+ }
+ }
+
+ // draw rest of module mask
+ EDA_ITEM* Struct = Module->m_Drawings;
+
+ for( ; Struct != NULL; Struct = Struct->Next() )
+ {
+ if( ( ( (BOARD_ITEM*) Struct )->GetLayer() == SOLDERMASK_N_BACK ) )
+ {
+ int ii, lpii = p_data.size();
+
+ switch( Struct->Type() )
+ {
+ case PCB_MODULE_TEXT_T:
+ break;
+
+ case PCB_MODULE_EDGE_T:
+ Draw3D_DrawSegmentMask( (DRAWSEGMENT*) Struct, SOLDERMASK_N_BACK,
+ &p_data );
+ break;
+
+ default:
+ break;
+ }
+
+ gluTessBeginContour( tess );
+
+ for( ii = (int) p_data.size() - 1; ii >= lpii; ii-- )
+ {
+ if( p_data[ii].x == (int) MAGIC_CONT )
+ {
+ gluTessEndContour( tess );
+ gluTessBeginContour( tess );
+ }
+ else
+ {
+ v_data[0] = p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &p_data[ii] );
+ }
+ }
+
+ gluTessEndContour( tess );
+ }
+ }
+ }
+
+ // draw mask graphic items
+ EDA_ITEM* PtStruct;
+
+ for( PtStruct = pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() )
+ {
+ if( ( ( (BOARD_ITEM*) PtStruct )->GetLayer() == SOLDERMASK_N_BACK ) )
+ {
+ int ii, lpii = p_data.size();
+
+ switch( PtStruct->Type() )
+ {
+ case PCB_LINE_T:
+ Draw3D_DrawSegmentMask( (DRAWSEGMENT*) PtStruct, SOLDERMASK_N_BACK,
+ &p_data );
+ break;
+
+ case PCB_TEXT_T:
+ Draw3D_DrawTextMask( (TEXTE_PCB*) PtStruct, SOLDERMASK_N_BACK, NULL );
+ break;
+
+ default:
+ break;
+ }
+
+ gluTessBeginContour( tess );
+
+ for( ii = lpii; ii < (int) p_data.size(); ii++ )
+ {
+ if( p_data[ii].x == (int) MAGIC_CONT )
+ {
+ gluTessEndContour( tess );
+ gluTessBeginContour( tess );
+ }
+ else
+ {
+ v_data[0] = p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &p_data[ii] );
+ }
+ }
+
+ gluTessEndContour( tess );
+ }
+ }
+
+ // draw mask zone items
+ {
+ // Draw segments used to fill copper areas. outdated!
+ for( segzone = pcb->m_Zone; segzone != NULL; segzone = segzone->Next() )
+ {
+ if( segzone->GetLayer() == SOLDERMASK_N_BACK )
+ if( segzone->Type() == PCB_ZONE_T )
+ {
+ Draw3D_Track( segzone );
+ }
+
+
+ }
+
+ // Draw new segments
+ for( ii = 0; ii < pcb->GetAreaCount(); ii++ )
+ {
+ ZONE_CONTAINER* curr_zone = pcb->GetArea( ii );
+
+ if( curr_zone->GetLayer() == SOLDERMASK_N_BACK )
+ {
+ if( curr_zone->m_FillMode == 0 )
+ {
+ // solid polygons only are used to fill areas
+ if( curr_zone->GetFilledPolysList().size() > 2 )
+ {
+ GLdouble v_data[3];
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+
+ // Draw solid areas contained in this zone
+ int lpii = 0;
+
+ std::vector<CPolyPt> polysList = curr_zone->GetFilledPolysList();
+
+ for( unsigned ii = 0; ii < polysList.size(); ii++ )
+ {
+ if( polysList[ii].end_contour == 1 )
+ {
+ int jj;
+ // reverse last polygon
+ gluTessBeginContour( tess );
+
+ for( jj = lpii; jj <= (int) ii; jj++ )
+ {
+ p_data.push_back( polysList[jj] );
+ v_data[0] = polysList[jj].x *
+ g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -polysList[jj].y *
+ g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data,
+ &p_data[p_data.size() - 1] );
+ }
+
+ gluTessEndContour( tess );
+ lpii = ii + 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ // segments are used to fill areas
+ for( unsigned iseg = 0;
+ iseg < curr_zone->m_FillSegmList.size();
+ iseg++ )
+ {
+ SEGZONE dummysegment( pcb );
+
+ dummysegment.SetLayer( curr_zone->GetLayer() );
+ dummysegment.m_Width = curr_zone->m_ZoneMinThickness;
+
+ dummysegment.m_Start.x =
+ curr_zone->m_FillSegmList[iseg].m_Start.x;
+ dummysegment.m_Start.y =
+ curr_zone->m_FillSegmList[iseg].m_Start.y;
+ dummysegment.m_End.x = curr_zone->m_FillSegmList[iseg].m_End.x;
+ dummysegment.m_End.y = curr_zone->m_FillSegmList[iseg].m_End.y;
+ Draw3D_Track( &dummysegment );
+ }
+ }
+ }
+ }
+
+ // Draw copper areas outlines
+ for( ii = 0; ii < pcb->GetAreaCount(); ii++ )
+ {
+ ZONE_CONTAINER* zone = pcb->GetArea( ii );
+
+ if( zone->GetLayer() == SOLDERMASK_N_BACK )
+ {
+ std::vector<CPolyPt> polysList = zone->GetFilledPolysList();
+
+ if( polysList.size() == 0 )
+ continue;
+
+ if( zone->m_ZoneMinThickness <= 1 )
+ continue;
+
+ int imax = polysList.size() - 1;
+ CPolyPt* firstcorner = &polysList[imax];
+ CPolyPt* begincorner = firstcorner;
+ SEGZONE dummysegment( pcb );
+
+ dummysegment.SetLayer( zone->GetLayer() );
+ dummysegment.m_Width = zone->m_ZoneMinThickness;
+
+ for( int ic = imax - 1; ic > 0; ic-- )
+ {
+ CPolyPt* endcorner = &polysList[ic];
+
+ if( begincorner->utility == 0 )
+ {
+ // Draw only basic outlines, not extra segments
+ dummysegment.m_Start.x = begincorner->x;
+ dummysegment.m_Start.y = begincorner->y;
+ dummysegment.m_End.x = endcorner->x;
+ dummysegment.m_End.y = endcorner->y;
+ Draw3D_Track( &dummysegment );
+ }
+
+ if( (endcorner->end_contour) || (ic == 0) )
+ {
+ // the last corner of a filled area is found: draw it
+ if( endcorner->utility == 0 )
+ {
+ // Draw only basic outlines, not extra segments
+ dummysegment.m_Start.x = endcorner->x;
+ dummysegment.m_Start.y = endcorner->y;
+ dummysegment.m_End.x = firstcorner->x;
+ dummysegment.m_End.y = firstcorner->y;
+
+ Draw3D_Track( &dummysegment );
+ }
+
+ ic++;
+
+ if( ic >= 0 )
+ begincorner = firstcorner = &polysList[ic];
+ }
+ else
+ {
+ begincorner = endcorner;
+ }
+ }
+ }
+ }
+ }
+
+ gluTessEndPolygon( tess );
+ gluDeleteTess( tess );
+ }
+
+ p_data.clear();
+ }
+
+ if( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] )
+ {
+ // draw silk..
+ int silki;
+
+ for( silki = 0; silki < 2; silki++ )
+ {
+ // fill jtess with silk stuff
+ int llay = (silki) ? SILKSCREEN_N_FRONT : SILKSCREEN_N_BACK;
+
+ if( !g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( llay ) )
+ continue;
+
+ tess = gluNewTess();
+ tmonly = 1;
+ GLUtesselator* jtess = gluNewTess();
+ p_data.clear();
+ g_Parm_3D_Visu.m_ActZpos = g_Parm_3D_Visu.m_LayerZcoord[llay];
+ GLdouble v_data[3];
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+ int color = g_ColorsSettings.GetLayerColor( llay );
+ MySetGLColor( color, llay, 0.8 );
+ glNormal3f( 0.0, 0.0, (silki) ? 1.0 : -1.0 );
+ gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )glBegin );
+ gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )glEnd );
+ gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )mytessErrorCB );
+ gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )mytessCPolyPt2Vertex );
+ gluTessCallback( tess, GLU_TESS_COMBINE, ( void (CALLBACK*) () )mytessCombineCB );
+ gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
+
+ gluTessCallback( jtess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )my3tessBeginCB );
+ gluTessCallback( jtess, GLU_TESS_END, ( void (CALLBACK*) () )my3tessEndCB );
+ gluTessCallback( jtess, GLU_TESS_ERROR, ( void (CALLBACK*) () )my3tessErrorCB );
+ gluTessCallback( jtess, GLU_TESS_VERTEX,
+ ( void (CALLBACK*) () )my3tessCPolyPt2Vertex );
+ gluTessCallback( jtess, GLU_TESS_COMBINE, ( void (CALLBACK*) () )my3tessCombineCB );
+ gluTessProperty( jtess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE );
+ gluTessProperty( jtess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO );
+
+ gluTessBeginPolygon( tess, NULL );
+ gluTessBeginPolygon( jtess, NULL );
+
+ gluTessNormal( tess, 0, 0, -1 );
+ gluTessNormal( jtess, 0, 0, -1 );
+
+ for( Module = pcb->m_Modules; Module != NULL; Module = Module->Next() )
+ {
+ TEXTE_MODULE* ref = Module->m_Reference;
+
+ // Draw Reference...
+ if( do_ref
+ && ( ( ( ( (BOARD_ITEM*) Module )->GetLayer() ) ? SILKSCREEN_N_FRONT :
+ SILKSCREEN_N_BACK )
+ == llay ) )
+ {
+ for( ; ref != NULL; ref = ref->Next() )
+ {
+ if( ref->IsVisible() )
+ {
+ Draw3D_DrawTextMask( (TEXTE_PCB*) ref, llay, jtess );
+ }
+ }
+ }
+
+ EDA_ITEM* Struct = Module->m_Drawings;
+
+ for( ; Struct != NULL; Struct = Struct->Next() )
+ {
+ if( ( ( (BOARD_ITEM*) Struct )->GetLayer() == llay ) )
+ {
+ int ii, lpii = p_data.size();
+
+ switch( Struct->Type() )
+ {
+ case PCB_MODULE_TEXT_T:
+ break;
+
+ case PCB_MODULE_EDGE_T:
+ {
+ // Draw module edges when no 3d shape exists.
+ // Always draw pcb edges.
+ /* if( !As3dShape || edge->GetLayer() == EDGE_N ) */
+ {
+ Draw3D_DrawSegmentMask( (DRAWSEGMENT*) Struct, llay, &p_data );
+ gluTessBeginContour( jtess );
+
+ for( ii = (int) p_data.size() - 1; ii >= lpii; ii-- )
+ {
+ if( p_data[ii].x == (int) MAGIC_CONT )
+ {
+ gluTessEndContour( jtess );
+ gluTessBeginContour( jtess );
+ }
+ else
+ {
+ v_data[0] = p_data[ii].x *
+ g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y *
+ g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( jtess, v_data, &p_data[ii] );
+ }
+ }
+
+ gluTessEndContour( jtess );
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ // draw silk graphic items
+ EDA_ITEM* PtStruct;
+
+ for( PtStruct = pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() )
+ {
+ if( ( ( (BOARD_ITEM*) PtStruct )->GetLayer() == llay ) )
+ {
+ int ii, lpii = p_data.size();
+
+ switch( PtStruct->Type() )
+ {
+ case PCB_LINE_T:
+ Draw3D_DrawSegmentMask( (DRAWSEGMENT*) PtStruct, llay, &p_data );
+ gluTessBeginContour( jtess );
+
+ for( ii = p_data.size() - 1; ii >= lpii; ii-- )
+ {
+ if( p_data[ii].x == (int) MAGIC_CONT )
+ {
+ gluTessEndContour( jtess );
+ gluTessBeginContour( jtess );
+ }
+ else
+ {
+ v_data[0] = p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( jtess, v_data, &p_data[ii] );
+ }
+ }
+
+ gluTessEndContour( jtess );
+ break;
+
+ case PCB_TEXT_T:
+ Draw3D_DrawTextMask( (TEXTE_PCB*) PtStruct, llay, jtess );
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ for( ii = 0; ii < pcb->GetAreaCount(); ii++ )
+ {
+ ZONE_CONTAINER* curr_zone = pcb->GetArea( ii );
+
+ if( curr_zone->GetLayer() == llay )
+ {
+ if( curr_zone->m_FillMode == 0 )
+ {
+ // solid polygons only are used to fill areas
+ if( curr_zone->GetFilledPolysList().size() > 2 )
+ {
+ GLdouble xv_data[3];
+ xv_data[2] = g_Parm_3D_Visu.m_ActZpos;
+
+ // Draw solid areas contained in this zone
+
+ std::vector<CPolyPt> polysList = curr_zone->GetFilledPolysList();
+ }
+ }
+ else
+ {
+ // segments are used to fill areas
+ for( unsigned iseg = 0; iseg < curr_zone->m_FillSegmList.size(); iseg++ )
+ {
+ SEGZONE dummysegment( pcb );
+
+ dummysegment.SetLayer( curr_zone->GetLayer() );
+ dummysegment.m_Width = curr_zone->m_ZoneMinThickness;
+
+ dummysegment.m_Start.x = curr_zone->m_FillSegmList[iseg].m_Start.x;
+ dummysegment.m_Start.y = curr_zone->m_FillSegmList[iseg].m_Start.y;
+ dummysegment.m_End.x = curr_zone->m_FillSegmList[iseg].m_End.x;
+ dummysegment.m_End.y = curr_zone->m_FillSegmList[iseg].m_End.y;
+ Draw3D_Track( &dummysegment );
+ }
+ }
+ }
+ }
+
+ // fill tess with mask stuff
+ if( edge_data.size() > 2 )
+ {
+ std::vector<CPolyPt> o_data;
+ int ei = 0;
+ int xmini = 0;
+ int xmin = 0x7fffffff;
+ int ymin = 0x7fffffff;
+ int xmax = MAGIC_CONT;
+ int ymax = MAGIC_CONT;
+ gluTessEndPolygon( jtess );
+
+ for( ii = 0; edge_data[ii].x != (int) MAGIC_CONT; ii++ )
+ {
+ if( (int) edge_data[ii].x > xmax )
+ {
+ xmax = edge_data[ii].x;
+ }
+
+ if( (int) edge_data[ii].y > ymax )
+ {
+ ymax = edge_data[ii].y;
+ }
+
+ if( (int) edge_data[ii].x < xmin )
+ {
+ xmin = edge_data[ii].x;
+ xmini = ii;
+ }
+
+ if( (int) edge_data[ii].y < ymin )
+ {
+ ymin = edge_data[ii].y;
+ }
+
+ ei = ii;
+ }
+
+ // do cover polygon...
+ o_data.push_back( CPolyPt( (int) 0x90000000, (int) 0x90000000 ) );
+ o_data.push_back( CPolyPt( (int) 0x90000000, (int) 0x70000000 ) );
+ o_data.push_back( CPolyPt( (int) 0x70000000, (int) 0x70000000 ) );
+ o_data.push_back( CPolyPt( (int) 0x70000000, (int) 0x90000000 ) );
+
+ gluTessBeginContour( tess );
+
+ for( ii = 0; ii < 4; ii++ )
+ {
+ v_data[0] = o_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -o_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &o_data[ii] );
+ }
+
+ gluTessEndContour( tess );
+ gluTessBeginContour( tess );
+
+ for( ii = 0; edge_data[ii].x != (int) MAGIC_CONT; ii++ )
+ {
+ v_data[0] = edge_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -edge_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &edge_data[ii] );
+ }
+
+ gluTessEndContour( tess );
+
+ // subtract pcb
+ int li = 0;
+
+ for( ii = 0; ii < (int) xe_data.size(); ii++ )
+ {
+ if( xe_data[ii].x == (int) MAGIC_CONT )
+ {
+ gluTessBeginContour( tess );
+
+ for( int j = ii - 1; j >= li; j-- )
+ {
+ v_data[0] = xe_data[j].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -xe_data[j].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &xe_data[j] );
+ }
+
+ gluTessEndContour( tess );
+ li = ii + 1;
+ }
+ }
+
+ // subtract pad mask holes
+ tmonly = (silki) ? 1 : 3;
+
+ for( Module = pcb->m_Modules; Module != NULL; Module = Module->Next() )
+ {
+ D_PAD* pad;
+ int lpii, ii;
+
+ for( pad = Module->m_Pads; pad != NULL; pad = pad->Next() )
+ {
+ lpii = p_data.size();
+
+ if( ( pad->GetLayerMask() & ( 1 << (SOLDERPASTE_N_BACK | llay) ) ) == 0 )
+ continue;
+
+ pad->Draw3D( this );
+
+ if( (int) p_data.size() > lpii )
+ {
+ gluTessBeginContour( tess );
+
+ for( ii = (int) p_data.size() - 1; ii >= lpii; ii-- )
+ {
+ v_data[0] = p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &p_data[ii] );
+ }
+
+ gluTessEndContour( tess );
+ }
+ }
+ }
+ }
+ else
+ {
+ gluTessEndPolygon( jtess );
+ }
+
+ gluTessEndPolygon( tess );
+ gluDeleteTess( tess );
+ gluDeleteTess( jtess );
+ p_data.clear();
+ tmonly = 0;
+ }
+ }
+
+ // draw rest of stuff..
+ for( int stuffi = DRAW_N; stuffi < LAYER_COUNT; stuffi++ )
+ {
+ EDA_ITEM* PtStruct;
+
+ for( PtStruct = pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() )
+ {
+ if( ( ( (BOARD_ITEM*) PtStruct )->GetLayer() == stuffi ) )
+ {
+ switch( PtStruct->Type() )
+ {
+ case PCB_LINE_T:
+ Draw3D_DrawSegment( (DRAWSEGMENT*) PtStruct );
+ break;
+
+ case PCB_TEXT_T:
+ Draw3D_DrawText( (TEXTE_PCB*) PtStruct );
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ for( ii = 0; ii < pcb->GetAreaCount(); ii++ )
+ {
+ ZONE_CONTAINER* curr_zone = pcb->GetArea( ii );
+
+ if( curr_zone->GetLayer() == stuffi )
+ {
+ if( curr_zone->m_FillMode == 0 )
+ {
+ // solid polygons only are used to fill areas
+ if( curr_zone->GetFilledPolysList().size() > 2 )
+ {
+ GLdouble xv_data[3];
+ xv_data[2] = g_Parm_3D_Visu.m_ActZpos;
+
+ // Draw solid areas contained in this zone
+
+ std::vector<CPolyPt> polysList = curr_zone->GetFilledPolysList();
+ }
+ }
+ else
+ {
+ // segments are used to fill areas
+ for( unsigned iseg = 0; iseg < curr_zone->m_FillSegmList.size(); iseg++ )
+ {
+ SEGZONE dummysegment( pcb );
+
+ dummysegment.SetLayer( curr_zone->GetLayer() );
+ dummysegment.m_Width = curr_zone->m_ZoneMinThickness;
+
+ dummysegment.m_Start.x = curr_zone->m_FillSegmList[iseg].m_Start.x;
+ dummysegment.m_Start.y = curr_zone->m_FillSegmList[iseg].m_Start.y;
+ dummysegment.m_End.x = curr_zone->m_FillSegmList[iseg].m_End.x;
+ dummysegment.m_End.y = curr_zone->m_FillSegmList[iseg].m_End.y;
+ Draw3D_Track( &dummysegment );
+ }
+ }
+ }
+ }
+ }
+
+#define MM2INTERN( mm ) ( (int) ( ( (double) (mm) ) * 10000.0 / 25.4 + 0.5 ) )
+#define INTERN2MM( intern ) ( (int) ( ( (double) (intern) ) / 10000.0 * 25.4 + 0.5 ) )
+
+ // draw mm grid..
+ if( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_GRID] )
+ {
+ int lx = MM2INTERN( -100 );
+ int uy = MM2INTERN( 100 );
+ int hh = 200;
+ int ww = 200;
+ int need_back = g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER];
+
+ if( paths.size() > 0 )
+ {
+ lx = 0x7fffffff;
+ int ly = 0x7fffffff;
+ int ux = 0x80000000;
+ uy = 0x80000000;
+
+ for( unsigned i = 0; i < paths[0].size(); i++ )
+ {
+ if( paths[0][i].x > ux )
+ ux = paths[0][i].x;
+
+ if( paths[0][i].y > uy )
+ uy = paths[0][i].y;
+
+ if( paths[0][i].x < lx )
+ lx = paths[0][i].x;
+
+ if( paths[0][i].y < ly )
+ ly = paths[0][i].y;
+ }
+
+ hh = INTERN2MM( uy - ly );
+ ww = INTERN2MM( ux - lx );
+ }
+
+ SEGZONE dummysegment( pcb );
+
+#define GRID_SCAL 5
+ for( int mm = 0; mm <= ww; mm += 1 )
+ {
+ int w = GRID_SCAL +
+ ( ( (mm % 10) == 0 ) ? GRID_SCAL : 0 ) + ( ( (mm % 5) == 0 ) ? GRID_SCAL : 0 );
+ dummysegment.m_Width = w;
+ // vert..
+ dummysegment.m_Start.x = lx + MM2INTERN( mm ) - 0;
+ dummysegment.m_Start.y = uy - MM2INTERN( 0 );
+ dummysegment.m_End.x = lx + MM2INTERN( mm ) + 0;
+ dummysegment.m_End.y = uy - MM2INTERN( hh );
+ dummysegment.SetLayer( 31 );
+ Draw3D_Track( &dummysegment );
+
+ if( need_back )
+ {
+ dummysegment.SetLayer( 30 );
+ Draw3D_Track( &dummysegment );
+ }
+ }
+
+ for( int mm = 0; mm <= hh; mm += 1 )
+ {
+ int w = GRID_SCAL +
+ ( ( (mm % 10) == 0 ) ? GRID_SCAL : 0 ) + ( ( (mm % 5) == 0 ) ? GRID_SCAL : 0 );
+ dummysegment.m_Width = w;
+ // hor..
+ dummysegment.m_Start.x = lx + MM2INTERN( 0 );
+ dummysegment.m_Start.y = uy - MM2INTERN( mm ) - 0;
+ dummysegment.m_End.x = lx + MM2INTERN( ww );
+ dummysegment.m_End.y = uy - MM2INTERN( mm ) + 0;
+ dummysegment.SetLayer( 31 );
+ Draw3D_Track( &dummysegment );
+
+ if( need_back )
+ {
+ dummysegment.SetLayer( 30 );
+ Draw3D_Track( &dummysegment );
+ }
+ }
}
glEndList();
@@ -382,36 +3483,61 @@
void EDA_3D_CANVAS::Draw3D_Track( TRACK* track )
{
double zpos;
- int layer = track->GetLayer();
+ int layer = track->GetLayer();
double ox, oy, fx, fy;
double w;
- if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
- return;
-
- int color = g_ColorsSettings.GetLayerColor( layer );
-
- if( layer == LAST_COPPER_LAYER )
- layer = g_Parm_3D_Visu.m_Layers - 1;
-
- zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
-
- SetGLColor( color );
- glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 );
-
- w = track->m_Width * g_Parm_3D_Visu.m_BoardScale;
- ox = track->m_Start.x * g_Parm_3D_Visu.m_BoardScale;
- oy = track->m_Start.y * g_Parm_3D_Visu.m_BoardScale;
- fx = track->m_End.x * g_Parm_3D_Visu.m_BoardScale;
- fy = track->m_End.y * g_Parm_3D_Visu.m_BoardScale;
- Draw3D_FilledSegment( ox, -oy, fx, -fy, w, zpos );
+ if( tmonly == 1 )
+ {
+ // fill polygon...
+ if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
+ return;
+
+ w = track->m_Width * g_Parm_3D_Visu.m_BoardScale;
+ ox = track->m_Start.x * g_Parm_3D_Visu.m_BoardScale;
+ oy = track->m_Start.y * g_Parm_3D_Visu.m_BoardScale;
+ fx = track->m_End.x * g_Parm_3D_Visu.m_BoardScale;
+ fy = track->m_End.y * g_Parm_3D_Visu.m_BoardScale;
+ Draw3D_FilledSegmentMask( ox, -oy, fx, -fy, w, 0, &p_data, 1 );
+ }
+ else
+ {
+ if( ( layer < 30) && ( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false ) )
+ return;
+
+ int color = g_ColorsSettings.GetLayerColor( layer );
+
+ if( layer == LAST_COPPER_LAYER )
+ layer = g_Parm_3D_Visu.m_Layers - 1;
+
+ zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
+
+ if( layer >= 30 )
+ {
+ glColor4f( 0.4, 0.4, 0.8, 0.7 );
+ glNormal3f( 0.0, 0.0, (layer & 1) ? 1.0 : -1.0 );
+ }
+ else
+ {
+ MySetGLColor( color, layer, 0.8 );
+ glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 );
+ }
+
+ w = track->m_Width * g_Parm_3D_Visu.m_BoardScale;
+ ox = track->m_Start.x * g_Parm_3D_Visu.m_BoardScale;
+ oy = track->m_Start.y * g_Parm_3D_Visu.m_BoardScale;
+ fx = track->m_End.x * g_Parm_3D_Visu.m_BoardScale;
+ fy = track->m_End.y * g_Parm_3D_Visu.m_BoardScale;
+ Draw3D_FilledSegment( ox, -oy, fx, -fy, w, zpos );
+ }
}
+/* XXX TSP */
void EDA_3D_CANVAS::Draw3D_SolidPolygonsInZones( ZONE_CONTAINER* aZone )
{
double zpos;
- int layer = aZone->GetLayer();
+ int layer = aZone->GetLayer();
if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
return;
@@ -425,24 +3551,23 @@
g_Parm_3D_Visu.m_ActZpos = zpos;
- SetGLColor( color );
+ MySetGLColor( color, layer, 0.8 );
glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 );
GLUtesselator* tess = gluNewTess();
- gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*)() )tessBeginCB );
- gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*)() )tessEndCB );
- gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*)() )tessErrorCB );
- gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*)() )tessCPolyPt2Vertex );
+ gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )glBegin );
+ gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )glEnd );
+ gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )tessErrorCB );
+ gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )tessCPolyPt2Vertex );
GLdouble v_data[3];
v_data[2] = zpos;
- //gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
-
// Draw solid areas contained in this zone
int StartContour = 1;
std::vector<CPolyPt> polysList = aZone->GetFilledPolysList();
+
for( unsigned ii = 0; ii < polysList.size(); ii++ )
{
if( StartContour == 1 )
@@ -452,8 +3577,8 @@
StartContour = 0;
}
- v_data[0] = polysList[ii].x * g_Parm_3D_Visu.m_BoardScale;
- v_data[1] = -polysList[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ v_data[0] = polysList[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -polysList[ii].y * g_Parm_3D_Visu.m_BoardScale;
gluTessVertex( tess, v_data, &polysList[ii] );
if( polysList[ii].end_contour == 1 )
@@ -471,59 +3596,68 @@
void EDA_3D_CANVAS::Draw3D_Via( SEGVIA* via )
{
double x, y, r, hole;
- int layer, top_layer, bottom_layer;
- double zpos, height;
- int color;
-
- r = via->m_Width * g_Parm_3D_Visu.m_BoardScale / 2;
- hole = via->GetDrillValue();
- hole *= g_Parm_3D_Visu.m_BoardScale / 2;
- x = via->m_Start.x * g_Parm_3D_Visu.m_BoardScale;
- y = via->m_Start.y * g_Parm_3D_Visu.m_BoardScale;
-
- via->ReturnLayerPair( &top_layer, &bottom_layer );
-
- // Drawing filled circles:
- for( layer = bottom_layer; layer < g_Parm_3D_Visu.m_Layers; layer++ )
- {
- zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
-
- if( layer < g_Parm_3D_Visu.m_Layers - 1 )
- {
- if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
- continue;
-
- color = g_ColorsSettings.GetLayerColor( layer );
- }
- else
- {
- if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( LAYER_N_FRONT ) == false )
- continue;
-
- color = g_ColorsSettings.GetLayerColor( LAYER_N_FRONT );
- }
-
- SetGLColor( color );
-
- // SetGLColor( LIGHTGRAY );
- glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 );
-
- if( layer == LAYER_N_BACK )
- zpos = zpos - 5 * g_Parm_3D_Visu.m_BoardScale;
- else
- zpos = zpos + 5 * g_Parm_3D_Visu.m_BoardScale;
-
- Draw3D_FilledCircle( x, -y, r, hole, zpos );
-
- if( layer >= top_layer )
- break;
- }
-
- // Drawing hole:
- color = g_ColorsSettings.GetItemColor( VIAS_VISIBLE + via->m_Shape );
- SetGLColor( color );
- height = g_Parm_3D_Visu.m_LayerZcoord[top_layer] - g_Parm_3D_Visu.m_LayerZcoord[bottom_layer];
- Draw3D_FilledCylinder( x, -y, hole, height, g_Parm_3D_Visu.m_LayerZcoord[bottom_layer] );
+ int layer, top_layer, bottom_layer;
+ double zpos, height = 0;
+ int color;
+
+ r = via->m_Width * g_Parm_3D_Visu.m_BoardScale / 2;
+ hole = via->GetDrillValue();
+ hole *= g_Parm_3D_Visu.m_BoardScale / 2;
+ x = via->m_Start.x * g_Parm_3D_Visu.m_BoardScale;
+ y = via->m_Start.y * g_Parm_3D_Visu.m_BoardScale;
+
+ if( tmonly == 0 )
+ {
+ via->ReturnLayerPair( &top_layer, &bottom_layer );
+
+ // Drawing filled circles:
+ for( layer = bottom_layer; layer < g_Parm_3D_Visu.m_Layers; layer++ )
+ {
+ zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
+
+ if( layer < g_Parm_3D_Visu.m_Layers - 1 )
+ {
+ if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
+ continue;
+
+ color = g_ColorsSettings.GetLayerColor( layer );
+ }
+ else
+ {
+ if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( LAYER_N_FRONT ) == false )
+ continue;
+
+ color = g_ColorsSettings.GetLayerColor( LAYER_N_FRONT );
+ }
+
+ MySetGLColor( color, layer, 1 );
+
+ glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 );
+
+ if( layer == LAYER_N_BACK )
+ zpos = zpos - 5 * g_Parm_3D_Visu.m_BoardScale;
+ else
+ zpos = zpos + 5 * g_Parm_3D_Visu.m_BoardScale;
+
+ Draw3D_FilledCircle( x, -y, r, hole, zpos );
+
+ if( layer >= top_layer )
+ break;
+ }
+
+ // Drawing hole:
+ color = g_ColorsSettings.GetItemColor( VIAS_VISIBLE + via->m_Shape );
+ MySetGLColor( color, layer, 0.8 );
+ height = g_Parm_3D_Visu.m_LayerZcoord[top_layer] -
+ g_Parm_3D_Visu.m_LayerZcoord[bottom_layer];
+ Draw3D_FilledCylinder( x, -y, hole, height, g_Parm_3D_Visu.m_LayerZcoord[bottom_layer] );
+ }
+ else
+ {
+ bottom_layer = 0;
+ Draw3D_FilledCylinderMask( x, -y, hole, height,
+ g_Parm_3D_Visu.m_LayerZcoord[bottom_layer] );
+ }
}
@@ -532,22 +3666,22 @@
double x, y, xf, yf;
double zpos, w;
- int layer = segment->GetLayer();
+ int layer = segment->GetLayer();
if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
return;
int color = g_ColorsSettings.GetLayerColor( layer );
- SetGLColor( color );
-
- w = segment->GetWidth() * g_Parm_3D_Visu.m_BoardScale;
-
- x = segment->GetStart().x * g_Parm_3D_Visu.m_BoardScale;
- y = segment->GetStart().y * g_Parm_3D_Visu.m_BoardScale;
-
- xf = segment->GetEnd().x * g_Parm_3D_Visu.m_BoardScale;
- yf = segment->GetEnd().y * g_Parm_3D_Visu.m_BoardScale;
+ MySetGLColor( color, layer, 0.8 );
+
+ w = segment->GetWidth() * g_Parm_3D_Visu.m_BoardScale;
+
+ x = segment->GetStart().x * g_Parm_3D_Visu.m_BoardScale;
+ y = segment->GetStart().y * g_Parm_3D_Visu.m_BoardScale;
+
+ xf = segment->GetEnd().x * g_Parm_3D_Visu.m_BoardScale;
+ yf = segment->GetEnd().y * g_Parm_3D_Visu.m_BoardScale;
if( layer == EDGE_N )
{
@@ -559,15 +3693,39 @@
switch( segment->GetShape() )
{
case S_ARC:
- Draw3D_ArcSegment( x, -y, xf, -yf, segment->GetAngle(), w, zpos );
+
+ if( !g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] )
+ Draw3D_ArcSegment( x, -y, xf, -yf, segment->GetAngle(), w, zpos );
+
+ if( layer == 1 )
+ {
+ Draw3D_ArcSegmentMask( x, -y, xf, -yf, segment->GetAngle(), w, zpos );
+ }
+
break;
case S_CIRCLE:
- Draw3D_CircleSegment( x, -y, xf, -yf, w, zpos );
+
+ if( !g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] )
+ Draw3D_CircleSegment( x, -y, xf, -yf, w, zpos );
+
+ if( layer == 1 )
+ {
+ Draw3D_CircleSegmentMask( x, y, xf, yf, w, zpos );
+ }
+
break;
default:
- Draw3D_FilledSegment( x, -y, xf, -yf, w, zpos );
+
+ if( !g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] )
+ Draw3D_FilledSegment( x, -y, xf, -yf, w, zpos );
+
+ if( layer == 1 )
+ {
+ Draw3D_Mask( x, y, xf, yf, w, zpos );
+ }
+
break;
}
}
@@ -598,18 +3756,118 @@
}
+void EDA_3D_CANVAS::Draw3D_DrawSegmentMask( DRAWSEGMENT* segment,
+ int layer,
+ std::vector<CPolyPt>* e_data )
+{
+ double x, y, xf, yf;
+ double zpos = 0, w;
+
+ if( segment->GetLayer() != layer )
+ return;
+
+ if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
+ return;
+
+ w = segment->GetWidth() * g_Parm_3D_Visu.m_BoardScale;
+
+ x = segment->GetStart().x * g_Parm_3D_Visu.m_BoardScale;
+ y = segment->GetStart().y * g_Parm_3D_Visu.m_BoardScale;
+
+ xf = segment->GetEnd().x * g_Parm_3D_Visu.m_BoardScale;
+ yf = segment->GetEnd().y * g_Parm_3D_Visu.m_BoardScale;
+
+ {
+ {
+ switch( segment->GetShape() )
+ {
+ case S_ARC:
+ {
+ Draw3D_ArcSegmentMask( x, -y, xf, -yf, segment->GetAngle(), w, zpos, &p_data );
+ }
+
+ break;
+
+ case S_CIRCLE:
+ {
+ Draw3D_CircleSegmentMask( x, -y, xf, -yf, w, zpos, &p_data );
+ }
+
+ break;
+
+ case S_POLYGON:
+ {
+ // We must compute true coordinates from m_PolyPoints
+ // which are relative to module position and module orientation = 0
+ EDGE_MODULE* edge = (EDGE_MODULE*) segment;
+ std::vector<wxPoint> points = edge->GetPolyPoints();
+ MODULE* module = (MODULE*) edge->GetParent();
+
+ if( module == NULL )
+ {
+ break;
+ }
+
+ for( int ii = 0; ii < (int) points.size(); ii++ )
+ {
+ wxPoint& pt = points[ii];
+ RotatePoint( &pt.x, &pt.y, module->GetOrientation() );
+ pt += module->m_Pos;
+ e_data->push_back( CPolyPt( (int) pt.x, (int) pt.y ) );
+ }
+
+ e_data->push_back( CPolyPt( (int) MAGIC_CONT, 0 ) );
+ }
+
+ default:
+ {
+ Draw3D_FilledSegmentMask( x, -y, xf, -yf, w, zpos, &p_data, 1 );
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+
static double s_Text3DWidth, s_Text3DZPos;
static void Draw3dTextSegm( int x0, int y0, int xf, int yf )
{
- double startx = x0 * g_Parm_3D_Visu.m_BoardScale;
- double starty = y0 * g_Parm_3D_Visu.m_BoardScale;
- double endx = xf * g_Parm_3D_Visu.m_BoardScale;
- double endy = yf * g_Parm_3D_Visu.m_BoardScale;
+ double startx = x0 * g_Parm_3D_Visu.m_BoardScale;
+ double starty = y0 * g_Parm_3D_Visu.m_BoardScale;
+ double endx = xf * g_Parm_3D_Visu.m_BoardScale;
+ double endy = yf * g_Parm_3D_Visu.m_BoardScale;
Draw3D_FilledSegment( startx, -starty, endx, -endy, s_Text3DWidth, s_Text3DZPos );
}
+static void Draw3dTextSegmMask( int x0, int y0, int xf, int yf )
+{
+ double startx = x0 * g_Parm_3D_Visu.m_BoardScale;
+ double starty = y0 * g_Parm_3D_Visu.m_BoardScale;
+ double endx = xf * g_Parm_3D_Visu.m_BoardScale;
+ double endy = yf * g_Parm_3D_Visu.m_BoardScale;
+
+ Draw3D_FilledSegmentMask( startx, -starty, endx, -endy, s_Text3DWidth, s_Text3DZPos, gtess,
+ 1 );
+}
+
+
+static void Draw3dTextSegmMaskBuf( int x0, int y0, int xf, int yf )
+{
+ double startx = x0 * g_Parm_3D_Visu.m_BoardScale;
+ double starty = y0 * g_Parm_3D_Visu.m_BoardScale;
+ double endx = xf * g_Parm_3D_Visu.m_BoardScale;
+ double endy = yf * g_Parm_3D_Visu.m_BoardScale;
+
+ Draw3D_FilledSegmentMask( startx, -starty, endx, -endy, s_Text3DWidth, s_Text3DZPos, &p_data,
+ 1 );
+ p_data.push_back( CPolyPt( (int) MAGIC_CONT, 0 ) );
+}
+
+
void EDA_3D_CANVAS::Draw3D_DrawText( TEXTE_PCB* text )
{
int layer = text->GetLayer();
@@ -618,10 +3876,9 @@
return;
int color = g_ColorsSettings.GetLayerColor( layer );
-
- SetGLColor( color );
- s_Text3DZPos = g_Parm_3D_Visu.m_LayerZcoord[layer];
- s_Text3DWidth = text->GetThickness() * g_Parm_3D_Visu.m_BoardScale;
+ MySetGLColor( color, layer, 1 );
+ s_Text3DZPos = g_Parm_3D_Visu.m_LayerZcoord[layer];
+ s_Text3DWidth = text->GetThickness() * g_Parm_3D_Visu.m_BoardScale;
glNormal3f( 0.0, 0.0, Get3DLayerSide( layer ) );
wxSize size = text->m_Size;
@@ -630,9 +3887,9 @@
if( text->m_MultilineAllowed )
{
- wxPoint pos = text->m_Pos;
+ wxPoint pos = text->m_Pos;
wxArrayString* list = wxStringSplit( text->m_Text, '\n' );
- wxPoint offset;
+ wxPoint offset;
offset.y = text->GetInterline();
@@ -663,24 +3920,175 @@
}
+void EDA_3D_CANVAS::Draw3D_DrawTextMask( TEXTE_PCB* text, int layer, GLUtesselator* tess )
+{
+ if( text->GetLayer() != layer )
+ return;
+
+ if( !Get3DLayerEnable( layer ) )
+ return;
+
+ s_Text3DWidth = text->GetThickness() * g_Parm_3D_Visu.m_BoardScale;
+ wxSize size = text->m_Size;
+
+ if( text->m_Mirror )
+ NEGATE( size.x );
+
+ if( text->m_MultilineAllowed )
+ {
+ wxPoint pos = text->m_Pos;
+ wxArrayString* list = wxStringSplit( text->m_Text, '\n' );
+ wxPoint offset;
+
+ offset.y = text->GetInterline();
+
+ RotatePoint( &offset, text->GetOrientation() );
+
+ for( unsigned i = 0; i<list->Count(); i++ )
+ {
+ wxString txt = list->Item( i );
+
+ if( tess == NULL )
+ {
+ DrawGraphicText( NULL, NULL, pos, (EDA_COLOR_T) 0, // color,
+ txt, text->GetOrientation(), size,
+ text->m_HJustify, text->m_VJustify,
+ text->GetThickness(), text->m_Italic,
+ true, Draw3dTextSegmMaskBuf );
+ }
+ else
+ {
+ gtess = tess;
+ DrawGraphicText( NULL, NULL, pos, (EDA_COLOR_T) 0, // color,
+ txt, text->GetOrientation(), size,
+ text->m_HJustify, text->m_VJustify,
+ text->GetThickness(), text->m_Italic,
+ true, Draw3dTextSegmMask );
+ }
+
+ pos += offset;
+ }
+
+ delete list;
+ }
+ else
+ {
+ if( tess == NULL )
+ {
+ DrawGraphicText( NULL, NULL, text->m_Pos, (EDA_COLOR_T) 0, // color,
+ text->m_Text, text->GetOrientation(), size,
+ text->m_HJustify, text->m_VJustify,
+ text->GetThickness(), text->m_Italic,
+ true,
+ Draw3dTextSegmMaskBuf );
+ }
+ else
+ {
+ gtess = tess;
+ DrawGraphicText( NULL, NULL, text->m_Pos, (EDA_COLOR_T) 0, // color,
+ text->m_Text, text->GetOrientation(), size,
+ text->m_HJustify, text->m_VJustify,
+ text->GetThickness(), text->m_Italic,
+ true,
+ Draw3dTextSegmMask );
+ }
+ }
+}
+
+
+void EDA_3D_CANVAS::Draw3D_DrawText( TEXTE_MODULE* text, double rot )
+{
+ int layer = text->GetLayer();
+
+ int color = g_ColorsSettings.GetLayerColor( layer );
+
+ MySetGLColor( color, layer, 1 );
+ s_Text3DZPos = g_Parm_3D_Visu.m_LayerZcoord[layer];
+ s_Text3DWidth = text->GetThickness() * g_Parm_3D_Visu.m_BoardScale;
+ glNormal3f( 0.0, 0.0, Get3DLayerSide( layer ) );
+ wxSize size = text->m_Size;
+
+ if( text->m_Mirror )
+ NEGATE( size.x );
+
+ if( text->m_MultilineAllowed )
+ {
+ wxPoint pos = text->m_Pos;
+ wxArrayString* list = wxStringSplit( text->m_Text, '\n' );
+ wxPoint offset;
+ double newrot = text->GetOrientation() + rot;
+
+ while( newrot < -900.0 )
+ newrot += 1800.0;
+
+ while( newrot > 900.0 )
+ newrot -= 1800.0;
+
+ offset.y = text->GetInterline();
+
+ RotatePoint( &offset, text->GetOrientation() + rot );
+
+ for( unsigned i = 0; i<list->Count(); i++ )
+ {
+ wxString txt = list->Item( i );
+ DrawGraphicText( NULL, NULL, pos, (EDA_COLOR_T) color,
+ txt, newrot, size,
+ text->m_HJustify, text->m_VJustify,
+ text->GetThickness(), text->m_Italic,
+ true, Draw3dTextSegm );
+ pos += offset;
+ }
+
+ delete list;
+ }
+ else
+ {
+ double newrot = text->GetOrientation() + rot;
+
+ while( newrot < -900.0 )
+ newrot += 1800.0;
+
+ while( newrot > 900.0 )
+ newrot -= 1800.0;
+
+ DrawGraphicText( NULL, NULL, text->m_Pos, (EDA_COLOR_T) color,
+ text->m_Text, newrot, size,
+ text->m_HJustify, text->m_VJustify,
+ text->GetThickness(), text->m_Italic,
+ true,
+ Draw3dTextSegm );
+ }
+}
+
+
void MODULE::Draw3D( EDA_3D_CANVAS* glcanvas )
{
D_PAD* pad = m_Pads;
// Draw pads
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
- glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
-
- for( ; pad != NULL; pad = pad->Next() )
- {
- pad->Draw3D( glcanvas );
- }
+ glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
+
+
+ if( tmonly & 4 ) // TSP_20120605
+ {
+ }
+ else
+ {
+ for( ; pad != NULL; pad = pad->Next() )
+ {
+ pad->Draw3D( glcanvas );
+ }
+ }
+
+ if( tmonly & ~4 ) // TSP_20120605
+ return;
// Draw module shape: 3D shape if exists (or module outlines if not exists)
- S3D_MASTER* Struct3D = m_3D_Drawings;
- bool As3dShape = false;
+ S3D_MASTER* Struct3D = m_3D_Drawings;
+ bool As3dShape = false;
- if (g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_MODULE])
+ if( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_MODULE] )
{
glPushMatrix();
@@ -703,10 +4111,112 @@
for( ; Struct3D != NULL; Struct3D = Struct3D->Next() )
{
- if( !Struct3D->m_Shape3DName.IsEmpty() )
+ if( !Struct3D->m_Shape3DName.IsEmpty()
+ && ( ( GetAttributes() != MOD_VIRTUAL )
+ || ( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_VIRT] ) ) )
{
+ std::vector<S3D_Vertex> minmax;
+ Struct3D->m_MinPos.x = Struct3D->m_MinPos.y = Struct3D->m_MinPos.z = 1E30;
+ Struct3D->m_MaxPos.x = Struct3D->m_MaxPos.y = Struct3D->m_MaxPos.z = -1E30;
As3dShape = true;
- Struct3D->ReadData();
+ Struct3D->ReadData( &m_Reference->m_Text );
+ minmax.push_back( Struct3D->m_MinPos );
+ minmax.push_back( Struct3D->m_MaxPos );
+ double hi = minmax[1].y - minmax[0].y;
+ double hix = minmax[1].x - minmax[0].x;
+
+ if( hi < 0 )
+ hi = -hi;
+
+ if( hix < 0 )
+ hix = -hix;
+
+ if( do_values )
+ {
+ wxString txt = m_Value->m_Text;
+ wxPoint pos;
+ wxSize size;
+ pos.x = 0;
+ pos.y = 0;
+
+ if( hi > 0.5 )
+ hi = 0.5;
+
+ size.x = (int) (hi * 300);
+ size.y = (int) (hi * 300);
+ glPushMatrix();
+ glTranslatef( 0,
+ 0,
+ g_Parm_3D_Visu.m_BoardScale * minmax[1].z * 1000.0 - 0 *
+ g_Parm_3D_Visu.m_LayerZcoord[m_Layer] );
+ glColor4f( 0.2, 0.2, 0.2, 0.7 );
+ s_Text3DWidth = 100 * g_Parm_3D_Visu.m_BoardScale;
+ s_Text3DZPos = g_Parm_3D_Visu.m_BoardScale * 9;
+ glTranslatef(
+ g_Parm_3D_Visu.m_BoardScale * 1000 * (minmax[1].x + minmax[0].x) / 2,
+ g_Parm_3D_Visu.m_BoardScale * 1000 * (minmax[1].y + minmax[0].y) / 2,
+ 0 );
+ double o = m_Orient;
+ double ro = 0;
+
+ while( o < -900.0 )
+ {
+ o += 1800.0; ro += 180;
+ }
+
+ while( o > 900.0 )
+ {
+ o -= 1800.0; ro -= 180;
+ }
+
+ glRotatef( -ro, 0.0, 0.0, 1.0 );
+ double bscf = g_Parm_3D_Visu.m_BoardScale;
+ double scf = 1e-4;
+ double pw = scf * 1000 * fabs( minmax[1].x - minmax[0].x );
+ double ph = scf * 1000 * fabs( minmax[1].y - minmax[0].y );
+ double slen = NegableTextLength( txt );
+
+ if( slen > 0 )
+ {
+ size.x = (int) ( (10000 * pw) / (slen + 1) );
+
+ if( size.x < 100 )
+ size.x = 100;
+
+ if( size.x > 400 )
+ size.x = 400;
+
+ size.y = (size.x * 120) / 100;
+
+ if( size.y > 10000.0 * ph / 1.8 )
+ {
+ size.y = (int) ( (10000.0 * ph / 1.8) );
+ size.x = (size.y * 100) / 120;
+ }
+
+ pw = size.x * (slen) * bscf;
+ double ph = 1.5 * size.y * bscf;
+ {
+ glBegin( GL_POLYGON );
+ glVertex3f( pw / 2, ph / 2, s_Text3DZPos );
+ glVertex3f( pw / 2, -ph / 2, s_Text3DZPos );
+ glVertex3f( -pw / 2, -ph / 2, s_Text3DZPos );
+ glVertex3f( -pw / 2, ph / 2, s_Text3DZPos );
+ glEnd();
+ }
+ glColor3f( 0.8, 0.8, 0.8 );
+ glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
+ s_Text3DZPos = g_Parm_3D_Visu.m_BoardScale * 10;
+ s_Text3DWidth = 20 * g_Parm_3D_Visu.m_BoardScale;
+ DrawGraphicText( NULL, NULL, pos, RED,
+ txt, 0, size,
+ GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER,
+ 20, 0, true,
+ Draw3dTextSegm );
+ }
+
+ glPopMatrix();
+ }
}
}
@@ -714,28 +4224,58 @@
}
EDA_ITEM* Struct = m_Drawings;
- glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
+ glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
for( ; Struct != NULL; Struct = Struct->Next() )
{
- switch( Struct->Type() )
- {
- case PCB_MODULE_TEXT_T:
- break;
-
- case PCB_MODULE_EDGE_T:
- {
- EDGE_MODULE* edge = (EDGE_MODULE*) Struct;
-
- // Draw module edges when no 3d shape exists.
- // Always draw pcb edges.
- if( !As3dShape || edge->GetLayer() == EDGE_N )
- edge->Draw3D( glcanvas );
- }
- break;
-
- default:
- break;
+ unsigned int tl = ( (BOARD_ITEM*) Struct )->GetLayer();
+
+ if( tl == 0 )
+ continue; // TSP_20120606
+
+ if( tl == 15 )
+ continue; // TSP_20120606
+
+ if( tl == SILKSCREEN_N_FRONT )
+ continue; // TSP_20120606
+
+ if( tl == SILKSCREEN_N_BACK )
+ continue; // TSP_20120606
+
+ if( (tl == SOLDERMASK_N_BACK) && g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] )
+ continue; // TSP_20120606
+
+ if( (tl == SOLDERMASK_N_FRONT) && g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] )
+ continue; // TSP_20120606
+
+ if( ( (tl == DRAW_N) && g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_DRAWINGS] )
+ || ( (tl == COMMENT_N) && g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_COMMENTS] )
+ || ( (tl == ECO1_N) && g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ECO1] )
+ || ( (tl == ECO2_N) && g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ECO2] )
+ )
+ {
+ switch( Struct->Type() )
+ {
+ case PCB_MODULE_TEXT_T:
+ glcanvas->Draw3D_DrawText( (TEXTE_PCB*) Struct );
+ break;
+
+ case PCB_MODULE_EDGE_T:
+ {
+ EDGE_MODULE* edge = (EDGE_MODULE*) Struct;
+
+ // Draw module edges when no 3d shape exists.
+ // Always draw pcb edges.
+ /* if( !As3dShape || edge->GetLayer() == EDGE_N ) */
+ {
+ edge->Draw3D( glcanvas );
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
}
}
}
@@ -744,23 +4284,23 @@
void EDGE_MODULE::Draw3D( EDA_3D_CANVAS* glcanvas )
{
wxString s;
- int dx, dy;
- double x, y, fx, fy, w, zpos;
+ int dx, dy;
+ double x, y, fx, fy, w, zpos;
if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( m_Layer ) == false )
return;
int color = g_ColorsSettings.GetLayerColor( m_Layer );
- SetGLColor( color );
+ MySetGLColor( color, m_Layer, 1 );
- dx = m_End.x;
- dy = m_End.y;
- w = m_Width * g_Parm_3D_Visu.m_BoardScale;
- x = m_Start.x * g_Parm_3D_Visu.m_BoardScale;
- y = m_Start.y * g_Parm_3D_Visu.m_BoardScale;
- fx = dx * g_Parm_3D_Visu.m_BoardScale;
- fy = dy * g_Parm_3D_Visu.m_BoardScale;
+ dx = m_End.x;
+ dy = m_End.y;
+ w = m_Width * g_Parm_3D_Visu.m_BoardScale;
+ x = m_Start.x * g_Parm_3D_Visu.m_BoardScale;
+ y = m_Start.y * g_Parm_3D_Visu.m_BoardScale;
+ fx = dx * g_Parm_3D_Visu.m_BoardScale;
+ fy = dy * g_Parm_3D_Visu.m_BoardScale;
if( m_Layer == EDGE_N )
@@ -785,6 +4325,56 @@
break;
case S_POLYGON:
+ {
+ // We must compute true coordinates from m_PolyPoints
+ // which are relative to module position and module orientation = 0
+ std::vector<wxPoint> points = m_PolyPoints;
+ MODULE* module = (MODULE*) m_Parent;
+
+ if( module == NULL )
+ break;
+
+ for( unsigned ii = 0; ii < points.size(); ii++ )
+ {
+ wxPoint& pt = points[ii];
+
+ RotatePoint( &pt.x, &pt.y, module->GetOrientation() );
+ pt += module->m_Pos;
+ }
+
+ glcanvas->Draw3D_Polygon( points, zpos );
+ }
+ break;
+
+ default:
+ s.Printf( wxT( "Error: Shape nr %d not implemented!\n" ), m_Shape );
+ D( printf( "%s", TO_UTF8( s ) ); )
+ break;
+ }
+ }
+ }
+ else
+ {
+ glNormal3f( 0.0,
+ 0.0,
+ ( (m_Layer == LAYER_N_BACK) || (m_Layer == SILKSCREEN_N_BACK) ) ? -1.0 : 1.0 );
+ zpos = g_Parm_3D_Visu.m_LayerZcoord[m_Layer];
+
+ switch( m_Shape )
+ {
+ case S_SEGMENT:
+ Draw3D_FilledSegment( x, -y, fx, -fy, w, zpos );
+ break;
+
+ case S_CIRCLE:
+ Draw3D_CircleSegment( x, -y, fx, -fy, w, zpos );
+ break;
+
+ case S_ARC:
+ Draw3D_ArcSegment( x, -y, fx, -fy, (double) m_Angle, w, zpos );
+ break;
+
+ case S_POLYGON:
{
// We must compute true coordinates from m_PolyPoints
// which are relative to module position and module orientation = 0
@@ -806,54 +4396,6 @@
}
break;
- default:
- s.Printf( wxT( "Error: Shape nr %d not implemented!\n" ), m_Shape );
- D( printf( "%s", TO_UTF8( s ) ); )
- break;
- }
- }
- }
- else
- {
- glNormal3f( 0.0, 0.0, (m_Layer == LAYER_N_BACK) ? -1.0 : 1.0 );
- zpos = g_Parm_3D_Visu.m_LayerZcoord[m_Layer];
-
- switch( m_Shape )
- {
- case S_SEGMENT:
- Draw3D_FilledSegment( x, -y, fx, -fy, w, zpos );
- break;
-
- case S_CIRCLE:
- Draw3D_CircleSegment( x, -y, fx, -fy, w, zpos );
- break;
-
- case S_ARC:
- Draw3D_ArcSegment( x, -y, fx, -fy, (double) m_Angle, w, zpos );
- break;
-
- case S_POLYGON:
- {
- // We must compute true coordinates from m_PolyPoints
- // which are relative to module position and module orientation = 0
- std::vector<wxPoint> points = m_PolyPoints;
- MODULE* module = (MODULE*) m_Parent;
-
- if( module == NULL )
- break;
-
- for( unsigned ii = 0; ii < points.size(); ii++ )
- {
- wxPoint& pt = points[ii];
-
- RotatePoint( &pt.x, &pt.y, module->GetOrientation() );
- pt += module->m_Pos;
- }
-
- glcanvas->Draw3D_Polygon( points, zpos );
- }
- break;
-
default:
s.Printf( wxT( "Error: Shape nr %d not implemented!\n" ), m_Shape );
D( printf( "%s", TO_UTF8( s ) ); )
@@ -871,99 +4413,269 @@
dx, dx0, dy, dy0,
delta_cx, delta_cy,
xc, yc;
- int angle;
- double scale;
- double zpos;
+ int angle;
+ double scale;
+ double zpos = 0;
wxPoint shape_pos;
- double x, y, r, w, hole, holeX, holeY;
- double drillx, drilly;
- bool Oncu, Oncmp, Both;
- int color;
+ double w, hole, holeX, holeY;
+ double drillx, drilly;
+ bool Oncu, Oncmp, Both;
+ int color;
+ double rm = GetSolderMaskMargin();
+ wxSize rp = GetSolderPasteMargin();
+ double offX, offY;
- scale = g_Parm_3D_Visu.m_BoardScale;
- holeX = (double) m_Drill.x * scale / 2;
- holeY = (double) m_Drill.y * scale / 2;
- hole = fmin( holeX, holeY );
+ scale = g_Parm_3D_Visu.m_BoardScale;
+ holeX = (double) m_Drill.x * scale / 2;
+ holeY = (double) m_Drill.y * scale / 2;
+ offX = (double) m_Offset.x * scale;
+ offY = (double) m_Offset.y * scale;
+ hole = fmin( holeX, holeY );
// Calculate the center of the pad.
- shape_pos = ReturnShapePos();
+ shape_pos = m_Pos;
ux0 = shape_pos.x;
uy0 = shape_pos.y;
xc = ux0;
yc = uy0;
- dx = dx0 = m_Size.x >> 1;
- dy = dy0 = m_Size.y >> 1;
-
- angle = m_Orient;
- drillx = m_Pos.x * scale;
- drilly = m_Pos.y * scale;
-
- // Draw the pad hole (TODO: draw OBLONG hole)
+ dx = dx0 = m_Size.x / 2;
+ dy = dy0 = m_Size.y / 2;
+
+ angle = m_Orient;
+ drillx = m_Pos.x * scale;
+ drilly = m_Pos.y * scale;
+
+#define ZLO ( 9 - ( (layer & 6) >> 1 ) )
+
+ if( (tmonly & 1) == 1 )
+ {
+ nlmax = g_Parm_3D_Visu.m_Layers - 1;
+ Oncu = (m_layerMask & LAYER_BACK) ? true : false;
+ Oncmp = (m_layerMask & LAYER_FRONT) ? true : false;
+ Both = Oncu && Oncmp;
+
+ switch( m_PadShape & 0x7F )
+ {
+ case PAD_CIRCLE:
+ case PAD_OVAL:
+ rm *= scale;
+
+ if( dx > dy ) // Horizontal ellipse
+ {
+ delta_cx = dx - dy;
+ delta_cy = 0;
+ w = m_Size.y * scale;
+ }
+ else // Vertical ellipse
+ {
+ delta_cx = 0;
+ delta_cy = dy - dx;
+ w = m_Size.x * scale;
+ }
+
+ RotatePoint( &delta_cx, &delta_cy, angle );
+
+ {
+ double ox, oy, fx, fy;
+ ox = (double) ( ux0 + delta_cx ) * scale;
+ oy = (double) ( uy0 + delta_cy ) * scale;
+ fx = (double) ( ux0 - delta_cx ) * scale;
+ fy = (double) ( uy0 - delta_cy ) * scale;
+
+ layer = (tmonly & 2) ? SOLDERMASK_N_BACK : SOLDERMASK_N_FRONT;
+
+ if( ( (1 << layer) & m_layerMask ) != 0 )
+ {
+ Draw3D_FilledSegmentWithHoleMask( ox,
+ -oy,
+ fx,
+ -fy,
+ w + rm,
+ drillx,
+ -drilly,
+ hole,
+ zpos,
+ offX,
+ offY, angle );
+ }
+ }
+ break;
+
+ case PAD_RECT:
+ case PAD_TRAPEZOID:
+ {
+ wxPoint coord[5];
+ wxRealPoint fcoord[8], f_hole_coord[8];
+ layer = (tmonly & 2) ? SOLDERMASK_N_BACK : SOLDERMASK_N_FRONT;
+
+ if( ( (1 << layer) & m_layerMask ) != 0 )
+ {
+ wxSize lrp;
+ lrp.x = rm;
+ lrp.y = rm;
+ BuildPadPolygon( coord, lrp, angle );
+
+ RotatePoint( &offX, &offY, angle );
+
+ for( ii = 0; ii < 4; ii++ )
+ {
+ coord[ii].x += ux0 + offX / scale; // TSP_20120604
+ coord[ii].y += uy0 + offY / scale;
+ ll = ii * 2;
+ fcoord[ll].x = coord[ii].x * scale;
+ fcoord[ll].y = coord[ii].y * scale;
+ }
+
+ for( ii = 0; ii < 7; ii += 2 )
+ {
+ ll = ll + 2;
+
+ if( ll > 7 )
+ ll -= 8;
+
+ fcoord[ii + 1].x = (fcoord[ii].x + fcoord[ll].x) / 2;
+ fcoord[ii + 1].y = (fcoord[ii].y + fcoord[ll].y) / 2;
+ }
+
+ for( ii = 0; ii < 8; ii++ )
+ {
+ f_hole_coord[ii].x = -hole * 0.707;
+ f_hole_coord[ii].y = hole * 0.707;
+ RotatePoint( &f_hole_coord[ii].x, &f_hole_coord[ii].y, angle -
+ (ii * 450) );
+ f_hole_coord[ii].x += drillx;
+ f_hole_coord[ii].y += drilly;
+ }
+
+ for( ii = 0; ii < 4; ii++ )
+ {
+ p_data.push_back( CPolyPt( (int) (coord[ii].x), (int) (coord[ii].y) ) );
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return;
+ }
+ else if( tmonly == 2 )
+ {
+ // Draw the pad hole
+ if( holeX && holeY )
+ {
+ if( holeX == holeY )
+ {
+ Draw3D_FilledCylinderMask( drillx, -drilly, hole,
+ g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_FRONT], 0.0 );
+ }
+ else
+ {
+ double ldx, ldy;
+
+ if( holeX > holeY ) // Horizontal oval
+ {
+ ldx = holeX - holeY;
+ ldy = 0;
+ w = m_Size.y * scale;
+ }
+ else // Vertical oval
+ {
+ ldx = 0;
+ ldy = holeY - holeX;
+ w = m_Size.x * scale;
+ }
+
+ RotatePoint( &ldx, &ldy, angle );
+
+ {
+ double ox, oy, fx, fy;
+ ox = ( (double) ( ux0 ) ) * scale + ldx;
+ oy = ( (double) ( uy0 ) ) * scale + ldy;
+ fx = ( (double) ( ux0 ) ) * scale - ldx;
+ fy = ( (double) ( uy0 ) ) * scale - ldy;
+
+ double height = g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_FRONT];
+ Draw3D_FilledOblongMask( ox, -oy, fx, -fy, drillx, -drilly, hole, height,
+ 0.0 );
+ }
+ }
+ }
+
+ return;
+ }
+
+ // Draw the pad hole
if( holeX && holeY )
{
- SetGLColor( DARKGRAY );
- Draw3D_FilledCylinder( drillx, -drilly, hole,
- g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_FRONT], 0.0 );
+ if( (GetAttribute() == PAD_STANDARD) )
+ {
+ MySetGLColor( DARKGRAY, 0, 1 );
+
+ if( holeX == holeY )
+ {
+ Draw3D_FilledCylinder( drillx, -drilly, hole,
+ g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_FRONT], 0.0 );
+ }
+ else
+ {
+ double ldx, ldy;
+
+ if( holeX > holeY ) // Horizontal oval
+ {
+ ldx = holeX - holeY;
+ ldy = 0;
+ w = m_Size.y * scale;
+ }
+ else // Vertical oval
+ {
+ ldx = 0;
+ ldy = holeY - holeX;
+ w = m_Size.x * scale;
+ }
+
+ RotatePoint( &ldx, &ldy, angle );
+ ldx /= scale;
+ ldy /= scale;
+
+ {
+ double ox, oy, fx, fy;
+ ox = (double) ( (double) ux0 + ldx ) * scale;
+ oy = (double) ( (double) uy0 + ldy ) * scale;
+ fx = (double) ( (double) ux0 - ldx ) * scale;
+ fy = (double) ( (double) uy0 - ldy ) * scale;
+
+ double height = g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_FRONT];
+ Draw3D_FilledOblong( ox, -oy, fx, -fy, drillx, -drilly, hole, height, 0.0 );
+ }
+ }
+ }
}
- glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
- nlmax = g_Parm_3D_Visu.m_Layers - 1;
- Oncu = (m_layerMask & LAYER_BACK) ? true : false;
- Oncmp = (m_layerMask & LAYER_FRONT) ? true : false;
- Both = Oncu && Oncmp;
+ glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
+ nlmax = g_Parm_3D_Visu.m_Layers - 1;
+ Oncu = (m_layerMask & LAYER_BACK) ? true : false;
+ Oncmp = (m_layerMask & LAYER_FRONT) ? true : false;
+ Both = Oncu && Oncmp;
switch( m_PadShape & 0x7F )
{
case PAD_CIRCLE:
- x = xc * scale;
- y = yc * scale;
- r = (double) dx * scale;
-
- for( layer = FIRST_COPPER_LAYER; layer <= LAST_COPPER_LAYER; layer++ )
- {
- if( layer && (layer == nlmax) )
- layer = LAYER_N_FRONT;
-
- if( (layer == LAYER_N_FRONT) && !Oncmp )
- continue;
-
- if( (layer == LAYER_N_BACK) && !Oncu )
- continue;
-
- if( (layer > FIRST_COPPER_LAYER) && (layer < LAST_COPPER_LAYER) && !Both )
- continue;
-
- color = g_ColorsSettings.GetLayerColor( layer );
-
- if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
- continue;
-
- SetGLColor( color );
- glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 );
- zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
-
- if( layer == LAYER_N_BACK )
- zpos = zpos - 5 * g_Parm_3D_Visu.m_BoardScale;
- else
- zpos = zpos + 5 * g_Parm_3D_Visu.m_BoardScale;
-
- Draw3D_FilledCircle( x, -y, r, hole, zpos );
- }
-
- break;
-
case PAD_OVAL:
- if( dx > dy ) // Horizontal ellipse
+
+ if( dx > dy ) // Horizontal ellipse
{
- delta_cx = dx - dy;
- delta_cy = 0;
+ delta_cx = dx - dy;
+ delta_cy = 0;
w = m_Size.y * scale;
}
- else // Vertical ellipse
+ else // Vertical ellipse
{
- delta_cx = 0;
- delta_cy = dy - dx;
+ delta_cx = 0;
+ delta_cy = dy - dx;
w = m_Size.x * scale;
}
@@ -971,40 +4683,61 @@
{
double ox, oy, fx, fy;
- ox = (double) ( ux0 + delta_cx ) * scale;
- oy = (double) ( uy0 + delta_cy ) * scale;
- fx = (double) ( ux0 - delta_cx ) * scale;
- fy = (double) ( uy0 - delta_cy ) * scale;
+ ox = (double) ( ux0 + delta_cx ) * scale;
+ oy = (double) ( uy0 + delta_cy ) * scale;
+ fx = (double) ( ux0 - delta_cx ) * scale;
+ fy = (double) ( uy0 - delta_cy ) * scale;
- for( layer = FIRST_COPPER_LAYER; layer <= LAST_COPPER_LAYER; layer++ )
+ for( layer = FIRST_NO_COPPER_LAYER; layer <= SILKSCREEN_N_FRONT; layer++ )
{
- if( layer && (layer == nlmax) )
- layer = LAYER_N_FRONT;
-
- if( (layer == LAYER_N_FRONT) && !Oncmp )
- continue;
-
- if( (layer == LAYER_N_BACK) && !Oncu )
- continue;
-
- if( (layer > FIRST_COPPER_LAYER) && (layer < LAST_COPPER_LAYER) && !Both )
+ if( ( (1 << layer) & m_layerMask ) == 0 )
+ continue;
+
+ if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
continue;
color = g_ColorsSettings.GetLayerColor( layer );
- glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 );
-
- if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
- continue;
-
- SetGLColor( color );
+ glNormal3f( 0.0, 0.0, (layer & 1) ? 1.0 : -1.0 );
+
+ MySetGLColor( color, layer, 0.8 );
zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
- if( layer == LAYER_N_BACK )
- zpos = zpos - 5 * g_Parm_3D_Visu.m_BoardScale;
+ if( layer & 1 )
+ zpos = zpos + ZLO * g_Parm_3D_Visu.m_BoardScale;
else
- zpos = zpos + 5 * g_Parm_3D_Visu.m_BoardScale;
+ zpos = zpos - ZLO * g_Parm_3D_Visu.m_BoardScale;
- Draw3D_FilledSegmentWithHole( ox, -oy, fx, -fy, w, drillx, -drilly, hole, zpos );
+ if( (layer == SOLDERPASTE_N_BACK) || (layer == SOLDERPASTE_N_FRONT) )
+ {
+ Draw3D_FilledSegmentWithHole( ox,
+ -oy,
+ fx,
+ -fy,
+ w + (double) rp.x * scale,
+ drillx,
+ -drilly,
+ 0,
+ zpos,
+ offX,
+ offY, 0, 0, dx, dy, angle );
+ }
+ else if( (layer == SILKSCREEN_N_BACK) || (layer == SILKSCREEN_N_FRONT) )
+ {
+ }
+ else
+ {
+ Draw3D_FilledSegmentWithHole( ox,
+ -oy,
+ fx,
+ -fy,
+ w,
+ drillx,
+ -drilly,
+ hole,
+ zpos,
+ offX,
+ offY, holeX, holeY, dx, dy, angle );
+ }
}
}
@@ -1012,82 +4745,56 @@
case PAD_RECT:
case PAD_TRAPEZOID:
- {
- wxPoint coord[5];
- wxRealPoint fcoord[8], f_hole_coord[8];
- BuildPadPolygon( coord, wxSize(0,0), angle );
-
- for( ii = 0; ii < 4; ii++ )
- {
- coord[ii].x += ux0;
- coord[ii].y += uy0;
- ll = ii * 2;
- fcoord[ll].x = coord[ii].x *scale;
- fcoord[ll].y = coord[ii].y *scale;
- }
-
- for( ii = 0; ii < 7; ii += 2 )
- {
- ll = ii + 2;
-
- if( ll > 7 )
- ll -= 8;
-
- fcoord[ii + 1].x = (fcoord[ii].x + fcoord[ll].x) / 2;
- fcoord[ii + 1].y = (fcoord[ii].y + fcoord[ll].y) / 2;
- }
-
- for( ii = 0; ii < 8; ii++ )
- {
- f_hole_coord[ii].x = -hole * 0.707;
- f_hole_coord[ii].y = hole * 0.707;
- RotatePoint( &f_hole_coord[ii].x, &f_hole_coord[ii].y, angle - (ii * 450) );
- f_hole_coord[ii].x += drillx;
- f_hole_coord[ii].y += drilly;
- }
-
- for( layer = FIRST_COPPER_LAYER; layer <= LAST_COPPER_LAYER; layer++ )
- {
- if( layer && (layer == nlmax) )
- layer = LAYER_N_FRONT;
-
- if( (layer == LAYER_N_FRONT) && !Oncmp )
- continue;
-
- if( (layer == LAYER_N_BACK) && !Oncu )
- continue;
-
- if( (layer > FIRST_COPPER_LAYER) && (layer < LAST_COPPER_LAYER) && !Both )
- continue;
-
- color = g_ColorsSettings.GetLayerColor( layer );
- glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 );
-
- if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
- continue;
-
- SetGLColor( color );
- zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
-
- if( layer == LAYER_N_BACK )
- zpos = zpos - 5 * g_Parm_3D_Visu.m_BoardScale;
- else
- zpos = zpos + 5 * g_Parm_3D_Visu.m_BoardScale;
-
- glBegin( GL_QUAD_STRIP );
-
- for( ii = 0; ii < 8; ii++ )
+ {
+ wxPoint coord[5];
+ BuildPadPolygon( coord, wxSize( 0, 0 ), angle );
+ RotatePoint( &offX, &offY, angle );
+
+ for( layer = FIRST_NO_COPPER_LAYER; layer <= SILKSCREEN_N_FRONT; layer++ )
{
- glVertex3f( f_hole_coord[ii].x, -f_hole_coord[ii].y, zpos );
- glVertex3f( fcoord[ii].x, -fcoord[ii].y, zpos );
+ if( ( (1 << layer) & m_layerMask ) == 0 )
+ continue;
+
+ color = g_ColorsSettings.GetLayerColor( layer );
+
+ glNormal3f( 0.0, 0.0, (layer & 1) ? 1.0 : -1.0 );
+
+ if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
+ continue;
+
+ {
+ wxSize lrp;
+
+ if( (layer == SOLDERPASTE_N_BACK) || (layer == SOLDERPASTE_N_FRONT) )
+ {
+ lrp = rp;
+ }
+ else
+ {
+ lrp.x = 0;
+ lrp.y = 0;
+ }
+
+ BuildPadPolygon( coord, lrp, angle );
+ }
+ MySetGLColor( color, layer, 0.8 );
+ zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
+
+ if( layer & 1 )
+ zpos = zpos + ZLO * g_Parm_3D_Visu.m_BoardScale;
+ else
+ zpos = zpos - ZLO * g_Parm_3D_Visu.m_BoardScale;
+
+ if( (layer == SILKSCREEN_N_BACK) || (layer == SILKSCREEN_N_FRONT) )
+ {
+ }
+ else
+ {
+ Draw3D_FilledPolyWithHole( coord, 5, ux0, uy0, offX, offY, 0, 0, zpos, angle );
+ }
}
-
- glVertex3f( f_hole_coord[0].x, -f_hole_coord[0].y, zpos );
- glVertex3f( fcoord[0].x, -fcoord[0].y, zpos );
- glEnd();
}
- }
- break;
+ break;
default:
break;
@@ -1095,35 +4802,49 @@
}
-void SetGLColor( int color )
+void MySetGLColor( int color, int layer, double alpha )
{
- double red, green, blue;
+ double red, green, blue;
StructColors colordata = ColorRefs[color & MASKCOLOR];
- red = colordata.m_Red / 255.0;
- blue = colordata.m_Blue / 255.0;
- green = colordata.m_Green / 255.0;
- glColor3f( red, green, blue );
+ if( layer < 0 )
+ {
+ red = colordata.m_Red / 255.0;
+ blue = colordata.m_Blue / 255.0;
+ green = colordata.m_Green / 255.0;
+ glColor4f( red, green, blue, 1 );
+ }
+ else if( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] && (layer < 16) )
+ {
+ glColor3f( 0.6, 0.55, 0.2 );
+ }
+ else
+ {
+ red = colordata.m_Red / 255.0;
+ blue = colordata.m_Blue / 255.0;
+ green = colordata.m_Green / 255.0;
+ glColor4f( red, green, blue, (alpha < 0) ? 0.9 : alpha );
+ }
}
static void Draw3D_FilledCircle( double posx, double posy,
- double rayon, double hole, double zpos )
+ double radius, double holeradius, double zpos )
{
- int ii, slice = 16;
+ int ii, slice = C_SLICE * 2;
double x, y;
glBegin( GL_QUAD_STRIP );
for( ii = 0; ii <= slice; ii++ )
{
- x = hole;
- y = 0.0;
- RotatePoint( &x, &y, ii * 225 );
+ x = holeradius;
+ y = 0.0;
+ RotatePoint( &x, &y, ii * _SEG( slice ) );
glVertex3f( x + posx, y + posy, zpos );
- x = rayon;
- y = 0.0;
- RotatePoint( &x, &y, ii * 225 );
+ x = radius;
+ y = 0.0;
+ RotatePoint( &x, &y, ii * _SEG( slice ) );
glVertex3f( x + posx, y + posy, zpos );
}
@@ -1131,29 +4852,29 @@
}
-static void Draw3D_FilledCylinder( double posx, double posy, double rayon,
+static void Draw3D_FilledCylinder( double posx, double posy, double radius,
double height, double zpos )
{
- int ii;
- double x, y;
-
-#define NB_SEGM 12
- std::vector< S3D_Vertex > coords;
+ int ii;
+ double x, y;
+
+ std::vector<S3D_Vertex> coords;
+
coords.resize( 4 );
- double tmp = DataScale3D;
+ double tmp = DataScale3D;
- DataScale3D = 1.0; // Coordinate is already in range for Set_Object_Data();
- coords[0].x = coords[1].x = posx + rayon;
+ DataScale3D = 1.0; // Coordinate is already in range for Set_Object_Data();
+ coords[0].x = coords[1].x = posx + radius;
coords[0].y = coords[1].y = posy;
coords[0].z = coords[3].z = zpos;
coords[1].z = coords[2].z = zpos + height;
- for( ii = 0; ii <= NB_SEGM; ii++ )
+ for( ii = 1; ii <= C_SLICE * 2; ii++ )
{
- x = rayon;
- y = 0.0;
- RotatePoint( &x, &y, ii * (3600 / NB_SEGM) );
+ x = radius;
+ y = 0.0;
+ RotatePoint( &x, &y, ii * _SEG( C_SLICE * 2 ) );
coords[2].x = coords[3].x = posx + x;
coords[2].y = coords[3].y = posy + y;
Set_Object_Data( coords );
@@ -1163,8 +4884,156 @@
coords[1].y = coords[3].y;
}
- glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
- DataScale3D = tmp;
+ glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
+ DataScale3D = tmp;
+}
+
+
+static void Draw3D_FilledOblong( double startx, double starty,
+ double endx, double endy,
+ double holex,
+ double holey, double holeradius,
+ double height, double zpos )
+{
+ double ddx, ddy, dx, dy;
+ double angle;
+ std::vector<S3D_Vertex> coords;
+
+ coords.resize( 4 );
+
+ double tmp = DataScale3D;
+
+ DataScale3D = 1.0; // Coordinate is already in range for Set_Object_Data();
+
+ dx = endx - startx;
+ dy = endy - starty;
+ angle = ATAN2( dy, dx );
+ dx = 0;
+ dy = holeradius;
+ RotatePoint( &dx, &dy, angle );
+ coords[0].x = coords[1].x = startx + dx;
+ coords[0].y = coords[1].y = starty - dy;
+ coords[2].x = coords[3].x = endx + dx;
+ coords[2].y = coords[3].y = endy - dy;
+ coords[0].z = coords[3].z = zpos;
+ coords[1].z = coords[2].z = zpos + height;
+ Set_Object_Data( coords );
+
+ for( int ii = 1; ii <= C_SLICE; ii++ )
+ {
+ ddx = dx;
+ ddy = -dy;
+ RotatePoint( &ddx, &ddy, -ii * _SEG2( C_SLICE ) );
+ coords[0].x = coords[2].x;
+ coords[0].y = coords[2].y;
+ coords[1].x = coords[3].x;
+ coords[1].y = coords[3].y;
+ coords[2].x = coords[3].x = endx + ddx;
+ coords[2].y = coords[3].y = endy + ddy;
+ Set_Object_Data( coords );
+ }
+
+ coords[0].x = coords[1].x = endx - dx;
+ coords[0].y = coords[1].y = endy + dy;
+ coords[2].x = coords[3].x = startx - dx;
+ coords[2].y = coords[3].y = starty + dy;
+ coords[0].z = coords[3].z = zpos;
+ coords[1].z = coords[2].z = zpos + height;
+ Set_Object_Data( coords );
+
+ for( int ii = 1; ii <= C_SLICE; ii++ )
+ {
+ ddx = -dx;
+ ddy = dy;
+ RotatePoint( &ddx, &ddy, -ii * _SEG2( C_SLICE ) );
+ coords[0].x = coords[2].x;
+ coords[0].y = coords[2].y;
+ coords[1].x = coords[3].x;
+ coords[1].y = coords[3].y;
+ coords[2].x = coords[3].x = startx + ddx;
+ coords[2].y = coords[3].y = starty + ddy;
+ Set_Object_Data( coords );
+ }
+
+ // Calculate the coordinates of the segment assumed horizontal.
+ // Then turn the strips of the desired angle.
+
+ glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
+ DataScale3D = tmp;
+}
+
+
+static void Draw3D_FilledOblongMask( double startx, double starty,
+ double endx, double endy,
+ double holex,
+ double holey, double holeradius,
+ double height, double zpos )
+{
+ double ddx, ddy, dx, dy;
+ int spii = p_data.size();
+ double angle;
+
+ dx = endx - startx;
+ dy = endy - starty;
+ angle = ATAN2( dy, dx );
+ dx = 0;
+ dy = holeradius;
+ RotatePoint( &dx, &dy, angle );
+
+ for( int ii = 0; ii <= C_SLICE; ii++ )
+ {
+ ddx = dx;
+ ddy = -dy;
+ RotatePoint( &ddx, &ddy, -ii * _SEG2( C_SLICE ) );
+ p_data.push_back( CPolyPt( (int) ( (endx + ddx) / g_Parm_3D_Visu.m_BoardScale ),
+ (int) (-(endy + ddy) / g_Parm_3D_Visu.m_BoardScale) ) );
+ }
+
+ for( int ii = 0; ii <= C_SLICE; ii++ )
+ {
+ ddx = -dx;
+ ddy = dy;
+ RotatePoint( &ddx, &ddy, -ii * _SEG2( C_SLICE ) );
+ p_data.push_back( CPolyPt( (int) ( (startx + ddx) / g_Parm_3D_Visu.m_BoardScale ),
+ (int) (-(starty + ddy) / g_Parm_3D_Visu.m_BoardScale) ) );
+ }
+
+ for( int ii = 0; ii < ( (int) p_data.size() - spii ) / 2; ii++ )
+ {
+ CPolyPt h = p_data[spii + ii];
+ p_data[spii + ii] = p_data[p_data.size() - ii - 1];
+ p_data[p_data.size() - ii - 1] = h;
+ }
+}
+
+
+static void Draw3D_FilledCylinderMask( double posx, double posy, double radius,
+ double height, double zpos )
+{
+ int ii, slice = C_SLICE * 2;
+ double x, y;
+
+ for( ii = 0; ii <= slice; ii++ )
+ {
+ x = radius;
+ y = 0.0;
+ RotatePoint( &x, &y, ii * _SEG( slice ) );
+ x = (x + posx) / g_Parm_3D_Visu.m_BoardScale;
+ y = -( (y + posy) / g_Parm_3D_Visu.m_BoardScale );
+ p_data.push_back( CPolyPt( (int) x, (int) y ) );
+ }
+}
+
+
+static void Draw3D_Mask( double startx, double starty, double endx,
+ double endy, double width, double zpos )
+{
+ startx /= g_Parm_3D_Visu.m_BoardScale;
+ starty /= g_Parm_3D_Visu.m_BoardScale;
+ endx /= g_Parm_3D_Visu.m_BoardScale;
+ endy /= g_Parm_3D_Visu.m_BoardScale;
+ e_data.push_back( CPolyPt( (int) startx, (int) starty ) );
+ e_data.push_back( CPolyPt( (int) endx, (int) endy ) );
}
@@ -1173,13 +5042,13 @@
double endy, double width, double zpos )
{
double dx, dy, x, y, firstx = 0, firsty = 0;
- int ii, angle;
+ double angle;
// Calculate the coordinates of the segment assumed horizontal.
// Then turn the strips of the desired angle.
- dx = endx - startx;
- dy = endy - starty;
- angle = (int) ( ( atan2( dy, dx ) * 1800 / M_PI ) + 0.5 );
+ dx = endx - startx;
+ dy = endy - starty;
+ angle = ATAN2( dy, dx );
RotatePoint( &dx, &dy, angle );
width /= 2;
@@ -1187,28 +5056,28 @@
glBegin( GL_POLYGON );
// Trace the flare to right (1st half polygon at the end of the segment)
- for( ii = 0; ii <= 8; ii++ )
+ for( int ii = 0; ii <= C_SLICE; ii++ )
{
- x = 0.0;
- y = -width;
- RotatePoint( &x, &y, -ii * 225 );
+ x = 0.0;
+ y = -width;
+ RotatePoint( &x, &y, -ii * _SEG2( C_SLICE ) );
x += dx;
RotatePoint( &x, &y, -angle );
glVertex3f( startx + x, starty + y, zpos );
if( ii == 0 )
{
- firstx = startx + x;
- firsty = starty + y;
+ firstx = startx + x;
+ firsty = starty + y;
}
}
// Rounding the left (2nd half polygon is the origin of the segment)
- for( ii = 0; ii <= 8; ii++ )
+ for( int ii = 0; ii <= C_SLICE; ii++ )
{
- int jj = ii * 225;
- x = 0.0;
- y = width;
+ double jj = ii * _SEG2( C_SLICE );
+ x = 0.0;
+ y = width;
RotatePoint( &x, &y, -angle - jj );
glVertex3f( startx + x, starty + y, zpos );
}
@@ -1218,94 +5087,502 @@
}
+// Draw a polygon similar to a segment has rounded tips
+static void Draw3D_FilledSegmentMask( double startx,
+ double starty,
+ double endx,
+ double endy,
+ double width,
+ double zpos,
+ GLUtesselator* tess,
+ int orient )
+{
+ double dx, dy, x, y, firstx = 0, firsty = 0;
+ double angle;
+ GLdouble v_data[3];
+ int lpii = p_data.size();
+
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+
+ // Calculate the coordinates of the segment assumed horizontal.
+ // Then turn the strips of the desired angle.
+ dx = endx - startx;
+ dy = endy - starty;
+ angle = ATAN2( dy, dx );
+
+ RotatePoint( &dx, &dy, angle );
+ width /= 2;
+
+ // Trace the flare to right (1st half polygon at the end of the segment)
+ for( int ii = 0; ii <= C_SLICE; ii++ )
+ {
+ x = 0.0;
+ y = -width;
+ RotatePoint( &x, &y, -ii * _SEG2( C_SLICE ) );
+ x += dx;
+ RotatePoint( &x, &y, -angle );
+ p_data.push_back( CPolyPt( (int) ( (startx + x) / g_Parm_3D_Visu.m_BoardScale ),
+ -(int) ( (starty + y) / g_Parm_3D_Visu.m_BoardScale ) ) );
+
+ if( ii == 0 )
+ {
+ firstx = startx + x;
+ firsty = starty + y;
+ }
+ }
+
+ // Rounding the left (2nd half polygon is the origin of the segment)
+ for( int ii = 0; ii <= C_SLICE; ii++ )
+ {
+ double jj = ii * _SEG2( C_SLICE );
+ x = 0.0;
+ y = width;
+ RotatePoint( &x, &y, -angle - jj );
+ p_data.push_back( CPolyPt( (int) ( (startx + x) / g_Parm_3D_Visu.m_BoardScale ),
+ -(int) ( (starty + y) / g_Parm_3D_Visu.m_BoardScale ) ) );
+ }
+
+ gluTessBeginContour( tess );
+
+ for( int ii = p_data.size() - 1; ii >= lpii; ii-- )
+ {
+ v_data[0] = p_data[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -p_data[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &p_data[ii] );
+ }
+
+ gluTessEndContour( tess );
+}
+
+
+static void Draw3D_FilledSegmentMask( double startx,
+ double starty,
+ double endx,
+ double endy,
+ double width,
+ double zpos,
+ std::vector<CPolyPt>* p_data,
+ int orient )
+{
+ double dx, dy, x, y, firstx = 0, firsty = 0;
+
+ // Calculate the coordinates of the segment assumed horizontal.
+ // Then turn the strips of the desired angle.
+ dx = endx - startx;
+ dy = endy - starty;
+ double angle = ATAN2( dy, dx );
+
+ RotatePoint( &dx, &dy, angle );
+ width /= 2;
+
+ // Trace the flare to right (1st half polygon at the end of the segment)
+ for( int ii = 0; ii <= C_SLICE; ii++ )
+ {
+ x = 0.0;
+ y = -width;
+ RotatePoint( &x, &y, -ii * _SEG2( C_SLICE ) );
+ x += dx;
+ RotatePoint( &x, &y, -angle );
+ p_data->push_back( CPolyPt( (int) ( (startx + x) / g_Parm_3D_Visu.m_BoardScale ),
+ -(int) ( (starty + y) / g_Parm_3D_Visu.m_BoardScale ) ) );
+
+ if( ii == 0 )
+ {
+ firstx = startx + x;
+ firsty = starty + y;
+ }
+ }
+
+ // Rounding the left (2nd half polygon is the origin of the segment)
+ for( int ii = 0; ii <= C_SLICE; ii++ )
+ {
+ double jj = ii * _SEG2( C_SLICE );
+ x = 0.0;
+ y = width;
+ RotatePoint( &x, &y, -angle - jj );
+ p_data->push_back( CPolyPt( (int) ( (startx + x) / g_Parm_3D_Visu.m_BoardScale ),
+ -(int) ( (starty + y) / g_Parm_3D_Visu.m_BoardScale ) ) );
+ }
+}
+
+
+/* Draw a polygon with oblong hole
+ */
+static void Draw3D_FilledPolyWithHole( wxPoint* coord,
+ int n,
+ double x,
+ double y,
+ double offX,
+ double offY,
+ double holeX,
+ double holeY,
+ double zpos,
+ double oang )
+{
+ GLUtesselator* tess = gluNewTess();
+ GLdouble v_data[3];
+ CPolyPt corner[1024];
+ int ii, ppii = 0;
+
+ v_data[2] = zpos;
+ g_Parm_3D_Visu.m_ActZpos = zpos;
+ gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )glBegin );
+ gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )glEnd );
+ gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )mytessErrorCB );
+ gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )mytessCPolyPt2Vertex );
+ gluTessCallback( tess, GLU_TESS_COMBINE, ( void (CALLBACK*) () )mytessCombineCB );
+ gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD );
+
+ gluTessBeginPolygon( tess, NULL );
+
+ gluTessBeginContour( tess );
+
+ for( ii = 0; ii < n - 1; ii++ )
+ {
+ corner[ppii].x = (int) ( (coord[ii].x + x + offX / g_Parm_3D_Visu.m_BoardScale) );
+ corner[ppii].y = (int) ( (coord[ii].y + y + offY / g_Parm_3D_Visu.m_BoardScale) );
+ v_data[0] = corner[ppii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -corner[ppii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &corner[ppii] );
+ ppii++;
+ }
+
+ gluTessEndContour( tess );
+
+ // hole...
+ double startx = x * g_Parm_3D_Visu.m_BoardScale;
+ double starty = y * g_Parm_3D_Visu.m_BoardScale;
+ double hy;
+ double theta;
+ double holeradius;
+ double xin, yin;
+
+ if( holeX >= holeY )
+ {
+ // oang direction
+ holeradius = holeY;
+ hy = holeX - holeY;
+ }
+ else
+ {
+ // perpendicular
+ oang -= 900;
+ holeradius = holeX;
+ hy = holeY - holeX;
+ }
+
+ if( holeradius > 0 )
+ {
+ gluTessBeginContour( tess );
+
+ for( ii = 0; ii <= C_SLICE; ii++ )
+ {
+ xin = 0.0;
+ yin = -holeradius;
+ theta = -ii* _SEG2( C_SLICE );
+
+ RotatePoint( &xin, &yin, theta );
+ xin += hy;
+ RotatePoint( &xin, &yin, oang );
+ corner[ppii].x = (int) ( (startx + xin) / g_Parm_3D_Visu.m_BoardScale );
+ corner[ppii].y = (int) ( (starty + yin) / g_Parm_3D_Visu.m_BoardScale );
+ v_data[0] = corner[ppii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -corner[ppii].y * g_Parm_3D_Visu.m_BoardScale;
+ // gluTessVertex store pointers on data, not data, so do not store
+ // different corners values in a temporary variable
+ // but send pointer on each corner value in aCornersList
+ gluTessVertex( tess, v_data, &corner[ppii] );
+ ppii++;
+ }
+
+ // Layout of the rounded left (2nd half polygon is the origin of the
+ // segment)
+ for( ii = 0; ii <= C_SLICE; ii++ )
+ {
+ theta = -ii* _SEG2( C_SLICE );
+
+ xin = 0.0;
+ yin = holeradius;
+ RotatePoint( &xin, &yin, theta );
+ xin -= hy;
+ RotatePoint( &xin, &yin, oang );
+ corner[ppii].x = (int) ( (startx + xin) / g_Parm_3D_Visu.m_BoardScale );
+ corner[ppii].y = (int) ( (starty + yin) / g_Parm_3D_Visu.m_BoardScale );
+ v_data[0] = corner[ppii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -corner[ppii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &corner[ppii] );
+ ppii++;
+ }
+
+ gluTessEndContour( tess );
+ }
+
+ gluTessEndPolygon( tess );
+ gluDeleteTess( tess );
+}
+
+
/* Draw a polygon similar to a segment ends with round hole
*/
-static void Draw3D_FilledSegmentWithHole( double startx, double starty,
- double endx, double endy,
- double width, double holex,
- double holey, double holeradius,
- double zpos )
+static void Draw3D_FilledSegmentWithHole( double startx,
+ double starty,
+ double endx,
+ double endy,
+ double width,
+ double holex,
+ double holey,
+ double holeradius,
+ double zpos,
+ double offX,
+ double offY,
+ double holeX,
+ double holeY,
+ double odx,
+ double ody,
+ double oang )
+{
+ GLUtesselator* tess = gluNewTess();
+ GLdouble v_data[3];
+ CPolyPt corner[1024];
+ int ppii = 0;
+ double x, y, xin, yin;
+ double angle, theta;
+ // Calculate the coordinates of the segment assumed horizontal
+ // Then turn the strips of the desired angle
+ // All calculations are done with startx, starty as the origin of the route
+ double hy = fabs( holeX - holeY );
+ double oendx = endx;
+ double oendy = endy;
+
+ v_data[2] = zpos;
+ g_Parm_3D_Visu.m_ActZpos = zpos;
+ gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )glBegin );
+ gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )glEnd );
+ gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )mytessErrorCB );
+ gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )mytessCPolyPt2Vertex );
+ gluTessCallback( tess, GLU_TESS_COMBINE, ( void (CALLBACK*) () )mytessCombineCB );
+ gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD );
+
+ gluTessBeginPolygon( tess, NULL );
+
+ gluTessBeginContour( tess );
+
+ endx -= startx;
+ endy -= starty;
+
+ if( (endx + endy) == 0 )
+ {
+ angle = oang;
+ }
+ else
+ {
+ angle = ATAN2( endy, endx );
+ }
+
+ RotatePoint( &endx, &endy, angle );
+ RotatePoint( &holex, &holey, angle );
+
+ width /= 2;
+
+ RotatePoint( &offX, &offY, oang );
+
+ // Path of the flare to right (1st half polygon at the end of the segment)
+ // around the half-hole drilling
+ for( int ii = 0; ii <= C_SLICE; ii++ )
+ {
+ x = 0.0;
+ y = -width;
+ theta = -ii* _SEG2( C_SLICE );
+
+ RotatePoint( &x, &y, theta );
+ x += endx;
+ RotatePoint( &x, &y, -angle );
+ corner[ppii].x = (int) ( (startx + x + offX ) / g_Parm_3D_Visu.m_BoardScale );
+ corner[ppii].y = -(int) ( (starty + y - offY ) / g_Parm_3D_Visu.m_BoardScale );
+ v_data[0] = corner[ppii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -corner[ppii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &corner[ppii] );
+ ppii++;
+ }
+
+ // Layout of the rounded left (2nd half polygon is the origin of the
+ // segment)
+ for( int ii = 0; ii <= C_SLICE; ii++ )
+ {
+ theta = -ii* _SEG2( C_SLICE );
+
+ x = 0.0;
+ y = width;
+ RotatePoint( &x, &y, -angle + theta );
+ corner[ppii].x = (int) ( (startx + x + offX) / g_Parm_3D_Visu.m_BoardScale );
+ corner[ppii].y = -(int) ( (starty + y - offY) / g_Parm_3D_Visu.m_BoardScale );
+ v_data[0] = corner[ppii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -corner[ppii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &corner[ppii] );
+ ppii++;
+ }
+
+ gluTessEndContour( tess );
+
+ // hole...
+ startx = (startx + oendx) / 2;
+ starty = (starty + oendy) / 2;
+
+ if( (endx == 0) && (endy == 0) )
+ {
+ if( holeY > holeX )
+ {
+ angle += 900;
+ }
+ }
+ else
+ {
+ if( ( ( holeY > holeX ) && ( ody < odx) ) || ( ( holeY < holeX ) && ( ody > odx) ) )
+ {
+ angle += 900;
+ }
+ }
+
+ gluTessBeginContour( tess );
+
+ for( int ii = 0; ii <= C_SLICE; ii++ )
+ {
+ xin = 0.0;
+ yin = -holeradius;
+ theta = -ii* _SEG2( C_SLICE );
+
+ RotatePoint( &xin, &yin, theta );
+ xin += hy;
+ RotatePoint( &xin, &yin, -angle );
+ corner[ppii].x = (int) ( (startx + xin) / g_Parm_3D_Visu.m_BoardScale );
+ corner[ppii].y = -(int) ( (starty + yin) / g_Parm_3D_Visu.m_BoardScale );
+ v_data[0] = corner[ppii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -corner[ppii].y * g_Parm_3D_Visu.m_BoardScale;
+ // gluTessVertex store pointers on data, not data, so do not store
+ // different corners values in a temporary variable
+ // but send pointer on each corner value in aCornersList
+ gluTessVertex( tess, v_data, &corner[ppii] );
+ ppii++;
+ }
+
+ // Layout of the rounded left (2nd half polygon is the origin of the
+ // segment)
+ for( int ii = 0; ii <= C_SLICE; ii++ )
+ {
+ theta = -ii* _SEG2( C_SLICE );
+
+ xin = 0.0;
+ yin = holeradius;
+ RotatePoint( &xin, &yin, theta );
+ xin -= hy;
+ RotatePoint( &xin, &yin, -angle );
+ corner[ppii].x = (int) ( (startx + xin) / g_Parm_3D_Visu.m_BoardScale );
+ corner[ppii].y = -(int) ( (starty + yin) / g_Parm_3D_Visu.m_BoardScale );
+ v_data[0] = corner[ppii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -corner[ppii].y * g_Parm_3D_Visu.m_BoardScale;
+ gluTessVertex( tess, v_data, &corner[ppii] );
+ ppii++;
+ }
+
+ gluTessEndContour( tess );
+
+ gluTessEndPolygon( tess );
+ gluDeleteTess( tess );
+}
+
+
+static void Draw3D_FilledSegmentWithHoleMask( double startx, double starty,
+ double endx, double endy,
+ double width, double holex,
+ double holey, double holeradius,
+ double zpos, double offX, double offY, double oang )
{
double x, y, xin, yin;
double firstx = 0, firsty = 0, firstxin = 0, firstyin = 0;
- int ii, angle, theta;
+
+ int spii = p_data.size();
// Calculate the coordinates of the segment assumed horizontal
// Then turn the strips of the desired angle
// All calculations are done with startx, starty as the origin of the route
- endx -= startx;
- endy -= starty;
- holex -= startx;
- holey -= starty;
- angle = (int) ( ( atan2( endy, endx ) * 1800 / M_PI ) + 0.5 );
+ endx -= startx;
+ endy -= starty;
+ holex -= startx;
+ holey -= starty;
+ double angle = ATAN2( endy, endx );
RotatePoint( &endx, &endy, angle );
RotatePoint( &holex, &holey, angle );
+ RotatePoint( &offX, &offY, oang );
width /= 2;
- glBegin( GL_QUAD_STRIP );
-
// Path of the flare to right (1st half polygon at the end of the segment)
// around the half-hole drilling
- for( ii = 0; ii <= 8; ii++ )
+ for( int ii = 0; ii <= C_SLICE; ii++ )
{
- x = 0.0;
- y = -width;
- xin = 0.0;
- yin = -holeradius;
- theta = -ii * 225;
+ x = 0.0;
+ y = -width;
+ xin = 0.0;
+ yin = -holeradius;
+ double theta = -ii* _SEG2( C_SLICE );
+
RotatePoint( &x, &y, theta );
RotatePoint( &xin, &yin, theta );
x += endx;
RotatePoint( &x, &y, -angle );
xin += holex;
RotatePoint( &xin, &yin, -angle );
- glVertex3f( startx + xin, starty + yin, zpos );
- glVertex3f( startx + x, starty + y, zpos );
+ p_data.push_back( CPolyPt( (int) ( (startx + x + offX) / g_Parm_3D_Visu.m_BoardScale ),
+ -(int) ( (starty + y -
+ offY) / g_Parm_3D_Visu.m_BoardScale ) ) );
if( ii == 0 )
{
- firstx = startx + x;
- firsty = starty + y;
- firstxin = startx + xin;
- firstyin = starty + yin;
+ firstx = startx + x;
+ firsty = starty + y;
+ firstxin = startx + xin;
+ firstyin = starty + yin;
}
}
// Layout of the rounded left (2nd half polygon is the origin of the
// segment)
- for( ii = 0; ii <= 8; ii++ )
+ for( int ii = 0; ii <= C_SLICE; ii++ )
{
- theta = -ii * 225;
- x = 0.0;
- y = width;
+ double theta = -ii* _SEG2( C_SLICE );
+
+ x = 0.0;
+ y = width;
RotatePoint( &x, &y, -angle + theta );
xin = 0.0;
yin = holeradius;
RotatePoint( &xin, &yin, theta );
xin += holex;
RotatePoint( &xin, &yin, -angle );
- glVertex3f( startx + xin, starty + yin, zpos );
- glVertex3f( startx + x, starty + y, zpos );
+ p_data.push_back( CPolyPt( (int) ( (startx + x + offX) / g_Parm_3D_Visu.m_BoardScale ),
+ -(int) ( (starty + y -
+ offY) / g_Parm_3D_Visu.m_BoardScale ) ) );
}
- glVertex3f( firstxin, firstyin, zpos );
- glVertex3f( firstx, firsty, zpos );
- glEnd();
+ for( int ii = 0; ii < ( (int) p_data.size() - spii ) / 2; ii++ )
+ {
+ CPolyPt h = p_data[spii + ii];
+ p_data[spii + ii] = p_data[p_data.size() - ii - 1];
+ p_data[p_data.size() - ii - 1] = h;
+ }
}
static void Draw3D_ArcSegment( double startx, double starty, double centrex,
double centrey, double arc_angle, double width, double zpos )
{
- int ii;
- int slice = 36; // Number of segments to approximate a circle by segments
- double hole, rayon;
+ int slice = C_SLICE * 2;
+ double hole, radius;
double arcStart_Angle;
- arcStart_Angle = (atan2( startx - centrex, starty - centrey ) * 1800 / M_PI );
- rayon = hypot( startx - centrex, starty - centrey ) + ( width / 2);
- hole = rayon - width;
+ arcStart_Angle = ( ATAN2( startx - centrex, starty - centrey ) );
+ radius = hypot( startx - centrex, starty - centrey ) + ( width / 2);
+ hole = radius - width;
// Calculate the number of segments to approximate this arc
int imax = (int) ( (double) arc_angle * slice / 3600.0 );
@@ -1322,16 +5599,16 @@
glBegin( GL_QUAD_STRIP );
- for( ii = 0; ii <= imax; ii++ )
+ for( int ii = 0; ii <= imax; ii++ )
{
double angle = (double) ii * delta_angle;
angle += arcStart_Angle + 900;
- double dx = hole;
- double dy = 0.0;
+ double dx = hole;
+ double dy = 0.0;
RotatePoint( &dx, &dy, (int) angle );
glVertex3f( dx + startx, dy + starty, zpos );
- dx = rayon;
- dy = 0.0;
+ dx = radius;
+ dy = 0.0;
RotatePoint( &dx, &dy, (int) angle );
glVertex3f( dx + startx, dy + starty, zpos );
}
@@ -1340,24 +5617,126 @@
}
+static void Draw3D_ArcSegmentMask( double startx, double starty, double centrex,
+ double centrey, double arc_angle, double width, double zpos )
+{
+ int slice = C_SLICE * 2;
+ double radius;
+ double arcStart_Angle;
+ double lx, ly;
+
+ arcStart_Angle = ( ATAN2( startx - centrex, starty - centrey ) );
+ radius = hypot( startx - centrex, starty - centrey );
+
+ // Calculate the number of segments to approximate this arc
+ int imax = (int) ( (double) arc_angle * slice / 3600.0 );
+
+ if( imax < 0 )
+ imax = -imax;
+
+ if( imax == 0 )
+ imax = 1;
+
+ // Adjust delta_angle to have exactly imax segments in arc_angle
+ // i.e. arc_angle = imax delta_agnle.
+ double delta_angle = (double) arc_angle / imax;
+
+ for( int ii = 0; ii <= imax; ii++ )
+ {
+ double angle = (double) ii * delta_angle;
+ angle += arcStart_Angle + 900;
+ double dx = radius;
+ double dy = 0.0;
+ dy = 0.0;
+ RotatePoint( &dx, &dy, angle );
+ dx += startx;
+ dy += starty;
+ dx /= g_Parm_3D_Visu.m_BoardScale;
+ dy /= g_Parm_3D_Visu.m_BoardScale;
+
+ if( ii > 0 )
+ {
+ e_data.push_back( CPolyPt( (int) lx, (int) (-ly) ) );
+ e_data.push_back( CPolyPt( (int) dx, (int) (-dy) ) );
+ }
+
+ lx = dx;
+ ly = dy;
+ }
+}
+
+
+static void Draw3D_ArcSegmentMask( double startx,
+ double starty,
+ double centrex,
+ double centrey,
+ double arc_angle,
+ double width,
+ double zpos,
+ std::vector<CPolyPt>* e_data )
+{
+ int slice = C_SLICE * 2;
+ double radius;
+ double arcStart_Angle;
+ double lx = 0, ly = 0;
+
+ arcStart_Angle = ( ATAN2( startx - centrex, starty - centrey ) );
+ radius = hypot( startx - centrex, starty - centrey );
+
+ // Calculate the number of segments to approximate this arc
+ int imax = (int) ( (double) arc_angle * slice / 3600.0 );
+
+ if( imax < 0 )
+ imax = -imax;
+
+ if( imax == 0 )
+ imax = 1;
+
+ // Adjust delta_angle to have exactly imax segments in arc_angle
+ // i.e. arc_angle = imax delta_agnle.
+ double delta_angle = (double) arc_angle / imax;
+
+ for( int ii = 0; ii <= imax; ii++ )
+ {
+ double angle = (double) ii * delta_angle;
+ angle += arcStart_Angle + 900;
+ double dx = radius;
+ double dy = 0.0;
+ dy = 0.0;
+ RotatePoint( &dx, &dy, angle );
+ dx += startx;
+ dy += starty;
+
+ if( ii > 0 )
+ {
+ Draw3D_FilledSegmentMask( lx, ly, dx, dy, width, zpos, e_data, 1 );
+ e_data->push_back( CPolyPt( MAGIC_CONT, 0 ) );
+ }
+
+ lx = dx;
+ ly = dy;
+ }
+}
+
+
static void Draw3D_CircleSegment( double startx, double starty, double endx,
double endy, double width, double zpos )
{
- int ii, slice = 36;
- double x, y, hole, rayon;
+ int slice = C_SLICE * 2;
+ double x, y, hole, radius;
- rayon = hypot( startx - endx, starty - endy ) + ( width / 2);
- hole = rayon - width;
+ radius = hypot( startx - endx, starty - endy ) + ( width / 2);
+ hole = radius - width;
glBegin( GL_QUAD_STRIP );
- for( ii = 0; ii <= slice; ii++ )
+ for( int ii = 0; ii <= slice; ii++ )
{
x = hole; y = 0.0;
- RotatePoint( &x, &y, ii * 3600 / slice );
+ RotatePoint( &x, &y, ii * _SEG( slice ) );
glVertex3f( x + startx, y + starty, zpos );
- x = rayon; y = 0.0;
- RotatePoint( &x, &y, ii * 3600 / slice );
+ x = radius; y = 0.0;
+ RotatePoint( &x, &y, ii * _SEG( slice ) );
glVertex3f( x + startx, y + starty, zpos );
}
@@ -1365,29 +5744,99 @@
}
+static void Draw3D_CircleSegmentMask( double startx, double starty, double endx,
+ double endy, double width, double zpos )
+{
+ int ii, slice = C_SLICE * 2;
+ double lx, ly, x, y, radius;
+
+ int seii = e_data.size();
+
+ radius = hypot( startx - endx, starty - endy );
+
+ for( ii = 0; ii <= slice; ii++ )
+ {
+ x = radius; y = 0.0;
+ RotatePoint( &x, &y, ii * _SEG( slice ) );
+ x += startx;
+ y += starty;
+ x /= g_Parm_3D_Visu.m_BoardScale;
+ y /= g_Parm_3D_Visu.m_BoardScale;
+
+ if( ii > 0 )
+ {
+ e_data.push_back( CPolyPt( (int) lx, (int) ly ) );
+ e_data.push_back( CPolyPt( (int) x, (int) y ) );
+ }
+
+ lx = x;
+ ly = y;
+ }
+
+ for( ii = 0; ii < ( (int) e_data.size() - seii ) / 2; ii++ )
+ {
+ CPolyPt h = e_data[seii + ii];
+ e_data[seii + ii] = e_data[e_data.size() - ii - 1];
+ e_data[e_data.size() - ii - 1] = h;
+ }
+}
+
+
+static void Draw3D_CircleSegmentMask( double startx,
+ double starty,
+ double endx,
+ double endy,
+ double width,
+ double zpos,
+ std::vector<CPolyPt>* e_data )
+{
+ int ii, slice = C_SLICE * 2;
+ double lx = 0, ly = 0, x, y, radius;
+
+ radius = hypot( startx - endx, starty - endy );
+
+ for( ii = 0; ii <= slice; ii++ )
+ {
+ x = radius; y = 0.0;
+ RotatePoint( &x, &y, ii * _SEG( slice ) );
+ x += startx;
+ y += starty;
+
+ if( ii > 0 )
+ {
+ Draw3D_FilledSegmentMask( lx, ly, x, y, width, zpos, e_data, 1 );
+ e_data->push_back( CPolyPt( MAGIC_CONT, 0 ) );
+ }
+
+ lx = x;
+ ly = y;
+ }
+
+#warning "TODO REVERSE LIST!"
+}
+
+
void EDA_3D_CANVAS::Draw3D_Polygon( std::vector<wxPoint>& aCornersList, double aZpos )
{
g_Parm_3D_Visu.m_ActZpos = aZpos;
GLUtesselator* tess = gluNewTess();
- gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*)() )tessBeginCB );
- gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*)() )tessEndCB );
- gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*)() )tessErrorCB );
- gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*)() )tesswxPoint2Vertex );
+ gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )glBegin );
+ gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )glEnd );
+ gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )tessErrorCB );
+ gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )tesswxPoint2Vertex );
GLdouble v_data[3];
v_data[2] = aZpos;
- //gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
-
// Draw solid polygon
gluTessBeginPolygon( tess, NULL );
gluTessBeginContour( tess );
for( unsigned ii = 0; ii < aCornersList.size(); ii++ )
{
- v_data[0] = aCornersList[ii].x * g_Parm_3D_Visu.m_BoardScale;
- v_data[1] = -aCornersList[ii].y * g_Parm_3D_Visu.m_BoardScale;
+ v_data[0] = aCornersList[ii].x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -aCornersList[ii].y * g_Parm_3D_Visu.m_BoardScale;
// gluTessVertex store pointers on data, not data, so do not store
// different corners values in a temporary variable
// but send pointer on each corner value in aCornersList
@@ -1404,28 +5853,41 @@
static int Get3DLayerEnable( int act_layer )
{
int i = -1;
+
// see if layer needs to be shown
// check the flags
- switch (act_layer)
+ switch( act_layer )
{
- case DRAW_N:
- i=g_Parm_3D_Visu.FL_DRAWINGS;
- break;
-
- case COMMENT_N:
- i=g_Parm_3D_Visu.FL_COMMENTS;
- break;
-
- case ECO1_N:
- i=g_Parm_3D_Visu.FL_ECO1;
- break;
-
- case ECO2_N:
- i=g_Parm_3D_Visu.FL_ECO2;
- break;
+ case ADHESIVE_N_FRONT:
+ case ADHESIVE_N_BACK:
+ case SOLDERMASK_N_FRONT:
+ case SOLDERMASK_N_BACK:
+ case SOLDERPASTE_N_FRONT:
+ case SOLDERPASTE_N_BACK:
+ case SILKSCREEN_N_FRONT:
+ case SILKSCREEN_N_BACK:
+ return g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( act_layer );
+ break;
+
+ case DRAW_N:
+ i = g_Parm_3D_Visu.FL_DRAWINGS;
+ break;
+
+ case COMMENT_N:
+ i = g_Parm_3D_Visu.FL_COMMENTS;
+ break;
+
+ case ECO1_N:
+ i = g_Parm_3D_Visu.FL_ECO1;
+ break;
+
+ case ECO2_N:
+ i = g_Parm_3D_Visu.FL_ECO2;
+ break;
}
+
// the layer was not a layer with a flag, so show it
- if (i < 0)
+ if( i < 0 )
return true;
// if the layer has a flag, return the flag
@@ -1440,30 +5902,19 @@
nZ = 1.0;
if( ( act_layer <= LAST_COPPER_LAYER - 1 )
- || ( act_layer == ADHESIVE_N_BACK )
- || ( act_layer == SOLDERPASTE_N_BACK )
- || ( act_layer == SILKSCREEN_N_BACK )
- || ( act_layer == SOLDERMASK_N_BACK ) )
+ || ( act_layer == ADHESIVE_N_BACK )
+ || ( act_layer == SOLDERPASTE_N_BACK )
+ || ( act_layer == SILKSCREEN_N_BACK )
+ || ( act_layer == SOLDERMASK_N_BACK ) )
nZ = -1.0;
+
return nZ;
}
-///////////////////////////////////////////////////////////////////////////////
+// /////////////////////////////////////////////////////////////////////////////
// GLU_TESS CALLBACKS
-///////////////////////////////////////////////////////////////////////////////
-
-void CALLBACK tessBeginCB( GLenum which )
-{
- glBegin( which );
-}
-
-
-void CALLBACK tessEndCB()
-{
- glEnd();
-}
-
+// /////////////////////////////////////////////////////////////////////////////
void CALLBACK tessCPolyPt2Vertex( const GLvoid* data )
{
@@ -1475,6 +5926,7 @@
g_Parm_3D_Visu.m_ActZpos );
}
+
void CALLBACK tesswxPoint2Vertex( const GLvoid* data )
{
const wxPoint* ptr = (const wxPoint*) data;
@@ -1496,3 +5948,160 @@
D( printf( "Tess ERROR: %s\n", errorStr ); )
#endif
}
+
+
+// /////////////////////////////////////////////////////////////////////////////
+// MY GLU_TESS CALLBACKS
+// /////////////////////////////////////////////////////////////////////////////
+
+void CALLBACK mytessCPolyPt2Vertex( const GLvoid* data )
+{
+ // cast back to double type
+ const CPolyPt* ptr = (const CPolyPt*) data;
+
+ glVertex3f( ptr->x * g_Parm_3D_Visu.m_BoardScale,
+ -ptr->y * g_Parm_3D_Visu.m_BoardScale,
+ g_Parm_3D_Visu.m_ActZpos );
+}
+
+
+void CALLBACK mytessCombineCB( GLdouble coords[3],
+ void* vertex_data[4],
+ GLfloat weight[4],
+ void** outData )
+{
+ CPolyPt* n =
+ new CPolyPt( (int) (coords[0] / g_Parm_3D_Visu.m_BoardScale),
+ -(int) (coords[1] / g_Parm_3D_Visu.m_BoardScale) );
+
+ *outData = n;
+}
+
+
+void CALLBACK mytessErrorCB( GLenum errorCode )
+{
+#if defined(DEBUG)
+ const GLubyte* errorStr;
+
+ errorStr = gluErrorString( errorCode );
+
+ // DEBUG //
+ fprintf( stderr, "Tess ERROR: %s\n", errorStr );
+#endif
+}
+
+
+// /////////////////////////////////////////////////////////////////////////////
+// MY2 GLU_TESS CALLBACKS
+// /////////////////////////////////////////////////////////////////////////////
+
+void CALLBACK my2tessBeginCB( GLenum which )
+{
+ gluTessBeginContour( tess );
+}
+
+
+void CALLBACK my2tessEndCB()
+{
+ gluTessEndContour( tess );
+ xe_data.push_back( CPolyPt( (int) MAGIC_CONT, 0, true, 0 ) );
+}
+
+
+void CALLBACK my2tessCPolyPt2Vertex( const GLvoid* data )
+{
+ // cast back to double type
+ CPolyPt* ptr = (CPolyPt*) data;
+ GLdouble v_data[3];
+
+ v_data[0] = ptr->x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -ptr->y * g_Parm_3D_Visu.m_BoardScale;
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+ ptr->utility++;
+ xe_data.push_back( CPolyPt( ptr->x, ptr->y, false, 1 ) );
+ gluTessVertex( tess, v_data, ptr );
+}
+
+
+void CALLBACK my2tessCombineCB( GLdouble coords[3],
+ void* vertex_data[4],
+ GLfloat weight[4],
+ void** outData )
+{
+ CPolyPt* n =
+ new CPolyPt( (int) (coords[0] / g_Parm_3D_Visu.m_BoardScale),
+ -(int) (coords[1] / g_Parm_3D_Visu.m_BoardScale) );
+
+ *outData = n;
+}
+
+
+void CALLBACK my2tessErrorCB( GLenum errorCode )
+{
+#if defined(DEBUG)
+ const GLubyte* errorStr;
+
+ errorStr = gluErrorString( errorCode );
+
+ // DEBUG //
+ fprintf( stderr, "Tess 2 ERROR: %s\n", errorStr );
+#endif
+}
+
+
+// /////////////////////////////////////////////////////////////////////////////
+// MY3 GLU_TESS CALLBACKS
+// /////////////////////////////////////////////////////////////////////////////
+
+void CALLBACK my3tessBeginCB( GLenum which )
+{
+ gluTessBeginContour( tess );
+}
+
+
+void CALLBACK my3tessEndCB()
+{
+ gluTessEndContour( tess );
+ se_data.push_back( CPolyPt( (int) MAGIC_CONT, 0, true, 0 ) );
+}
+
+
+void CALLBACK my3tessCPolyPt2Vertex( const GLvoid* data )
+{
+ // cast back to double type
+ CPolyPt* ptr = (CPolyPt*) data;
+ GLdouble v_data[3];
+
+ v_data[0] = ptr->x * g_Parm_3D_Visu.m_BoardScale;
+ v_data[1] = -ptr->y * g_Parm_3D_Visu.m_BoardScale;
+ v_data[2] = g_Parm_3D_Visu.m_ActZpos;
+ ptr->utility++;
+ se_data.push_back( CPolyPt( ptr->x, ptr->y, false, 1 ) );
+ gluTessVertex( tess, v_data, ptr );
+}
+
+
+void CALLBACK my3tessCombineCB( GLdouble coords[3],
+ void* vertex_data[4],
+ GLfloat weight[4],
+ void** outData )
+{
+ CPolyPt* n =
+ new CPolyPt( (int) (coords[0] / g_Parm_3D_Visu.m_BoardScale),
+ -(int) (coords[1] / g_Parm_3D_Visu.m_BoardScale) );
+
+ *outData = n;
+}
+
+
+void CALLBACK my3tessErrorCB( GLenum errorCode )
+{
+#if defined(DEBUG)
+ const GLubyte* errorStr;
+
+ errorStr = gluErrorString( errorCode );
+
+ // DEBUG //
+ fprintf( stderr, "Tess 3 ERROR: %s\n", errorStr );
+#endif
+}
=== modified file '3d-viewer/3d_frame.cpp'
--- 3d-viewer/3d_frame.cpp 2012-04-19 06:55:45 +0000
+++ 3d-viewer/3d_frame.cpp 2012-06-15 14:50:19 +0000
@@ -321,6 +321,21 @@
NewDisplay();
return;
+ case ID_MENU3D_RENDER_ONOFF:
+ g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] = isChecked;
+ NewDisplay();
+ return;
+
+ case ID_MENU3D_GRID_ONOFF:
+ g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_GRID] = isChecked;
+ NewDisplay();
+ return;
+
+ case ID_MENU3D_VIRT_ONOFF:
+ g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_VIRT] = isChecked;
+ NewDisplay();
+ return;
+
default:
wxMessageBox( wxT( "EDA_3D_FRAME::Process_Special_Functions() error: unknown command" ) );
return;
=== modified file '3d-viewer/3d_read_mesh.cpp'
--- 3d-viewer/3d_read_mesh.cpp 2012-01-23 04:33:36 +0000
+++ 3d-viewer/3d_read_mesh.cpp 2012-06-15 16:21:09 +0000
@@ -35,14 +35,14 @@
#include <3d_viewer.h>
-
int S3D_MASTER::ReadData()
{
- char line[1024], * text;
- wxFileName fn;
- wxString FullFilename;
- FILE* file;
- int LineNum = 0;
+ char line[1024], * text;
+ wxFileName fn;
+
+ wxString FullFilename;
+ FILE* file;
+ int LineNum = 0;
if( m_Shape3DName.IsEmpty() )
{
@@ -51,9 +51,9 @@
wxString shape3DNname = m_Shape3DName;
#ifdef __WINDOWS__
- shape3DNname.Replace( wxT("/"), wxT("\\") );
+ shape3DNname.Replace( wxT( "/" ), wxT( "\\" ) );
#else
- shape3DNname.Replace( wxT("\\"), wxT("/") );
+ shape3DNname.Replace( wxT( "\\" ), wxT( "/" ) );
#endif
if( wxFileName::FileExists( shape3DNname ) )
@@ -112,16 +112,130 @@
return 0;
}
+int S3D_MASTER::ReadData(const wxString* ref)
+{
+ char line[1024], * text;
+ wxFileName fn;
+
+#ifndef TSP_20120603
+ wxString FullFilename;
+#endif // TSP_20120603
+ FILE* file;
+ int LineNum = 0;
+
+ if( m_Shape3DName.IsEmpty() )
+ {
+ return 1;
+ }
+
+ wxString shape3DNname = m_Shape3DName;
+#ifdef __WINDOWS__
+ shape3DNname.Replace( wxT( "/" ), wxT( "\\" ) );
+#else
+ shape3DNname.Replace( wxT( "\\" ), wxT( "/" ) );
+#endif
+
+ wxString alt_shape3DNname = (shape3DNname.Length() > 4)?shape3DNname.SubString(0, shape3DNname.Length()-5):shape3DNname;
+ alt_shape3DNname.Append( wxT( "_" ) );
+ alt_shape3DNname.Append( ref->GetChar(0) );
+ alt_shape3DNname.Append( wxT( ".wrl" ) );
+
+ if( wxFileName::FileExists( alt_shape3DNname ) )
+ {
+ FullFilename = alt_shape3DNname;
+ }
+ else
+ {
+ fn = alt_shape3DNname;
+ FullFilename = wxGetApp().FindLibraryPath( fn );
+
+ if( FullFilename.IsEmpty() )
+ {
+ if( wxFileName::FileExists( shape3DNname ) )
+ {
+ FullFilename = shape3DNname;
+ }
+ else
+ {
+ fn = shape3DNname;
+ FullFilename = wxGetApp().FindLibraryPath( fn );
+
+ if( FullFilename.IsEmpty() )
+ {
+ wxLogDebug( wxT( "3D part library <%s> could not be found." ),
+ GetChars( fn.GetFullPath() ) );
+ return -1;
+ }
+ }
+ }
+ }
+
+ file = wxFopen( FullFilename, wxT( "rt" ) );
+
+ if( file == NULL )
+ {
+ return -1;
+ }
+
+ // Switch the locale to standard C (needed to print floating point numbers like 1.3)
+ SetLocaleTo_C_standard();
+
+ while( GetLine( file, line, &LineNum, 512 ) )
+ {
+ text = strtok( line, " \t\n\r" );
+
+ if( stricmp( text, "DEF" ) == 0 )
+ {
+ while( GetLine( file, line, &LineNum, 512 ) )
+ {
+ text = strtok( line, " \t\n\r" );
+
+ if( text == NULL )
+ continue;
+
+ if( *text == '}' )
+ break;
+
+ if( stricmp( text, "children" ) == 0 )
+ {
+ ReadChildren( file, &LineNum );
+ }
+ }
+ }
+ }
+
+ std::vector<S3D_Vertex> m_MinMax;
+ m_MinMax.clear();
+ m_MinMax.push_back( m_MinPos );
+ m_MinMax.push_back( m_MaxPos );
+ Set_Object_Coords( m_MinMax );
+ if ( m_MinMax[0].z <= m_MinMax[1].z )
+ {
+ m_MinPos = m_MinMax[0];
+ m_MaxPos = m_MinMax[1];
+ }
+ else
+ {
+ m_MinPos = m_MinMax[1];
+ m_MaxPos = m_MinMax[0];
+ }
+
+
+ fclose( file );
+ SetLocaleTo_Default(); // revert to the current locale
+ return 0;
+}
+
int S3D_MASTER::ReadMaterial( FILE* file, int* LineNum )
{
- char line[512], * text, * command;
- wxString mat_name;
- S3D_MATERIAL* material = NULL;
+ char line[512], * text, * command;
+ wxString mat_name;
+ S3D_MATERIAL* material = NULL;
- command = strtok( NULL, " \t\n\r" );
- text = strtok( NULL, " \t\n\r" );
- mat_name = FROM_UTF8( text );
+ command = strtok( NULL, " \t\n\r" );
+ text = strtok( NULL, " \t\n\r" );
+ mat_name = FROM_UTF8( text );
if( stricmp( command, "USE" ) == 0 )
{
@@ -237,8 +351,8 @@
int S3D_MASTER::ReadShape( FILE* file, int* LineNum )
{
- char line[1024], * text;
- int err = 1;
+ char line[1024], * text;
+ int err = 1;
while( GetLine( file, line, LineNum, 512 ) )
{
@@ -260,7 +374,7 @@
}
else
{
- printf( "ReadShape error line %d <%s> \n", *LineNum, text );
+ printf( "ReadShape error line %d <%s>\n", *LineNum, text );
break;
}
}
@@ -271,8 +385,8 @@
int S3D_MASTER::ReadAppearance( FILE* file, int* LineNum )
{
- char line[1024], * text;
- int err = 1;
+ char line[1024], * text;
+ int err = 1;
while( GetLine( file, line, LineNum, 512 ) )
{
@@ -317,20 +431,20 @@
* text_buffer contains the first line of this node :
* "coord Coordinate { point ["
*/
-void ReadCoordsList( FILE* file, char* text_buffer, std::vector< double >& aList, int* LineNum )
+void ReadCoordsList( FILE* file, char* text_buffer, std::vector<double>& aList, int* LineNum )
{
- unsigned int ii = 0, jj = 0;
- char* text;
- bool HasData = false;
- bool StartData = false;
- bool EndNode = false;
- char string_num[512];
+ unsigned int ii = 0, jj = 0;
+ char* text;
+ bool HasData = false;
+ bool StartData = false;
+ bool EndNode = false;
+ char string_num[512];
text = text_buffer;
while( !EndNode )
{
- if( *text == 0 ) // Needs data !
+ if( *text == 0 ) // Needs data !
{
text = text_buffer;
GetLine( file, text_buffer, LineNum, 512 );
@@ -373,6 +487,7 @@
break;
default:
+
if( !StartData )
break;
@@ -395,9 +510,9 @@
int S3D_MASTER::ReadGeometry( FILE* file, int* LineNum )
{
char line[1024], buffer[1024], * text;
- int err = 1;
- std::vector< double > points;
- std::vector< double > list;
+ int err = 1;
+ std::vector<double> points;
+ std::vector<double> list;
while( GetLine( file, line, LineNum, 512 ) )
{
@@ -420,6 +535,7 @@
else
{
}
+
continue;
}
@@ -433,6 +549,7 @@
else
{
}
+
continue;
}
@@ -506,8 +623,8 @@
break;
}
- std::vector< int > coordIndex;
- std::vector< S3D_Vertex > vertices;
+ std::vector<int> coordIndex;
+ std::vector<S3D_Vertex> vertices;
while( GetLine( file, line, LineNum, 512 ) )
{
@@ -527,7 +644,7 @@
{
int kk = coordIndex[jj] * 3;
- if( (kk < 0) || ((kk + 3) > (int)points.size()) )
+ if( (kk < 0) || ( (kk + 3) > (int) points.size() ) )
{
wxLogError( wxT( "3D geometry index read error <%s> at line %d." ),
GetChars( FROM_UTF8( text ) ), *LineNum );
@@ -536,12 +653,30 @@
}
S3D_Vertex vertex;
- vertex.x = points[kk];
- vertex.y = points[kk + 1];
- vertex.z = points[kk + 2];
+ vertex.x = points[kk];
+ vertex.y = points[kk + 1];
+ vertex.z = points[kk + 2];
vertices.push_back( vertex );
+
+ if( vertex.x < m_MinPos.x )
+ m_MinPos.x = vertex.x;
+
+ if( vertex.y < m_MinPos.y )
+ m_MinPos.y = vertex.y;
+
+ if( vertex.z < m_MinPos.z )
+ m_MinPos.z = vertex.z;
+
+ if( vertex.x > m_MaxPos.x )
+ m_MaxPos.x = vertex.x;
+
+ if( vertex.y > m_MaxPos.y )
+ m_MaxPos.y = vertex.y;
+
+ if( vertex.z > m_MaxPos.z )
+ m_MaxPos.z = vertex.z;
}
-
+
Set_Object_Coords( vertices );
Set_Object_Data( vertices );
vertices.clear();
=== modified file '3d-viewer/3d_struct.h'
--- 3d-viewer/3d_struct.h 2012-05-11 09:02:35 +0000
+++ 3d-viewer/3d_struct.h 2012-06-14 15:40:05 +0000
@@ -97,6 +97,8 @@
S3D_Vertex m_MatPosition;
Struct3D_Shape* m_3D_Drawings;
S3D_MATERIAL* m_Materials;
+ S3D_Vertex m_MinPos;
+ S3D_Vertex m_MaxPos;
public:
S3D_MASTER( EDA_ITEM* aParent );
@@ -114,6 +116,7 @@
void Copy( S3D_MASTER* pattern );
int ReadData();
+ int ReadData(const wxString* ref);
/**
* Function ReadMaterial
=== modified file '3d-viewer/3d_toolbar.cpp'
--- 3d-viewer/3d_toolbar.cpp 2012-04-09 09:16:47 +0000
+++ 3d-viewer/3d_toolbar.cpp 2012-06-15 14:42:02 +0000
@@ -133,13 +133,14 @@
bool full_options = true;
// If called from the display frame of CvPcb, only some options are relevant
- if( Parent()->GetName() == wxT( "CmpFrame" ) ) {
+ if( Parent()->GetName() == wxT( "CmpFrame" ) )
+ {
full_options = false;
}
- wxMenuBar* menuBar = new wxMenuBar;
- wxMenu* fileMenu = new wxMenu;
- wxMenu* prefsMenu = new wxMenu;
+ wxMenuBar* menuBar = new wxMenuBar;
+ wxMenu* fileMenu = new wxMenu;
+ wxMenu* prefsMenu = new wxMenu;
menuBar->Append( fileMenu, _( "&File" ) );
@@ -161,36 +162,49 @@
wxMenuItem* item;
item = AddMenuItem( prefsMenu, ID_MENU3D_AXIS_ONOFF,
- _( "Show 3D &Axis" ), KiBitmap( axis3d_front_xpm ), wxITEM_CHECK );
- item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_AXIS]);
+ _( "Show 3D &Axis" ), KiBitmap( axis3d_front_xpm ), wxITEM_CHECK );
+ item->Check( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_AXIS] );
if( full_options )
{
- item = AddMenuItem( prefsMenu, ID_MENU3D_MODULE_ONOFF,
- _( "Show 3D F&ootprints" ), KiBitmap( shape_3d_xpm ), wxITEM_CHECK );
- item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_MODULE]);
-
- item = AddMenuItem( prefsMenu, ID_MENU3D_ZONE_ONOFF,
- _( "Show Zone &Filling" ), KiBitmap( add_zone_xpm ), wxITEM_CHECK );
- item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ZONE]);
-
- item = AddMenuItem( prefsMenu, ID_MENU3D_COMMENTS_ONOFF,
- _( "Show &Comments Layer" ), KiBitmap( edit_sheet_xpm ), wxITEM_CHECK );
- item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_COMMENTS]);
-
- item = AddMenuItem( prefsMenu, ID_MENU3D_DRAWINGS_ONOFF,
- _( "Show &Drawings Layer" ), KiBitmap( add_polygon_xpm ), wxITEM_CHECK );
- item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_DRAWINGS]);
-
- item = AddMenuItem( prefsMenu, ID_MENU3D_ECO1_ONOFF,
- _( "Show Eco&1 Layer" ), KiBitmap( tools_xpm ), wxITEM_CHECK );
- item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ECO1]);
-
- item = AddMenuItem( prefsMenu, ID_MENU3D_ECO2_ONOFF,
- _( "Show Eco&2 Layer" ), KiBitmap( tools_xpm ), wxITEM_CHECK );
- item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ECO2]);
-
+ item = AddMenuItem( prefsMenu, ID_MENU3D_MODULE_ONOFF,
+ _( "Show 3D F&ootprints" ), KiBitmap( shape_3d_xpm ), wxITEM_CHECK );
+ item->Check( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_MODULE] );
+
+ item = AddMenuItem( prefsMenu, ID_MENU3D_ZONE_ONOFF,
+ _( "Show Zone &Filling" ), KiBitmap( add_zone_xpm ), wxITEM_CHECK );
+ item->Check( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ZONE] );
+
+ item = AddMenuItem( prefsMenu, ID_MENU3D_COMMENTS_ONOFF,
+ _( "Show &Comments Layer" ), KiBitmap( edit_sheet_xpm ),
+ wxITEM_CHECK );
+ item->Check( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_COMMENTS] );
+
+ item = AddMenuItem( prefsMenu, ID_MENU3D_DRAWINGS_ONOFF,
+ _( "Show &Drawings Layer" ), KiBitmap( add_polygon_xpm ),
+ wxITEM_CHECK );
+ item->Check( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_DRAWINGS] );
+
+ item = AddMenuItem( prefsMenu, ID_MENU3D_ECO1_ONOFF,
+ _( "Show Eco&1 Layer" ), KiBitmap( tools_xpm ), wxITEM_CHECK );
+ item->Check( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ECO1] );
+
+ item = AddMenuItem( prefsMenu, ID_MENU3D_ECO2_ONOFF,
+ _( "Show Eco&2 Layer" ), KiBitmap( tools_xpm ), wxITEM_CHECK );
+ item->Check( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ECO2] );
+
+ item = AddMenuItem( prefsMenu, ID_MENU3D_RENDER_ONOFF,
+ _( "Show &Render Mode" ), KiBitmap( tools_xpm ), wxITEM_CHECK );
+ item->Check( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_RENDER] );
+
+ item = AddMenuItem( prefsMenu, ID_MENU3D_GRID_ONOFF,
+ _( "Show &Grid" ), KiBitmap( tools_xpm ), wxITEM_CHECK );
+ item->Check( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_GRID] );
+
+ item = AddMenuItem( prefsMenu, ID_MENU3D_VIRT_ONOFF,
+ _( "Show &Virtual Modules" ), KiBitmap( tools_xpm ), wxITEM_CHECK );
+ item->Check( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_VIRT] );
}
SetMenuBar( menuBar );
=== modified file '3d-viewer/3d_viewer.h'
--- 3d-viewer/3d_viewer.h 2012-04-09 09:16:47 +0000
+++ 3d-viewer/3d_viewer.h 2012-06-15 14:43:04 +0000
@@ -51,6 +51,7 @@
#include <3d_struct.h>
#include <id.h>
+#include <PolyLine.h>
class BOARD_DESIGN_SETTINGS;
@@ -97,6 +98,9 @@
ID_MENU3D_COMMENTS_ONOFF,
ID_MENU3D_ECO1_ONOFF,
ID_MENU3D_ECO2_ONOFF,
+ ID_MENU3D_RENDER_ONOFF,
+ ID_MENU3D_GRID_ONOFF,
+ ID_MENU3D_VIRT_ONOFF,
ID_END_COMMAND_3D,
ID_MENU_SCREENCOPY_PNG,
@@ -127,40 +131,39 @@
class SEGVIA;
-#define m_ROTX m_Rot[0]
-#define m_ROTY m_Rot[1]
-#define m_ROTZ m_Rot[2]
+#define m_ROTX m_Rot[0]
+#define m_ROTY m_Rot[1]
+#define m_ROTZ m_Rot[2]
/* information needed to display 3D board */
class Info_3D_Visu
{
-
public:
enum {
- FL_AXIS=0, FL_MODULE, FL_ZONE,
- FL_COMMENTS, FL_DRAWINGS, FL_ECO1, FL_ECO2,
+ FL_AXIS=0, FL_MODULE, FL_ZONE,
+ FL_COMMENTS, FL_DRAWINGS, FL_ECO1, FL_ECO2,
+ FL_RENDER, FL_GRID, FL_VIRT,
FL_LAST
};
- double m_Beginx, m_Beginy; /* position of mouse */
- double m_Quat[4]; /* orientation of object */
- double m_Rot[4]; /* man rotation of object */
- double m_Zoom; /* field of view in degrees */
- S3D_Color m_BgColor;
- bool m_DrawFlags[FL_LAST]; /* show these special items */
- wxPoint m_BoardPos;
- wxSize m_BoardSize;
- int m_Layers;
-
- const BOARD_DESIGN_SETTINGS* m_BoardSettings; // Link to current board design settings
-
- double m_Epoxy_Width; // Epoxy thickness (normalized)
-
- double m_BoardScale; /* Normalization scale for coordinates:
- * when scaled between -1.0 and +1.0 */
- double m_LayerZcoord[32];
- double m_ActZpos;
-
+ double m_Beginx, m_Beginy; /* position of mouse */
+ double m_Quat[4]; /* orientation of object */
+ double m_Rot[4]; /* man rotation of object */
+ double m_Zoom; /* field of view in degrees */
+ S3D_Color m_BgColor;
+ bool m_DrawFlags[FL_LAST]; /* show these special items */
+ wxPoint m_BoardPos;
+ wxSize m_BoardSize;
+ int m_Layers;
+
+ const BOARD_DESIGN_SETTINGS* m_BoardSettings; // Link to current board design settings
+
+ double m_Epoxy_Width; // Epoxy thickness (normalized)
+
+ double m_BoardScale; /* Normalization scale for coordinates:
+ * when scaled between -1.0 and +1.0 */
+ double m_LayerZcoord[32];
+ double m_ActZpos;
public: Info_3D_Visu();
~Info_3D_Visu();
};
@@ -171,76 +174,77 @@
private:
bool m_init;
GLuint m_gllist;
- /// Tracks whether to use Orthographic or Perspective projection
- // TODO: Does this belong here, or in EDA_3D_FRAME ???
+ // / Tracks whether to use Orthographic or Perspective projection
+ // TODO: Does this belong here, or in EDA_3D_FRAME ???
bool m_ortho;
wxGLContext* m_glRC;
wxRealPoint m_draw3dOffset; // offset to draw the 3 mesh.
double m_ZBottom; // position of the back layer
double m_ZTop; // position of the front layer
-
-
public:
EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList = 0 );
~EDA_3D_CANVAS();
- EDA_3D_FRAME* Parent() { return (EDA_3D_FRAME*)GetParent(); }
+ EDA_3D_FRAME* Parent() { return (EDA_3D_FRAME*) GetParent(); }
- void ClearLists();
+ void ClearLists();
// Event functions:
- void OnPaint( wxPaintEvent& event );
- void OnEraseBackground( wxEraseEvent& event );
- void OnChar( wxKeyEvent& event );
- void OnMouseWheel( wxMouseEvent& event );
- void OnMouseMove( wxMouseEvent& event );
- void OnRightClick( wxMouseEvent& event );
- void OnPopUpMenu( wxCommandEvent& event );
- void TakeScreenshot( wxCommandEvent& event );
- void OnEnterWindow( wxMouseEvent& event );
+ void OnPaint( wxPaintEvent& event );
+ void OnEraseBackground( wxEraseEvent& event );
+ void OnChar( wxKeyEvent& event );
+ void OnMouseWheel( wxMouseEvent& event );
+ void OnMouseMove( wxMouseEvent& event );
+ void OnRightClick( wxMouseEvent& event );
+ void OnPopUpMenu( wxCommandEvent& event );
+ void TakeScreenshot( wxCommandEvent& event );
+ void OnEnterWindow( wxMouseEvent& event );
// Display functions
- GLuint DisplayCubeforTest(); // Just a test function
- void SetView3D( int keycode );
- void DisplayStatus();
- void Redraw( bool finish = false );
- void Render();
+ GLuint DisplayCubeforTest(); // Just a test function
+ void SetView3D( int keycode );
+ void DisplayStatus();
+ void Redraw( bool finish = false );
+ void Render();
/**
* Function CreateDrawGL_List
* creates the OpenGL draw list items.
*/
- GLuint CreateDrawGL_List();
- void InitGL();
- void SetLights();
- void SetOffset(double aPosX, double aPosY)
+ GLuint CreateDrawGL_List();
+ void InitGL();
+ void SetLights();
+
+ void SetOffset( double aPosX, double aPosY )
{
- m_draw3dOffset.x = aPosX;
- m_draw3dOffset.y = aPosY;
+ m_draw3dOffset.x = aPosX;
+ m_draw3dOffset.y = aPosY;
}
- void Draw3D_Track( TRACK* track );
+
+ void Draw3D_Track( TRACK* track );
/**
* Function Draw3D_SolidPolygonsInZones
* draw all solid polygons used as filled areas in a zone
* @param aZone = the zone to draw
- */
- void Draw3D_SolidPolygonsInZones( ZONE_CONTAINER* aZone );
+ */
+ void Draw3D_SolidPolygonsInZones( ZONE_CONTAINER* aZone );
/**
* Function Draw3D_Polygon
* draw one solid polygon
* @param aCornersList = a std::vector<wxPoint> list of corners, in physical coordinates
* @param aZpos = the z position in 3D units
- */
- void Draw3D_Polygon( std::vector<wxPoint>& aCornersList, double aZpos );
+ */
+ void Draw3D_Polygon( std::vector<wxPoint>& aCornersList, double aZpos );
/**
* Function Draw3D_Via
* draws 3D via as a cylinder and filled circles.
*/
- void Draw3D_Via( SEGVIA* via );
- void Draw3D_DrawSegment( DRAWSEGMENT* segment );
+ void Draw3D_Via( SEGVIA* via );
+ void Draw3D_DrawSegment( DRAWSEGMENT* segment );
+ void Draw3D_DrawSegmentMask( DRAWSEGMENT* segment, int layer, std::vector<CPolyPt> *le_data );
/**
* Function Draw3D_DrawText
@@ -253,16 +257,24 @@
* Using DrawGraphicText to draw all texts ensure texts have the same shape
* in all contexts
*/
- void Draw3D_DrawText( TEXTE_PCB* text );
-
- /// Toggles orthographic projection on and off
- void ToggleOrtho(){ m_ortho = !m_ortho ; Refresh(true);};
-
- /// Returns the orthographic projection flag
- bool ModeIsOrtho() { return m_ortho ;};
-
-
- //int Get3DLayerEnable(int act_layer);
+ void Draw3D_DrawText( TEXTE_PCB* text );
+ void Draw3D_DrawTextMask( TEXTE_PCB* text, int layer, GLUtesselator* tess );
+ void Draw3D_DrawText( TEXTE_MODULE* text, double rot );
+
+ // / Toggles orthographic projection on and off
+ void ToggleOrtho() { m_ortho = !m_ortho; Refresh( true ); };
+
+ // / Returns the orthographic projection flag
+ bool ModeIsOrtho() { return m_ortho; };
+
+
+ // int Get3DLayerEnable(int act_layer);
+ // GLUtesselator* Get_mftess() { return mftess; };
+ // GLUtesselator* Get_mbtess() { return mbtess; };
+ // int Get_tmonly() { return tmonly; };
+ // void Set_mftess(GLUtesselator* tess) { mftess = tess; };
+ // void Set_mbtess(GLUtesselator* tess) { mbtess = tess; };
+ // void Set_tmonly(int i) { tmonly = i; };
DECLARE_EVENT_TABLE()
};
@@ -280,7 +292,6 @@
wxSize m_FrameSize;
wxAuiManager m_auimgr;
bool m_reloadRequest;
-
public:
EDA_3D_FRAME( PCB_BASE_FRAME* parent, const wxString& title,
long style = KICAD_DEFAULT_3D_DRAWFRAME_STYLE );
@@ -289,15 +300,15 @@
m_auimgr.UnInit();
};
- PCB_BASE_FRAME* Parent() { return (PCB_BASE_FRAME*)GetParent(); }
- void Exit3DFrame( wxCommandEvent& event );
- void OnCloseWindow( wxCloseEvent& Event );
- void ReCreateMenuBar();
- void ReCreateHToolbar();
- void ReCreateVToolbar();
- void SetToolbars();
- void GetSettings();
- void SaveSettings();
+ PCB_BASE_FRAME* Parent() { return (PCB_BASE_FRAME*) GetParent(); }
+ void Exit3DFrame( wxCommandEvent& event );
+ void OnCloseWindow( wxCloseEvent& Event );
+ void ReCreateMenuBar();
+ void ReCreateHToolbar();
+ void ReCreateVToolbar();
+ void SetToolbars();
+ void GetSettings();
+ void SaveSettings();
/**
* Function ReloadRequest
@@ -305,30 +316,30 @@
* mainly after edition of the board or footprint being displayed.
* mainly for the module editor.
*/
- void ReloadRequest( )
+ void ReloadRequest()
{
m_reloadRequest = true;
}
- void OnLeftClick( wxDC* DC, const wxPoint& MousePos );
- void OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu );
- void OnKeyEvent( wxKeyEvent& event );
- double BestZoom();
- void RedrawActiveWindow( wxDC* DC, bool EraseBg );
- void Process_Special_Functions( wxCommandEvent& event );
- void Process_Zoom( wxCommandEvent& event );
- void OnActivate( wxActivateEvent& event );
+ void OnLeftClick( wxDC* DC, const wxPoint& MousePos );
+ void OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu );
+ void OnKeyEvent( wxKeyEvent& event );
+ double BestZoom();
+ void RedrawActiveWindow( wxDC* DC, bool EraseBg );
+ void Process_Special_Functions( wxCommandEvent& event );
+ void Process_Zoom( wxCommandEvent& event );
+ void OnActivate( wxActivateEvent& event );
- void NewDisplay();
- void Set3DBgColor();
+ void NewDisplay();
+ void Set3DBgColor();
DECLARE_EVENT_TABLE()
};
-void SetGLColor( int color );
-void Set_Object_Data( std::vector< S3D_Vertex >& aVertices );
+void SetGLColor( int color );
+void Set_Object_Data( std::vector<S3D_Vertex>& aVertices );
extern Info_3D_Visu g_Parm_3D_Visu;
extern double DataScale3D; // 3D scale units.
-#endif /* __3D_VIEWER_H__ */
+#endif /* __3D_VIEWER_H__ */
=== modified file '3d-viewer/trackball.cpp'
--- 3d-viewer/trackball.cpp 2012-01-23 04:33:36 +0000
+++ 3d-viewer/trackball.cpp 2012-06-03 20:16:21 +0000
@@ -60,90 +60,91 @@
* simple example, though, so that is left as an Exercise for the
* Programmer.
*/
-#define TRACKBALLSIZE (0.8f)
+#define TRACKBALLSIZE (0.8f)
/*
* Local function prototypes (not defined in trackball.h)
*/
-static double tb_project_to_sphere(double, double, double);
-static void normalize_quat(double [4]);
-
-void
-vzero(double *v)
-{
- v[0] = 0.0;
- v[1] = 0.0;
- v[2] = 0.0;
-}
-
-void
-vset(double *v, double x, double y, double z)
-{
- v[0] = x;
- v[1] = y;
- v[2] = z;
-}
-
-void
-vsub(const double *src1, const double *src2, double *dst)
-{
- dst[0] = src1[0] - src2[0];
- dst[1] = src1[1] - src2[1];
- dst[2] = src1[2] - src2[2];
-}
-
-void
-vcopy(const double *v1, double *v2)
+static double tb_project_to_sphere( double, double, double );
+static void normalize_quat( double[4] );
+
+void vzero( double* v )
+{
+ v[0] = 0.0;
+ v[1] = 0.0;
+ v[2] = 0.0;
+}
+
+
+void vset( double* v, double x, double y, double z )
+{
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+}
+
+
+void vsub( const double* src1, const double* src2, double* dst )
+{
+ dst[0] = src1[0] - src2[0];
+ dst[1] = src1[1] - src2[1];
+ dst[2] = src1[2] - src2[2];
+}
+
+
+void vcopy( const double* v1, double* v2 )
{
register int i;
- for (i = 0 ; i < 3 ; i++)
+
+ for( i = 0; i < 3; i++ )
v2[i] = v1[i];
}
-void
-vcross(const double *v1, const double *v2, double *cross)
+
+void vcross( const double* v1, const double* v2, double* cross )
{
double temp[3];
temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]);
temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]);
temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]);
- vcopy(temp, cross);
-}
-
-double
-vlength(const double *v)
-{
- return (double) sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
-}
-
-void
-vscale(double *v, double div)
-{
- v[0] *= div;
- v[1] *= div;
- v[2] *= div;
-}
-
-void
-vnormal(double *v)
-{
- vscale(v, 1.0f/vlength(v));
-}
-
-double
-vdot(const double *v1, const double *v2)
-{
- return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
-}
-
-void
-vadd(const double *src1, const double *src2, double *dst)
-{
- dst[0] = src1[0] + src2[0];
- dst[1] = src1[1] + src2[1];
- dst[2] = src1[2] + src2[2];
-}
+ vcopy( temp, cross );
+}
+
+
+double vlength( const double* v )
+{
+ return (double) sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );
+}
+
+
+void vscale( double* v, double div )
+{
+ v[0] *= div;
+ v[1] *= div;
+ v[2] *= div;
+}
+
+
+void vnormal( double* v )
+{
+ vscale( v, 1.0f / vlength( v ) );
+}
+
+
+double vdot( const double* v1, const double* v2 )
+{
+ return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
+}
+
+
+void vadd( const double* src1, const double* src2, double* dst )
+{
+ dst[0] = src1[0] + src2[0];
+ dst[1] = src1[1] + src2[1];
+ dst[2] = src1[2] + src2[2];
+}
+
/*
* Ok, simulate a track-ball. Project the points onto the virtual
@@ -157,17 +158,17 @@
* It is assumed that the arguments to this routine are in the range
* (-1.0 ... 1.0)
*/
-void
-trackball(double q[4], double p1x, double p1y, double p2x, double p2y)
+void trackball( double q[4], double p1x, double p1y, double p2x, double p2y )
{
- double a[3]; /* Axis of rotation */
- double phi; /* how much to rotate about axis */
- double p1[3], p2[3], d[3];
- double t;
+ double a[3]; /* Axis of rotation */
+ double phi; /* how much to rotate about axis */
+ double p1[3], p2[3], d[3];
+ double t;
- if (p1x == p2x && p1y == p2y) {
+ if( p1x == p2x && p1y == p2y )
+ {
/* Zero rotation */
- vzero(q);
+ vzero( q );
q[3] = 1.0;
return;
}
@@ -176,61 +177,71 @@
* First, figure out z-coordinates for projection of P1 and P2 to
* deformed sphere
*/
- vset(p1, p1x, p1y, tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y));
- vset(p2, p2x, p2y, tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y));
+ vset( p1, p1x, p1y, tb_project_to_sphere( TRACKBALLSIZE, p1x, p1y ) );
+ vset( p2, p2x, p2y, tb_project_to_sphere( TRACKBALLSIZE, p2x, p2y ) );
/*
* Now, we want the cross product of P1 and P2
*/
- vcross(p2,p1,a);
+ vcross( p2, p1, a );
/*
* Figure out how much to rotate around that axis.
*/
- vsub(p1, p2, d);
- t = vlength(d) / (2.0f*TRACKBALLSIZE);
+ vsub( p1, p2, d );
+ t = vlength( d ) / (2.0f * TRACKBALLSIZE);
/*
* Avoid problems with out-of-control values...
*/
- if (t > 1.0) t = 1.0;
- if (t < -1.0) t = -1.0;
- phi = 2.0f * (double) asin(t);
-
- axis_to_quat(a,phi,q);
+ if( t > 1.0 )
+ t = 1.0;
+
+ if( t < -1.0 )
+ t = -1.0;
+
+ phi = 2.0f * (double) asin( t );
+
+ axis_to_quat( a, phi, q );
}
+
/*
* Given an axis and angle, compute quaternion.
*/
-void
-axis_to_quat(double a[3], double phi, double q[4])
+void axis_to_quat( double a[3], double phi, double q[4] )
{
- vnormal(a);
- vcopy(a, q);
- vscale(q, (double) sin(phi/2.0));
- q[3] = (double) cos(phi/2.0);
+ vnormal( a );
+ vcopy( a, q );
+ vscale( q, (double) sin( phi / 2.0 ) );
+ q[3] = (double) cos( phi / 2.0 );
}
+
/*
* Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
* if we are away from the center of the sphere.
*/
-static double
-tb_project_to_sphere(double r, double x, double y)
+static double tb_project_to_sphere( double r, double x, double y )
{
double d, t, z;
- d = (double) sqrt(x*x + y*y);
- if (d < r * 0.70710678118654752440) { /* Inside sphere */
- z = (double) sqrt(r*r - d*d);
- } else { /* On hyperbola */
- t = r / 1.41421356237309504880f;
- z = t*t / d;
- }
+ d = (double) sqrt( x * x + y * y );
+
+ if( d < r * 0.70710678118654752440 ) /* Inside sphere */
+ {
+ z = (double) sqrt( r * r - d * d );
+ }
+ else /* On hyperbola */
+ {
+ t = r / 1.41421356237309504880f;
+ z = t * t / d;
+ }
+
return z;
}
+
/*
* Given two rotations, e1 and e2, expressed as quaternion rotations,
* figure out the equivalent single rotation and stuff it into dest.
@@ -244,35 +255,36 @@
#define RENORMCOUNT 97
-void
-add_quats(double q1[4], double q2[4], double dest[4])
+void add_quats( double q1[4], double q2[4], double dest[4] )
{
- static int count=0;
- double t1[4], t2[4], t3[4];
- double tf[4];
-
- vcopy(q1,t1);
- vscale(t1,q2[3]);
-
- vcopy(q2,t2);
- vscale(t2,q1[3]);
-
- vcross(q2,q1,t3);
- vadd(t1,t2,tf);
- vadd(t3,tf,tf);
- tf[3] = q1[3] * q2[3] - vdot(q1,q2);
+ static int count = 0;
+ double t1[4], t2[4], t3[4];
+ double tf[4];
+
+ vcopy( q1, t1 );
+ vscale( t1, q2[3] );
+
+ vcopy( q2, t2 );
+ vscale( t2, q1[3] );
+
+ vcross( q2, q1, t3 );
+ vadd( t1, t2, tf );
+ vadd( t3, tf, tf );
+ tf[3] = q1[3] * q2[3] - vdot( q1, q2 );
dest[0] = tf[0];
dest[1] = tf[1];
dest[2] = tf[2];
dest[3] = tf[3];
- if (++count > RENORMCOUNT) {
+ if( ++count > RENORMCOUNT )
+ {
count = 0;
- normalize_quat(dest);
+ normalize_quat( dest );
}
}
+
/*
* Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0
* If they don't add up to 1.0, dividing by their magnitued will
@@ -285,20 +297,23 @@
* - Pletinckx, D., Quaternion calculus as a basic tool in computer
* graphics, The Visual Computer 5, 2-13, 1989.
*/
-static void normalize_quat(double q[4])
+static void normalize_quat( double q[4] )
{
- int i;
- double mag;
-
- mag = (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
- for (i = 0; i < 4; i++) q[i] /= mag;
+ int i;
+ double mag;
+
+ mag = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
+
+ for( i = 0; i < 4; i++ )
+ q[i] /= mag;
}
+
/*
* Build a rotation matrix, given a quaternion rotation.
*
*/
-void build_rotmatrix(GLfloat m[4][4], double q[4])
+void build_rotmatrix( GLfloat m[4][4], double q[4] )
{
m[0][0] = 1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]);
m[0][1] = 2.0f * (q[0] * q[1] - q[2] * q[3]);
@@ -306,7 +321,7 @@
m[0][3] = 0.0f;
m[1][0] = 2.0f * (q[0] * q[1] + q[2] * q[3]);
- m[1][1]= 1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]);
+ m[1][1] = 1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]);
m[1][2] = 2.0f * (q[1] * q[2] - q[0] * q[3]);
m[1][3] = 0.0f;
@@ -320,4 +335,3 @@
m[3][2] = 0.0f;
m[3][3] = 1.0f;
}
-
=== modified file '3d-viewer/trackball.h'
--- 3d-viewer/trackball.h 2008-10-30 10:55:46 +0000
+++ 3d-viewer/trackball.h 2012-06-03 20:16:21 +0000
@@ -47,7 +47,7 @@
* The resulting rotation is returned as a quaternion rotation in the
* first paramater.
*/
-void trackball(double q[4], double p1x, double p1y, double p2x, double p2y);
+void trackball( double q[4], double p1x, double p1y, double p2x, double p2y );
/*
* Given two quaternions, add them together to get a third quaternion.
@@ -57,18 +57,17 @@
* rotation, the second and third the total rotation (which will be
* over-written with the resulting new total rotation).
*/
-void add_quats(double *q1, double *q2, double *dest);
+void add_quats( double* q1, double* q2, double* dest );
/*
* A useful function, builds a rotation matrix in Matrix based on
* given quaternion.
*/
-void build_rotmatrix(GLfloat m[4][4], double q[4]);
+void build_rotmatrix( GLfloat m[4][4], double q[4] );
/*
* This function computes a quaternion based on an axis (defined by
* the given vector) and an angle about which to rotate. The angle is
* expressed in radians. The result is put into the third argument.
*/
-void axis_to_quat(double a[3], double phi, double q[4]);
-
+void axis_to_quat( double a[3], double phi, double q[4] );