Compare commits
123 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fa85cb3a8b | |||
| 853984120c | |||
| be62a1ade6 | |||
| 3b4cdd96ab | |||
| f776b7c3fb | |||
| 9d233b4cdb | |||
| 19c54933c1 | |||
| 7aca6174d6 | |||
| 5f98fc0591 | |||
| bcdcaa724d | |||
| 32f24289bd | |||
| 021320be1b | |||
| e309ca10d1 | |||
| a65b7963d1 | |||
| 26c5485be9 | |||
| 48d2ac15d5 | |||
| 2ab90d6d20 | |||
| 81cc0b4c42 | |||
| 95b84f4a8d | |||
| 6c25b29e9f | |||
| 1f6789e692 | |||
| e4307a86cc | |||
| ce181e6e0a | |||
| 4212d99c3d | |||
| 535f3ae006 | |||
| 90ed0183c8 | |||
| 2bb695b767 | |||
| c980e6999a | |||
| 1e7ba6c644 | |||
| 53f6bf29c7 | |||
| 8e4098f3f1 | |||
| 7179a71cdc | |||
| 606978297d | |||
| 648b7d53b5 | |||
| 93c5e5e4aa | |||
| 7940f0773c | |||
| 226d56433c | |||
| 5cf68726d6 | |||
| 3c233ae08e | |||
| 9810236314 | |||
| 7dbf84a9bd | |||
| b73a71c696 | |||
| e4e635d3b5 | |||
| 2ffdc0d03d | |||
| 91f34a9478 | |||
| 67ab1be495 | |||
| fdc4d2a8a9 | |||
| 72f19ded75 | |||
| 3c8bed9c92 | |||
| 6a33549b68 | |||
| ab99c58ead | |||
| c8daccbe0e | |||
| b6dedd9f5b | |||
| fd054f566e | |||
| 4a665f492e | |||
| a0d41f75ff | |||
| 5f72cca19a | |||
| 8191327fc2 | |||
| a19a52398a | |||
| f3d173fe64 | |||
| 3076e98b29 | |||
| 1d55823fef | |||
| 62475d0464 | |||
| 1060d4ac6e | |||
| 44038c47c6 | |||
| fef0759155 | |||
| 16dbe11868 | |||
| 68725bc20c | |||
| 963b4d5ed6 | |||
| 6657981553 | |||
| 286f6a426b | |||
| cc058033cc | |||
| 18f07d8efb | |||
| 6d3e1b9391 | |||
| 79fe4a0acb | |||
| 5c4fbbec43 | |||
| 7d0299f153 | |||
| e9570fddd6 | |||
| 34217c0199 | |||
| ab0e3d0ce2 | |||
| c8b2971d1c | |||
| 9b0bd7ca1f | |||
| fd009f924a | |||
| 48e2addd69 | |||
| a773ecc735 | |||
| dcd81e23f4 | |||
| bff0068065 | |||
| d0932944fc | |||
| 5c3a56bdcc | |||
| e9bfcc28c3 | |||
| 3cdac44ac2 | |||
| 2cebaa2d79 | |||
| 609b996abe | |||
| ea0c187e09 | |||
| bf6cd8445a | |||
| c50763bd5b | |||
| 1aa6932b12 | |||
| 342ec2be0e | |||
| d451800d0a | |||
| 48435c5cb3 | |||
| 8999ae9fb2 | |||
| 8184ba1cf3 | |||
| 228ed4ea41 | |||
| 3031a3f5cf | |||
| 42aa93e34b | |||
| eb8b407717 | |||
| eaea15fbef | |||
| 72a69f9428 | |||
| c66656c5d4 | |||
| 14363262c2 | |||
| 509e71fdb3 | |||
| 6c5e2f3900 | |||
| f46272bed9 | |||
| 2f7b3ab56e | |||
| b526227529 | |||
| e93c815e02 | |||
| 5c8f7c7a3a | |||
| 7fb6698e29 | |||
| f11b426151 | |||
| 827dad3197 | |||
| 593c974063 | |||
| a68b3cb486 | |||
| ce81524b83 |
+50
@@ -0,0 +1,50 @@
|
||||
boost_root
|
||||
.downloads-by-cmake
|
||||
Build
|
||||
build
|
||||
common/netlist_keywords.*
|
||||
common/netlist_lexer.h
|
||||
common/pcb_plot_params_lexer.h
|
||||
common/page_layout/page_layout_reader_keywords.cpp
|
||||
common/fp_lib_table_keywords.*
|
||||
common/gal/opengl/shader_src.h
|
||||
include/fp_lib_table_lexer.h
|
||||
include/netlist_lexer.h
|
||||
include/page_layout_reader_lexer.h
|
||||
eeschema/cmp_library_lexer.h
|
||||
eeschema/cmp_library_keywords.*
|
||||
eeschema/dialogs/dialog_bom_cfg_keywords.cpp
|
||||
eeschema/dialogs/dialog_bom_cfg_lexer.h
|
||||
eeschema/dialogs/dialog_bom_help_html.h
|
||||
eeschema/template_fieldnames_keywords.*
|
||||
eeschema/template_fieldnames_lexer.h
|
||||
pcbnew/dialogs/dialog_freeroute_exchange_help_html.h
|
||||
pcbnew/pcb_plot_params_keywords.cpp
|
||||
pcbnew/pcb_plot_params_lexer.h
|
||||
Makefile
|
||||
CMakeCache.txt
|
||||
auto_renamed_to_cpp
|
||||
Testing
|
||||
version.h
|
||||
config.h
|
||||
install_manifest.txt
|
||||
Documentation/doxygen
|
||||
Documentation/development/doxygen
|
||||
*.bak
|
||||
.*.swp
|
||||
*.~*
|
||||
common/pcb_plot_params_keywords.cpp
|
||||
include/pcb_plot_params_lexer.h
|
||||
pcbnew/specctra_keywords.cpp
|
||||
pcbnew/specctra_lexer.h
|
||||
pcb_calculator/pcb_calculator_datafile_keywords.cpp
|
||||
pcb_calculator/pcb_calculator_datafile_lexer.h
|
||||
new/html
|
||||
new/sch_lib_table_keywords.cpp
|
||||
new/sch_lib_table_lexer.h
|
||||
new/sweet_keywords.cpp
|
||||
new/sweet_lexer.h
|
||||
bitmaps_png/png*
|
||||
bitmaps_png/tmp
|
||||
common/pcb_keywords.cpp
|
||||
include/pcb_lexer.h
|
||||
@@ -0,0 +1,2 @@
|
||||
[core]
|
||||
excludesfile .bzrignore
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
boost_root
|
||||
.downloads-by-cmake
|
||||
Build*
|
||||
build*
|
||||
common/fp_lib_table_keywords.cpp
|
||||
common/netlist_keywords.*
|
||||
common/netlist_lexer.h
|
||||
common/pcb_plot_params_lexer.h
|
||||
common/page_layout/page_layout_reader_keywords.cpp
|
||||
common/lib_table_keywords.*
|
||||
common/gal/opengl/shader_src.h
|
||||
include/fp_lib_table_lexer.h
|
||||
include/lib_table_lexer.h
|
||||
include/netlist_lexer.h
|
||||
include/page_layout_reader_lexer.h
|
||||
eeschema/cmp_library_lexer.h
|
||||
eeschema/cmp_library_keywords.*
|
||||
eeschema/dialogs/dialog_bom_cfg_keywords.cpp
|
||||
eeschema/dialogs/dialog_bom_cfg_lexer.h
|
||||
eeschema/dialogs/dialog_bom_help_html.h
|
||||
eeschema/template_fieldnames_keywords.*
|
||||
eeschema/template_fieldnames_lexer.h
|
||||
pcbnew/dialogs/dialog_freeroute_exchange_help_html.h
|
||||
pcbnew/pcb_plot_params_keywords.cpp
|
||||
pcbnew/pcb_plot_params_lexer.h
|
||||
pcb_calculator/attenuators/bridget_tee_formula.h
|
||||
pcb_calculator/attenuators/pi_formula.h
|
||||
pcb_calculator/attenuators/splitter_formula.h
|
||||
pcb_calculator/attenuators/tee_formula.h
|
||||
Makefile
|
||||
CMakeCache.txt
|
||||
auto_renamed_to_cpp
|
||||
Testing
|
||||
version.h
|
||||
config.h
|
||||
install_manifest.txt
|
||||
Documentation/doxygen
|
||||
Documentation/development/doxygen
|
||||
*.bak
|
||||
*.pyc
|
||||
common/pcb_plot_params_keywords.cpp
|
||||
include/pcb_plot_params_lexer.h
|
||||
pcbnew/specctra_import_export/specctra_keywords.cpp
|
||||
pcbnew/specctra_import_export/specctra_lexer.h
|
||||
pcb_calculator/pcb_calculator_datafile_keywords.cpp
|
||||
pcb_calculator/pcb_calculator_datafile_lexer.h
|
||||
new/html
|
||||
new/sch_lib_table_keywords.cpp
|
||||
new/sch_lib_table_lexer.h
|
||||
new/sweet_keywords.cpp
|
||||
new/sweet_lexer.h
|
||||
bitmaps_png/png*
|
||||
bitmaps_png/tmp
|
||||
common/pcb_keywords.cpp
|
||||
include/pcb_lexer.h
|
||||
|
||||
# demo project auxillary files
|
||||
demos/**/*-bak
|
||||
demos/**/_autosave-*
|
||||
|
||||
# editor/OS fluff
|
||||
.*.swp
|
||||
*~
|
||||
.idea
|
||||
.DS_Store
|
||||
*.png
|
||||
*.kiface
|
||||
*.o
|
||||
*.a
|
||||
*.cmake
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.old
|
||||
*.gch
|
||||
*.orig
|
||||
*.patch
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_aux.cpp
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
|
||||
#include <common.h>
|
||||
#include <trigo.h>
|
||||
#include <wxBasePcbFrame.h>
|
||||
|
||||
#include <class_board_design_settings.h>
|
||||
#include <class_zone.h>
|
||||
#include <class_text_mod.h>
|
||||
#include <class_module.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_pcb_text.h>
|
||||
|
||||
#include <3d_viewer.h>
|
||||
#include <3d_canvas.h>
|
||||
#include <info3d_visu.h>
|
||||
#include <trackball.h>
|
||||
|
||||
|
||||
void S3D_MASTER::ObjectCoordsTo3DUnits( std::vector< S3D_VERTEX >& aVertices )
|
||||
{
|
||||
/* adjust object scale, rotation and offset position */
|
||||
for( unsigned ii = 0; ii < aVertices.size(); ii++ )
|
||||
{
|
||||
aVertices[ii].x *= m_MatScale.x;
|
||||
aVertices[ii].y *= m_MatScale.y;
|
||||
aVertices[ii].z *= m_MatScale.z;
|
||||
|
||||
// adjust rotation
|
||||
if( m_MatRotation.x )
|
||||
{
|
||||
double a = aVertices[ii].y;
|
||||
double b = aVertices[ii].z;
|
||||
RotatePoint( &a, &b, m_MatRotation.x * 10 );
|
||||
aVertices[ii].y = (float)a;
|
||||
aVertices[ii].z = (float)b;
|
||||
}
|
||||
|
||||
if( m_MatRotation.y )
|
||||
{
|
||||
double a = aVertices[ii].z;
|
||||
double b = aVertices[ii].x;
|
||||
RotatePoint( &a, &b, m_MatRotation.x * 10 );
|
||||
aVertices[ii].z = (float)a;
|
||||
aVertices[ii].x = (float)b;
|
||||
}
|
||||
|
||||
if( m_MatRotation.z )
|
||||
{
|
||||
double a = aVertices[ii].x;
|
||||
double b = aVertices[ii].y;
|
||||
RotatePoint( &a, &b, m_MatRotation.x * 10 );
|
||||
aVertices[ii].x = (float)a;
|
||||
aVertices[ii].y = (float)b;
|
||||
}
|
||||
|
||||
/* adjust offset position (offset is given in UNIT 3D (0.1 inch) */
|
||||
aVertices[ii].x += m_MatPosition.x * SCALE_3D_CONV;
|
||||
aVertices[ii].y += m_MatPosition.y * SCALE_3D_CONV;
|
||||
aVertices[ii].z += m_MatPosition.z * SCALE_3D_CONV;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TransfertToGLlist( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUnits )
|
||||
{
|
||||
unsigned ii;
|
||||
GLfloat ax, ay, az, bx, by, bz, nx, ny, nz, r;
|
||||
|
||||
/* ignore faces with less than 3 points */
|
||||
if( aVertices.size() < 3 )
|
||||
return;
|
||||
|
||||
/* calculate normal direction */
|
||||
ax = aVertices[1].x - aVertices[0].x;
|
||||
ay = aVertices[1].y - aVertices[0].y;
|
||||
az = aVertices[1].z - aVertices[0].z;
|
||||
|
||||
bx = aVertices[2].x - aVertices[0].x;
|
||||
by = aVertices[2].y - aVertices[0].y;
|
||||
bz = aVertices[2].z - aVertices[0].z;
|
||||
|
||||
nx = ay * bz - az * by;
|
||||
ny = az * bx - ax * bz;
|
||||
nz = ax * by - ay * bx;
|
||||
|
||||
r = sqrt( nx * nx + ny * ny + nz * nz );
|
||||
|
||||
if( r >= 0.000001 ) /* avoid division by zero */
|
||||
{
|
||||
nx /= r;
|
||||
ny /= r;
|
||||
nz /= r;
|
||||
glNormal3f( nx, ny, nz );
|
||||
}
|
||||
|
||||
/* glBegin/glEnd */
|
||||
switch( aVertices.size() )
|
||||
{
|
||||
case 3:
|
||||
glBegin( GL_TRIANGLES );
|
||||
break;
|
||||
|
||||
case 4:
|
||||
glBegin( GL_QUADS );
|
||||
break;
|
||||
|
||||
default:
|
||||
glBegin( GL_POLYGON );
|
||||
break;
|
||||
}
|
||||
|
||||
/* draw polygon/triangle/quad */
|
||||
for( ii = 0; ii < aVertices.size(); ii++ )
|
||||
{
|
||||
glVertex3d( aVertices[ii].x * aBiuTo3DUnits,
|
||||
aVertices[ii].y * aBiuTo3DUnits,
|
||||
aVertices[ii].z * aBiuTo3DUnits );
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
S3DPOINT_VALUE_CTRL::S3DPOINT_VALUE_CTRL( wxWindow* aParent, wxBoxSizer* aBoxSizer )
|
||||
{
|
||||
wxString text;
|
||||
|
||||
wxFlexGridSizer* gridSizer = new wxFlexGridSizer( 0, 2, 0, 0 );
|
||||
gridSizer->AddGrowableCol( 1 );
|
||||
gridSizer->SetFlexibleDirection( wxHORIZONTAL );
|
||||
gridSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
aBoxSizer->Add( gridSizer, 0, wxEXPAND, 5 );
|
||||
|
||||
wxStaticText* msgtitle = new wxStaticText( aParent, wxID_ANY, wxT( "X:" ) );
|
||||
gridSizer->Add( msgtitle, 0, wxALL , 5 );
|
||||
|
||||
m_XValueCtrl = new wxTextCtrl( aParent, wxID_ANY, wxEmptyString,
|
||||
wxDefaultPosition,wxDefaultSize, 0 );
|
||||
gridSizer->Add( m_XValueCtrl, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
msgtitle = new wxStaticText( aParent, wxID_ANY, wxT( "Y:" ), wxDefaultPosition,
|
||||
wxDefaultSize, 0 );
|
||||
gridSizer->Add( msgtitle, 0, wxALL, 5 );
|
||||
|
||||
m_YValueCtrl = new wxTextCtrl( aParent, wxID_ANY, wxEmptyString,
|
||||
wxDefaultPosition, wxDefaultSize, 0 );
|
||||
gridSizer->Add( m_YValueCtrl, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
msgtitle = new wxStaticText( aParent, wxID_ANY, wxT( "Z:" ), wxDefaultPosition,
|
||||
wxDefaultSize, 0 );
|
||||
gridSizer->Add( msgtitle, 0, wxALL, 5 );
|
||||
|
||||
m_ZValueCtrl = new wxTextCtrl( aParent, wxID_ANY, wxEmptyString,
|
||||
wxDefaultPosition, wxDefaultSize, 0 );
|
||||
gridSizer->Add( m_ZValueCtrl, 0, wxALL|wxEXPAND, 5 );
|
||||
}
|
||||
|
||||
|
||||
S3DPOINT_VALUE_CTRL::~S3DPOINT_VALUE_CTRL()
|
||||
{
|
||||
// Nothing to delete: all items are managed by the parent window.
|
||||
}
|
||||
|
||||
|
||||
S3DPOINT S3DPOINT_VALUE_CTRL::GetValue()
|
||||
{
|
||||
S3DPOINT value;
|
||||
double dtmp;
|
||||
|
||||
m_XValueCtrl->GetValue().ToDouble( &dtmp );
|
||||
value.x = dtmp;
|
||||
m_YValueCtrl->GetValue().ToDouble( &dtmp );
|
||||
value.y = dtmp;
|
||||
m_ZValueCtrl->GetValue().ToDouble( &dtmp );
|
||||
value.z = dtmp;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void S3DPOINT_VALUE_CTRL::SetValue( S3DPOINT vertex )
|
||||
{
|
||||
wxString text;
|
||||
|
||||
text.Printf( wxT( "%f" ), vertex.x );
|
||||
m_XValueCtrl->Clear();
|
||||
m_XValueCtrl->AppendText( text );
|
||||
|
||||
text.Printf( wxT( "%f" ), vertex.y );
|
||||
m_YValueCtrl->Clear();
|
||||
m_YValueCtrl->AppendText( text );
|
||||
|
||||
text.Printf( wxT( "%f" ), vertex.z );
|
||||
m_ZValueCtrl->Clear();
|
||||
m_ZValueCtrl->AppendText( text );
|
||||
}
|
||||
|
||||
|
||||
void S3DPOINT_VALUE_CTRL::Enable( bool onoff )
|
||||
{
|
||||
m_XValueCtrl->Enable( onoff );
|
||||
m_YValueCtrl->Enable( onoff );
|
||||
m_ZValueCtrl->Enable( onoff );
|
||||
}
|
||||
@@ -1,774 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
|
||||
#include <wx/datetime.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdpaths.h>
|
||||
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#if BOOST_VERSION >= 106800
|
||||
#include <boost/uuid/detail/sha1.hpp>
|
||||
#else
|
||||
#include <boost/uuid/sha1.hpp>
|
||||
#endif
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/ext.hpp>
|
||||
|
||||
#include "common.h"
|
||||
#include "3d_cache.h"
|
||||
#include "3d_info.h"
|
||||
#include "sg/scenegraph.h"
|
||||
#include "3d_filename_resolver.h"
|
||||
#include "3d_plugin_manager.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
|
||||
|
||||
#define MASK_3D_CACHE "3D_CACHE"
|
||||
|
||||
static wxCriticalSection lock3D_cache;
|
||||
|
||||
|
||||
static bool isSHA1Same( const unsigned char* shaA, const unsigned char* shaB )
|
||||
{
|
||||
for( int i = 0; i < 20; ++i )
|
||||
if( shaA[i] != shaB[i] )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool checkTag( const char* aTag, void* aPluginMgrPtr )
|
||||
{
|
||||
if( NULL == aTag || NULL == aPluginMgrPtr )
|
||||
return false;
|
||||
|
||||
S3D_PLUGIN_MANAGER *pp = (S3D_PLUGIN_MANAGER*) aPluginMgrPtr;
|
||||
|
||||
return pp->CheckTag( aTag );
|
||||
}
|
||||
|
||||
|
||||
static const wxString sha1ToWXString( const unsigned char* aSHA1Sum )
|
||||
{
|
||||
unsigned char uc;
|
||||
unsigned char tmp;
|
||||
char sha1[41];
|
||||
int j = 0;
|
||||
|
||||
for( int i = 0; i < 20; ++i )
|
||||
{
|
||||
uc = aSHA1Sum[i];
|
||||
tmp = uc / 16;
|
||||
|
||||
if( tmp > 9 )
|
||||
tmp += 87;
|
||||
else
|
||||
tmp += 48;
|
||||
|
||||
sha1[j++] = tmp;
|
||||
tmp = uc % 16;
|
||||
|
||||
if( tmp > 9 )
|
||||
tmp += 87;
|
||||
else
|
||||
tmp += 48;
|
||||
|
||||
sha1[j++] = tmp;
|
||||
}
|
||||
|
||||
sha1[j] = 0;
|
||||
|
||||
return wxString::FromUTF8Unchecked( sha1 );
|
||||
}
|
||||
|
||||
|
||||
class S3D_CACHE_ENTRY
|
||||
{
|
||||
private:
|
||||
// prohibit assignment and default copy constructor
|
||||
S3D_CACHE_ENTRY( const S3D_CACHE_ENTRY& source );
|
||||
S3D_CACHE_ENTRY& operator=( const S3D_CACHE_ENTRY& source );
|
||||
|
||||
wxString m_CacheBaseName; // base name of cache file (a SHA1 digest)
|
||||
|
||||
public:
|
||||
S3D_CACHE_ENTRY();
|
||||
~S3D_CACHE_ENTRY();
|
||||
|
||||
void SetSHA1( const unsigned char* aSHA1Sum );
|
||||
const wxString GetCacheBaseName( void );
|
||||
|
||||
wxDateTime modTime; // file modification time
|
||||
unsigned char sha1sum[20];
|
||||
std::string pluginInfo; // PluginName:Version string
|
||||
SCENEGRAPH* sceneData;
|
||||
S3DMODEL* renderData;
|
||||
};
|
||||
|
||||
|
||||
S3D_CACHE_ENTRY::S3D_CACHE_ENTRY()
|
||||
{
|
||||
sceneData = NULL;
|
||||
renderData = NULL;
|
||||
memset( sha1sum, 0, 20 );
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE_ENTRY::~S3D_CACHE_ENTRY()
|
||||
{
|
||||
if( NULL != sceneData )
|
||||
delete sceneData;
|
||||
|
||||
if( NULL != renderData )
|
||||
S3D::Destroy3DModel( &renderData );
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE_ENTRY::SetSHA1( const unsigned char* aSHA1Sum )
|
||||
{
|
||||
if( NULL == aSHA1Sum )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] NULL passed for aSHA1Sum",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy( sha1sum, aSHA1Sum, 20 );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const wxString S3D_CACHE_ENTRY::GetCacheBaseName( void )
|
||||
{
|
||||
if( m_CacheBaseName.empty() )
|
||||
m_CacheBaseName = sha1ToWXString( sha1sum );
|
||||
|
||||
return m_CacheBaseName;
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE::S3D_CACHE()
|
||||
{
|
||||
m_DirtyCache = false;
|
||||
m_FNResolver = new S3D_FILENAME_RESOLVER;
|
||||
m_Plugins = new S3D_PLUGIN_MANAGER;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE::~S3D_CACHE()
|
||||
{
|
||||
FlushCache();
|
||||
|
||||
if( m_FNResolver )
|
||||
delete m_FNResolver;
|
||||
|
||||
if( m_Plugins )
|
||||
delete m_Plugins;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr )
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = NULL;
|
||||
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile );
|
||||
|
||||
if( full3Dpath.empty() )
|
||||
{
|
||||
// the model cannot be found; we cannot proceed
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [3D model] could not find model '%s'\n",
|
||||
__FILE__, __FUNCTION__, __LINE__, aModelFile );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check cache if file is already loaded
|
||||
wxCriticalSectionLocker lock( lock3D_cache );
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, S3D::rsort_wxString >::iterator mi;
|
||||
mi = m_CacheMap.find( full3Dpath );
|
||||
|
||||
if( mi != m_CacheMap.end() )
|
||||
{
|
||||
wxFileName fname( full3Dpath );
|
||||
|
||||
if( fname.FileExists() ) // Only check if file exists. If not, it will
|
||||
{ // use the same model in cache.
|
||||
bool reload = false;
|
||||
wxDateTime fmdate = fname.GetModificationTime();
|
||||
|
||||
if( fmdate != mi->second->modTime )
|
||||
{
|
||||
unsigned char hashSum[20];
|
||||
getSHA1( full3Dpath, hashSum );
|
||||
mi->second->modTime = fmdate;
|
||||
|
||||
if( !isSHA1Same( hashSum, mi->second->sha1sum ) )
|
||||
{
|
||||
mi->second->SetSHA1( hashSum );
|
||||
reload = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( reload )
|
||||
{
|
||||
if( NULL != mi->second->sceneData )
|
||||
{
|
||||
S3D::DestroyNode( mi->second->sceneData );
|
||||
mi->second->sceneData = NULL;
|
||||
}
|
||||
|
||||
if( NULL != mi->second->renderData )
|
||||
S3D::Destroy3DModel( &mi->second->renderData );
|
||||
|
||||
mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath, mi->second->pluginInfo );
|
||||
}
|
||||
}
|
||||
|
||||
if( NULL != aCachePtr )
|
||||
*aCachePtr = mi->second;
|
||||
|
||||
return mi->second->sceneData;
|
||||
}
|
||||
|
||||
// a cache item does not exist; search the Filename->Cachename map
|
||||
return checkCache( full3Dpath, aCachePtr );
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile )
|
||||
{
|
||||
return load( aModelFile );
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr )
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = NULL;
|
||||
|
||||
unsigned char sha1sum[20];
|
||||
|
||||
if( !getSHA1( aFileName, sha1sum ) || m_CacheDir.empty() )
|
||||
{
|
||||
// just in case we can't get a hash digest (for example, on access issues)
|
||||
// or we do not have a configured cache file directory, we create an
|
||||
// entry to prevent further attempts at loading the file
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
wxFileName fname( aFileName );
|
||||
ep->modTime = fname.GetModificationTime();
|
||||
|
||||
if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
|
||||
( aFileName, ep ) ).second == false )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
m_CacheList.pop_back();
|
||||
delete ep;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = ep;
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
wxFileName fname( aFileName );
|
||||
ep->modTime = fname.GetModificationTime();
|
||||
|
||||
if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
|
||||
( aFileName, ep ) ).second == false )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
m_CacheList.pop_back();
|
||||
delete ep;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( aCachePtr )
|
||||
*aCachePtr = ep;
|
||||
|
||||
ep->SetSHA1( sha1sum );
|
||||
|
||||
wxString bname = ep->GetCacheBaseName();
|
||||
wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
|
||||
|
||||
if( wxFileName::FileExists( cachename ) && loadCacheData( ep ) )
|
||||
return ep->sceneData;
|
||||
|
||||
ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
|
||||
|
||||
if( NULL != ep->sceneData )
|
||||
saveCacheData( ep );
|
||||
|
||||
return ep->sceneData;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum )
|
||||
{
|
||||
if( aFileName.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] empty filename",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == aSHA1Sum )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n * [BUG] NULL pointer passed for aMD5Sum",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
|
||||
#else
|
||||
FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
|
||||
#endif
|
||||
|
||||
if( NULL == fp )
|
||||
return false;
|
||||
|
||||
boost::uuids::detail::sha1 dblock;
|
||||
unsigned char block[4096];
|
||||
size_t bsize = 0;
|
||||
|
||||
while( ( bsize = fread( &block, 1, 4096, fp ) ) > 0 )
|
||||
dblock.process_bytes( block, bsize );
|
||||
|
||||
fclose( fp );
|
||||
unsigned int digest[5];
|
||||
dblock.get_digest( digest );
|
||||
|
||||
// ensure MSB order
|
||||
for( int i = 0; i < 5; ++i )
|
||||
{
|
||||
int idx = i << 2;
|
||||
unsigned int tmp = digest[i];
|
||||
aSHA1Sum[idx+3] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
aSHA1Sum[idx+2] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
aSHA1Sum[idx+1] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
aSHA1Sum[idx] = tmp & 0xff;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
{
|
||||
wxString bname = aCacheItem->GetCacheBaseName();
|
||||
|
||||
if( bname.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
" * [3D model] cannot load cached model; no file hash available" );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( m_CacheDir.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
" * [3D model] cannot load cached model; config directory unknown" );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString fname = m_CacheDir + bname + wxT( ".3dc" );
|
||||
|
||||
if( !wxFileName::FileExists( fname ) )
|
||||
{
|
||||
wxString errmsg = "cannot open file";
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] %s '%s'", errmsg.GetData(), fname.GetData() );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL != aCacheItem->sceneData )
|
||||
S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
|
||||
|
||||
aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
|
||||
|
||||
if( NULL == aCacheItem->sceneData )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
{
|
||||
if( NULL == aCacheItem )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * NULL passed for aCacheItem",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == aCacheItem->sceneData )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * aCacheItem has no valid scene data",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString bname = aCacheItem->GetCacheBaseName();
|
||||
|
||||
if( bname.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
" * [3D model] cannot load cached model; no file hash available" );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( m_CacheDir.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
" * [3D model] cannot load cached model; config directory unknown" );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString fname = m_CacheDir + bname + wxT( ".3dc" );
|
||||
|
||||
if( wxFileName::Exists( fname ) )
|
||||
{
|
||||
if( !wxFileName::FileExists( fname ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] path exists but is not a regular file '%s'",
|
||||
fname );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData,
|
||||
aCacheItem->pluginInfo.c_str() );
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
{
|
||||
if( !m_ConfigDir.empty() )
|
||||
return false;
|
||||
|
||||
wxFileName cfgdir;
|
||||
|
||||
if( aConfigDir.StartsWith( "${" ) || aConfigDir.StartsWith( "$(" ) )
|
||||
cfgdir.Assign( ExpandEnvVarSubstitutions( aConfigDir ), "" );
|
||||
else
|
||||
cfgdir.Assign( aConfigDir, "" );
|
||||
|
||||
cfgdir.Normalize();
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
"%s:%s:%d\n * failed to create 3D configuration directory '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_ConfigDir = cfgdir.GetPath();
|
||||
|
||||
// inform the file resolver of the config directory
|
||||
if( !m_FNResolver->Set3DConfigDir( m_ConfigDir ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
"%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
|
||||
" * config directory: '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, m_ConfigDir );
|
||||
}
|
||||
|
||||
// 3D cache data must go to a user's cache directory;
|
||||
// unfortunately wxWidgets doesn't seem to provide
|
||||
// functions to retrieve such a directory.
|
||||
//
|
||||
// 1. OSX: ~/Library/Caches/kicad/3d/
|
||||
// 2. Linux: ${XDG_CACHE_HOME}/kicad/3d ~/.cache/kicad/3d/
|
||||
// 3. MSWin: AppData\Local\kicad\3d
|
||||
wxString cacheDir;
|
||||
|
||||
#if defined(_WIN32)
|
||||
wxStandardPaths::Get().UseAppInfo( wxStandardPaths::AppInfo_None );
|
||||
cacheDir = wxStandardPaths::Get().GetUserLocalDataDir();
|
||||
cacheDir.append( "\\kicad\\3d" );
|
||||
#elif defined(__APPLE)
|
||||
cacheDir = "${HOME}/Library/Caches/kicad/3d";
|
||||
#else // assume Linux
|
||||
cacheDir = ExpandEnvVarSubstitutions( "${XDG_CACHE_HOME}" );
|
||||
|
||||
if( cacheDir.empty() || cacheDir == "${XDG_CACHE_HOME}" )
|
||||
cacheDir = "${HOME}/.cache";
|
||||
|
||||
cacheDir.append( "/kicad/3d" );
|
||||
#endif
|
||||
|
||||
cacheDir = ExpandEnvVarSubstitutions( cacheDir );
|
||||
cfgdir.Assign( cacheDir, "" );
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * failed to create 3D cache directory '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_CacheDir = cfgdir.GetPathWithSep();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_CACHE::Get3DConfigDir( bool createDefault )
|
||||
{
|
||||
if( !m_ConfigDir.empty() || !createDefault )
|
||||
return m_ConfigDir;
|
||||
|
||||
// note: duplicated from common/common.cpp GetKicadConfigPath() to avoid
|
||||
// code coupling; ideally the instantiating code should call
|
||||
// Set3DConfigDir() to set the directory rather than relying on this
|
||||
// directory remaining the same in future KiCad releases.
|
||||
wxFileName cfgpath;
|
||||
|
||||
// From the wxWidgets wxStandardPaths::GetUserConfigDir() help:
|
||||
// Unix: ~ (the home directory)
|
||||
// Windows: "C:\Documents and Settings\username\Application Data"
|
||||
// Mac: ~/Library/Preferences
|
||||
cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
|
||||
|
||||
#if !defined( __WINDOWS__ ) && !defined( __WXMAC__ )
|
||||
wxString envstr = ExpandEnvVarSubstitutions( "${XDG_CONFIG_HOME}" );
|
||||
|
||||
if( envstr.IsEmpty() || envstr == "${XDG_CONFIG_HOME}" )
|
||||
{
|
||||
// XDG_CONFIG_HOME is not set, so use the fallback
|
||||
cfgpath.AppendDir( wxT( ".config" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Override the assignment above with XDG_CONFIG_HOME
|
||||
cfgpath.AssignDir( envstr );
|
||||
}
|
||||
#endif
|
||||
|
||||
cfgpath.AppendDir( wxT( "kicad" ) );
|
||||
cfgpath.AppendDir( wxT( "3d" ) );
|
||||
|
||||
if( !cfgpath.DirExists() )
|
||||
{
|
||||
cfgpath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
}
|
||||
|
||||
if( !cfgpath.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * failed to create 3D configuration directory '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgpath.GetPath() );
|
||||
|
||||
return wxT( "" );
|
||||
}
|
||||
|
||||
if( Set3DConfigDir( cfgpath.GetPath() ) )
|
||||
return m_ConfigDir;
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::SetProjectDir( const wxString& aProjDir )
|
||||
{
|
||||
bool hasChanged = false;
|
||||
|
||||
if( m_FNResolver->SetProjectDir( aProjDir, &hasChanged ) && hasChanged )
|
||||
{
|
||||
m_CacheMap.clear();
|
||||
|
||||
std::list< S3D_CACHE_ENTRY* >::iterator sL = m_CacheList.begin();
|
||||
std::list< S3D_CACHE_ENTRY* >::iterator eL = m_CacheList.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
delete *sL;
|
||||
++sL;
|
||||
}
|
||||
|
||||
m_CacheList.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE::SetProgramBase( PGM_BASE* aBase )
|
||||
{
|
||||
m_FNResolver->SetProgramBase( aBase );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_CACHE::GetProjectDir( void )
|
||||
{
|
||||
return m_FNResolver->GetProjectDir();
|
||||
}
|
||||
|
||||
|
||||
S3D_FILENAME_RESOLVER* S3D_CACHE::GetResolver( void )
|
||||
{
|
||||
return m_FNResolver;
|
||||
}
|
||||
|
||||
|
||||
std::list< wxString > const* S3D_CACHE::GetFileFilters( void ) const
|
||||
{
|
||||
return m_Plugins->GetFileFilters();
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE::FlushCache( bool closePlugins )
|
||||
{
|
||||
std::list< S3D_CACHE_ENTRY* >::iterator sCL = m_CacheList.begin();
|
||||
std::list< S3D_CACHE_ENTRY* >::iterator eCL = m_CacheList.end();
|
||||
|
||||
while( sCL != eCL )
|
||||
{
|
||||
delete *sCL;
|
||||
++sCL;
|
||||
}
|
||||
|
||||
m_CacheList.clear();
|
||||
m_CacheMap.clear();
|
||||
|
||||
if( closePlugins )
|
||||
ClosePlugins();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE::ClosePlugins( void )
|
||||
{
|
||||
if( NULL != m_Plugins )
|
||||
m_Plugins->ClosePlugins();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName )
|
||||
{
|
||||
S3D_CACHE_ENTRY* cp = NULL;
|
||||
SCENEGRAPH* sp = load( aModelFileName, &cp );
|
||||
|
||||
if( !sp )
|
||||
return NULL;
|
||||
|
||||
if( !cp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
"%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( cp->renderData )
|
||||
return cp->renderData;
|
||||
|
||||
S3DMODEL* mp = S3D::GetModel( sp );
|
||||
cp->renderData = mp;
|
||||
|
||||
return mp;
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_CACHE::GetModelHash( const wxString& aModelFileName )
|
||||
{
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFileName );
|
||||
|
||||
if( full3Dpath.empty() || !wxFileName::FileExists( full3Dpath ) )
|
||||
return wxEmptyString;
|
||||
|
||||
// check cache if file is already loaded
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, S3D::rsort_wxString >::iterator mi;
|
||||
mi = m_CacheMap.find( full3Dpath );
|
||||
|
||||
if( mi != m_CacheMap.end() )
|
||||
return mi->second->GetCacheBaseName();
|
||||
|
||||
// a cache item does not exist; search the Filename->Cachename map
|
||||
S3D_CACHE_ENTRY* cp = NULL;
|
||||
checkCache( full3Dpath, &cp );
|
||||
|
||||
if( NULL != cp )
|
||||
return cp->GetCacheBaseName();
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_cache.h
|
||||
* defines the display data cache manager for 3D models
|
||||
*/
|
||||
|
||||
#ifndef CACHE_3D_H
|
||||
#define CACHE_3D_H
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <wx/string.h>
|
||||
#include "str_rsort.h"
|
||||
#include "3d_filename_resolver.h"
|
||||
#include "3d_info.h"
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
|
||||
|
||||
class PGM_BASE;
|
||||
class S3D_CACHE;
|
||||
class S3D_CACHE_ENTRY;
|
||||
class SCENEGRAPH;
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
class S3D_PLUGIN_MANAGER;
|
||||
|
||||
|
||||
class S3D_CACHE
|
||||
{
|
||||
private:
|
||||
/// cache entries
|
||||
std::list< S3D_CACHE_ENTRY* > m_CacheList;
|
||||
|
||||
/// mapping of file names to cache names and data
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, S3D::rsort_wxString > m_CacheMap;
|
||||
|
||||
/// object to resolve file names
|
||||
S3D_FILENAME_RESOLVER* m_FNResolver;
|
||||
|
||||
/// plugin manager
|
||||
S3D_PLUGIN_MANAGER* m_Plugins;
|
||||
|
||||
/// set true if the cache needs to be updated
|
||||
bool m_DirtyCache;
|
||||
|
||||
/// 3D cache directory
|
||||
wxString m_CacheDir;
|
||||
|
||||
/// base configuration path for 3D items
|
||||
wxString m_ConfigDir;
|
||||
|
||||
/// current KiCad project dir
|
||||
wxString m_ProjDir;
|
||||
|
||||
/** Find or create cache entry for file name
|
||||
*
|
||||
* Searches the cache list for the given filename and retrieves
|
||||
* the cache data; a cache entry is created if one does not
|
||||
* already exist.
|
||||
*
|
||||
* @param[in] aFileName file name (full or partial path)
|
||||
* @param[out] aCachePtr optional return address for cache entry pointer
|
||||
* @return SCENEGRAPH object associated with file name
|
||||
* @retval NULL on error
|
||||
*/
|
||||
SCENEGRAPH* checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr = NULL );
|
||||
|
||||
/**
|
||||
* Function getSHA1
|
||||
* calculates the SHA1 hash of the given file
|
||||
*
|
||||
* @param[in] aFileName file name (full path)
|
||||
* @param[out] aSHA1Sum a 20 byte character array to hold the SHA1 hash
|
||||
* @retval true success
|
||||
* @retval false failure
|
||||
*/
|
||||
bool getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum );
|
||||
|
||||
// load scene data from a cache file
|
||||
bool loadCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||
|
||||
// save scene data to a cache file
|
||||
bool saveCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||
|
||||
// the real load function (can supply a cache entry pointer to member functions)
|
||||
SCENEGRAPH* load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr = NULL );
|
||||
|
||||
public:
|
||||
S3D_CACHE();
|
||||
virtual ~S3D_CACHE();
|
||||
|
||||
/**
|
||||
* Function Set3DConfigDir
|
||||
* Sets the configuration directory to be used by the
|
||||
* model manager for storing 3D model manager configuration
|
||||
* data and the model cache. The config directory may only be
|
||||
* set once in the lifetime of the object.
|
||||
*
|
||||
* @param aConfigDir is the configuration directory to use
|
||||
* for 3D model manager data
|
||||
* @return true on success
|
||||
*/
|
||||
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||
|
||||
/**
|
||||
* Function Get3DConfigDir
|
||||
* returns the current 3D configuration directory on
|
||||
* success, otherwise it returns wxEmptyString. If the
|
||||
* directory was not previously set via Set3DConfigDir()
|
||||
* then a default is used which is based on kicad's
|
||||
* configuration directory code as of September 2015.
|
||||
*/
|
||||
wxString Get3DConfigDir( bool createDefault = false );
|
||||
|
||||
/**
|
||||
* Function SetProjectDir
|
||||
* sets the current project's working directory; this
|
||||
* affects the model search path
|
||||
*/
|
||||
bool SetProjectDir( const wxString& aProjDir );
|
||||
|
||||
/**
|
||||
* Function SetProgramBase
|
||||
* sets the filename resolver's pointer to the application's
|
||||
* PGM_BASE instance; the pointer is used to extract the
|
||||
* local env vars.
|
||||
*/
|
||||
void SetProgramBase( PGM_BASE* aBase );
|
||||
|
||||
/**
|
||||
* Function GetProjectDir
|
||||
* returns the current project's working directory
|
||||
*/
|
||||
wxString GetProjectDir( void );
|
||||
|
||||
/**
|
||||
* Function Load
|
||||
* attempts to load the scene data for a model; it will consult the
|
||||
* internal cache list and load from cache if possible before invoking
|
||||
* the load() function of the available plugins.
|
||||
*
|
||||
* @param aModelFile [in] is the partial or full path to the model to be loaded
|
||||
* @return true if the model was successfully loaded, otherwise false.
|
||||
* The model may fail to load if, for example, the plugin does not
|
||||
* support rendering of the 3D model.
|
||||
*/
|
||||
SCENEGRAPH* Load( const wxString& aModelFile );
|
||||
|
||||
S3D_FILENAME_RESOLVER* GetResolver( void );
|
||||
|
||||
/**
|
||||
* Function GetFileFilters
|
||||
* returns the list of file filters retrieved from the plugins;
|
||||
* this will contain at least the default "All Files (*.*)|*.*"
|
||||
*
|
||||
* @return a pointer to the filter list
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters( void ) const;
|
||||
|
||||
/**
|
||||
* Function FlushCache
|
||||
* frees all data in the cache and by default closes all plugins
|
||||
*/
|
||||
void FlushCache( bool closePlugins = true );
|
||||
|
||||
/**
|
||||
* Function ClosePlugins
|
||||
* unloads plugins to free memory
|
||||
*/
|
||||
void ClosePlugins( void );
|
||||
|
||||
/**
|
||||
* Function GetModel
|
||||
* attempts to load the scene data for a model and to translate it
|
||||
* into an S3D_MODEL structure for display by a renderer
|
||||
*
|
||||
* @param aModelFileName is the full path to the model to be loaded
|
||||
* @return is a pointer to the render data or NULL if not available
|
||||
*/
|
||||
S3DMODEL* GetModel( const wxString& aModelFileName );
|
||||
|
||||
wxString GetModelHash( const wxString& aModelFileName );
|
||||
};
|
||||
|
||||
#endif // CACHE_3D_H
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <common.h>
|
||||
#include <pgm_base.h>
|
||||
#include "3d_cache_wrapper.h"
|
||||
|
||||
static wxCriticalSection lock3D_wrapper;
|
||||
|
||||
CACHE_WRAPPER::CACHE_WRAPPER()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CACHE_WRAPPER::~CACHE_WRAPPER()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE* PROJECT::Get3DCacheManager( bool updateProjDir )
|
||||
{
|
||||
wxCriticalSectionLocker lock( lock3D_wrapper );
|
||||
CACHE_WRAPPER* cw = (CACHE_WRAPPER*) GetElem( ELEM_3DCACHE );
|
||||
S3D_CACHE* cache = dynamic_cast<S3D_CACHE*>( cw );
|
||||
|
||||
// check that we get the expected type of object or NULL
|
||||
wxASSERT( !cw || cache );
|
||||
|
||||
if( !cw )
|
||||
{
|
||||
cw = new CACHE_WRAPPER;
|
||||
cache = dynamic_cast<S3D_CACHE*>( cw );
|
||||
|
||||
wxFileName cfgpath;
|
||||
cfgpath.AssignDir( GetKicadConfigPath() );
|
||||
cfgpath.AppendDir( wxT( "3d" ) );
|
||||
cache->SetProgramBase( &Pgm() );
|
||||
cache->Set3DConfigDir( cfgpath.GetFullPath() );
|
||||
SetElem( ELEM_3DCACHE, cw );
|
||||
updateProjDir = true;
|
||||
}
|
||||
|
||||
if( updateProjDir )
|
||||
cache->SetProjectDir( GetProjectPath() );
|
||||
|
||||
return cache;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CACHE_WRAPPER_3D_H
|
||||
#define CACHE_WRAPPER_3D_H
|
||||
|
||||
#include <project.h>
|
||||
#include "3d_cache.h"
|
||||
|
||||
class CACHE_WRAPPER : public S3D_CACHE, public PROJECT::_ELEM
|
||||
{
|
||||
public:
|
||||
CACHE_WRAPPER();
|
||||
virtual ~CACHE_WRAPPER();
|
||||
};
|
||||
|
||||
#endif // CACHE_WRAPPER_3D_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_filename_resolver.h
|
||||
* provides an extensible class to resolve 3D model paths. Initially
|
||||
* the legacy behavior will be implemented and an incomplete path
|
||||
* would be checked against the project directory or the KISYS3DMOD
|
||||
* environment variable. In the future a configurable set of search
|
||||
* paths may be specified.
|
||||
*/
|
||||
|
||||
#ifndef FILENAME_RESOLVER_3D_H
|
||||
#define FILENAME_RESOLVER_3D_H
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <wx/string.h>
|
||||
#include "str_rsort.h"
|
||||
|
||||
class PGM_BASE;
|
||||
|
||||
struct S3D_ALIAS
|
||||
{
|
||||
wxString m_alias; // alias to the base path
|
||||
wxString m_pathvar; // base path as stored in the config file
|
||||
wxString m_pathexp; // expanded base path
|
||||
wxString m_description; // description of the aliased path
|
||||
};
|
||||
|
||||
class S3D_FILENAME_RESOLVER
|
||||
{
|
||||
private:
|
||||
wxString m_ConfigDir; // 3D configuration directory
|
||||
std::list< S3D_ALIAS > m_Paths; // list of base paths to search from
|
||||
int m_errflags;
|
||||
PGM_BASE* m_pgm;
|
||||
wxString m_curProjDir;
|
||||
|
||||
/**
|
||||
* Function createPathList
|
||||
* builds the path list using available information such as
|
||||
* KISYS3DMOD and the 3d_path_list configuration file. Invalid
|
||||
* paths are silently discarded and removed from the configuration
|
||||
* file.
|
||||
*
|
||||
* @return true if at least one valid path was found
|
||||
*/
|
||||
bool createPathList( void );
|
||||
|
||||
/**
|
||||
* Function addPath
|
||||
* checks that a path is valid and adds it to the search list
|
||||
*
|
||||
* @param aPath is the alias set to be checked and added
|
||||
* @return true if aPath is valid
|
||||
*/
|
||||
bool addPath( const S3D_ALIAS& aPath );
|
||||
|
||||
/**
|
||||
* Function readPathList
|
||||
* reads a list of path names from a configuration file
|
||||
*
|
||||
* @return true if a file was found and contained at least
|
||||
* one valid path
|
||||
*/
|
||||
bool readPathList( void );
|
||||
|
||||
/**
|
||||
* Function writePathList
|
||||
* writes the current path list to a configuration file
|
||||
*
|
||||
* @return true if the path list was not empty and was
|
||||
* successfully written to the configuration file
|
||||
*/
|
||||
bool writePathList( void );
|
||||
|
||||
/**
|
||||
* Function checkEnvVarPath
|
||||
* checks the ${ENV_VAR} component of a path and adds
|
||||
* it to the resolver's path list if it is not yet in
|
||||
* the list
|
||||
*/
|
||||
void checkEnvVarPath( const wxString& aPath );
|
||||
|
||||
public:
|
||||
S3D_FILENAME_RESOLVER();
|
||||
|
||||
/**
|
||||
* Function Set3DConfigDir
|
||||
* sets the user's configuration directory
|
||||
* for 3D models.
|
||||
*
|
||||
* @param aConfigDir
|
||||
* @return true if the call succeeds (directory exists)
|
||||
*/
|
||||
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||
|
||||
/**
|
||||
* Function SetProjectDir
|
||||
* sets the current KiCad project directory as the first
|
||||
* entry in the model path list
|
||||
*
|
||||
* @param[in] aProjDir current project directory
|
||||
* @param[out] flgChanged optional, set to true if directory was changed
|
||||
* @retval true success
|
||||
* @retval false failure
|
||||
*/
|
||||
bool SetProjectDir( const wxString& aProjDir, bool* flgChanged = NULL );
|
||||
wxString GetProjectDir( void );
|
||||
|
||||
/**
|
||||
* Function SetProgramBase
|
||||
* sets a pointer to the application's PGM_BASE instance;
|
||||
* the pointer is used to extract the local env vars.
|
||||
*/
|
||||
void SetProgramBase( PGM_BASE* aBase );
|
||||
|
||||
|
||||
/**
|
||||
* Function UpdatePathList
|
||||
* clears the current path list and substitutes the given path
|
||||
* list, updating the path configuration file on success.
|
||||
*/
|
||||
bool UpdatePathList( std::vector< S3D_ALIAS >& aPathList );
|
||||
|
||||
/**
|
||||
* Function ResolvePath
|
||||
* determines the full path of the given file name. In the future
|
||||
* remote files may be supported, in which case it is best to
|
||||
* require a full URI in which case ResolvePath should check that
|
||||
* the URI conforms to RFC-2396 and related documents and copies
|
||||
* aFileName into aResolvedName if the URI is valid.
|
||||
*/
|
||||
wxString ResolvePath( const wxString& aFileName );
|
||||
|
||||
/**
|
||||
* Function ShortenPath
|
||||
* produces a relative path based on the existing
|
||||
* search directories or returns the same path if
|
||||
* the path is not a superset of an existing search path.
|
||||
*
|
||||
* @param aFullPathName is an absolute path to shorten
|
||||
* @return the shortened path or aFullPathName
|
||||
*/
|
||||
wxString ShortenPath( const wxString& aFullPathName );
|
||||
|
||||
/**
|
||||
* Function GetPaths
|
||||
* returns a pointer to the internal path list; the items in:load
|
||||
*
|
||||
* the list can be used to set up the list of search paths
|
||||
* available to a 3D file browser.
|
||||
*
|
||||
* @return pointer to the internal path list
|
||||
*/
|
||||
const std::list< S3D_ALIAS >* GetPaths( void );
|
||||
|
||||
/**
|
||||
* Function SplitAlias
|
||||
* returns true if the given name contains an alias and
|
||||
* populates the string anAlias with the alias and aRelPath
|
||||
* with the relative path.
|
||||
*/
|
||||
bool SplitAlias( const wxString& aFileName, wxString& anAlias, wxString& aRelPath );
|
||||
|
||||
/**
|
||||
* Function ValidateName
|
||||
* returns true if the given path is a valid aliased relative path.
|
||||
* If the path contains an alias then hasAlias is set true.
|
||||
*/
|
||||
bool ValidateFileName( const wxString& aFileName, bool& hasAlias );
|
||||
|
||||
/**
|
||||
* Function GetKicadPaths
|
||||
* returns a list of path environment variables local to Kicad;
|
||||
* this list always includes KISYS3DMOD even if it is not
|
||||
* defined locally.
|
||||
*/
|
||||
bool GetKicadPaths( std::list< wxString >& paths );
|
||||
};
|
||||
|
||||
#endif // FILENAME_RESOLVER_3D_H
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_info.h
|
||||
* defines the basic data associated with a single 3D model.
|
||||
*/
|
||||
|
||||
#ifndef INFO_3D_H
|
||||
#define INFO_3D_H
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <plugins/3dapi/sg_base.h>
|
||||
|
||||
class MODULE_3D_SETTINGS;
|
||||
|
||||
struct S3D_INFO
|
||||
{
|
||||
S3D_INFO();
|
||||
S3D_INFO( const MODULE_3D_SETTINGS& aModel );
|
||||
|
||||
SGPOINT m_Scale; ///< scaling factors for the 3D footprint shape
|
||||
SGPOINT m_Rotation; ///< an X,Y,Z rotation (unit = degrees) for the 3D shape
|
||||
SGPOINT m_Offset; ///< an offset (unit = inch) for the 3D shape
|
||||
wxString m_Filename; ///< The 3D shape filename in 3D library
|
||||
};
|
||||
|
||||
#endif // INFO_3D_H
|
||||
@@ -1,588 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <wx/config.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/dynlib.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdpaths.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "pgm_base.h"
|
||||
#include "3d_plugin_dir.h"
|
||||
#include "3d_plugin_manager.h"
|
||||
#include "plugins/3d/3d_plugin.h"
|
||||
#include "3d_cache/sg/scenegraph.h"
|
||||
#include "plugins/ldr/3d/pluginldr3D.h"
|
||||
|
||||
#define MASK_3D_PLUGINMGR "3D_PLUGIN_MANAGER"
|
||||
|
||||
|
||||
S3D_PLUGIN_MANAGER::S3D_PLUGIN_MANAGER()
|
||||
{
|
||||
// create the initial file filter list entry
|
||||
m_FileFilters.push_back( _( "All Files (*.*)|*.*" ) );
|
||||
|
||||
// discover and load plugins
|
||||
loadPlugins();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( !m_ExtMap.empty() )
|
||||
{
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::const_iterator sM = m_ExtMap.begin();
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::const_iterator eM = m_ExtMap.end();
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * Extension [plugin name]:\n" );
|
||||
|
||||
while( sM != eM )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " + '%s' [%s]\n", sM->first.GetData(),
|
||||
sM->second->GetKicadPluginName() );
|
||||
++sM;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * No plugins available\n" );
|
||||
}
|
||||
|
||||
|
||||
if( !m_FileFilters.empty() )
|
||||
{
|
||||
/// list of file filters
|
||||
std::list< wxString >::const_iterator sFF = m_FileFilters.begin();
|
||||
std::list< wxString >::const_iterator eFF = m_FileFilters.end();
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * File filters:\n" );
|
||||
|
||||
while( sFF != eFF )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " + '%s'\n", (*sFF).GetData() );
|
||||
++sFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * No file filters available\n" );
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D_PLUGIN_MANAGER::~S3D_PLUGIN_MANAGER()
|
||||
{
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator sP = m_Plugins.begin();
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator eP = m_Plugins.end();
|
||||
|
||||
while( sP != eP )
|
||||
{
|
||||
(*sP)->Close();
|
||||
delete *sP;
|
||||
++sP;
|
||||
}
|
||||
|
||||
m_Plugins.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
{
|
||||
std::list< wxString > searchpaths;
|
||||
std::list< wxString > pluginlist;
|
||||
wxFileName fn;
|
||||
|
||||
#ifndef __WXMAC__
|
||||
|
||||
#ifdef DEBUG
|
||||
// set up to work from the build directory
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
fn.AppendDir( wxT("..") );
|
||||
fn.AppendDir( wxT("plugins") );
|
||||
fn.AppendDir( wxT("3d") );
|
||||
|
||||
std::string testpath = std::string( fn.GetPathWithSep().ToUTF8() );
|
||||
checkPluginPath( testpath, searchpaths );
|
||||
|
||||
// add subdirectories too
|
||||
wxDir debugPluginDir;
|
||||
wxString subdir;
|
||||
|
||||
debugPluginDir.Open( testpath );
|
||||
|
||||
if( debugPluginDir.IsOpened() &&
|
||||
debugPluginDir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS ) )
|
||||
{
|
||||
checkPluginPath( testpath + subdir, searchpaths );
|
||||
|
||||
while( debugPluginDir.GetNext( &subdir ) )
|
||||
checkPluginPath( testpath + subdir, searchpaths );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
// multiarch friendly determination of the plugin directory: the executable dir
|
||||
// is first determined via wxStandardPaths::Get().GetExecutablePath() and then
|
||||
// the CMAKE_INSTALL_LIBDIR path is appended relative to the executable dir.
|
||||
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
fn.RemoveLastDir();
|
||||
wxString tfname = fn.GetPathWithSep();
|
||||
tfname.Append( wxString::FromUTF8Unchecked( PLUGINDIR ) );
|
||||
fn.Assign( tfname, "");
|
||||
fn.AppendDir( "kicad" );
|
||||
#else
|
||||
// on windows the plugins directory is within the executable's directory
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
#endif
|
||||
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
|
||||
// checks plugin directory relative to executable path
|
||||
checkPluginPath( std::string( fn.GetPathWithSep().ToUTF8() ), searchpaths );
|
||||
|
||||
// check for per-user third party plugins
|
||||
// note: GetUserDataDir() gives '.pcbnew' rather than '.kicad' since it uses the exe name;
|
||||
fn.Assign( wxStandardPaths::Get().GetUserDataDir(), "" );
|
||||
fn.RemoveLastDir();
|
||||
#ifdef _WIN32
|
||||
fn.AppendDir( wxT( "kicad" ) );
|
||||
#else
|
||||
fn.AppendDir( wxT( ".kicad" ) );
|
||||
#endif
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
|
||||
#else
|
||||
|
||||
// Search path on OS X is
|
||||
// (1) User ~/Library/Application Support/kicad/PlugIns/3d
|
||||
checkPluginPath( GetOSXKicadUserDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
// (2) Machine /Library/Application Support/kicad/PlugIns/3d
|
||||
checkPluginPath( GetOSXKicadMachineDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
// (3) Bundle kicad.app/Contents/PlugIns/3d
|
||||
fn.Assign( Pgm().GetExecutablePath() );
|
||||
fn.AppendDir( wxT( "Contents" ) );
|
||||
fn.AppendDir( wxT( "PlugIns" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
|
||||
#endif
|
||||
|
||||
std::list< wxString >::iterator sPL = searchpaths.begin();
|
||||
std::list< wxString >::iterator ePL = searchpaths.end();
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << " * [DEBUG] searching path: '" << (*sPL).ToUTF8() << "'";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
listPlugins( *sPL, pluginlist );
|
||||
++sPL;
|
||||
}
|
||||
|
||||
if( pluginlist.empty() )
|
||||
return;
|
||||
|
||||
sPL = pluginlist.begin();
|
||||
ePL = pluginlist.end();
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
KICAD_PLUGIN_LDR_3D* pp = new KICAD_PLUGIN_LDR_3D;
|
||||
|
||||
if( pp->Open( sPL->ToUTF8() ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << "* [DEBUG] adding plugin";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
m_Plugins.push_back( pp );
|
||||
int nf = pp->GetNFilters();
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] adding " << nf << " filters";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
for( int i = 0; i < nf; ++i )
|
||||
{
|
||||
char const* cp = pp->GetFileFilter( i );
|
||||
|
||||
if( cp )
|
||||
addFilterString( wxString::FromUTF8Unchecked( cp ) );
|
||||
}
|
||||
|
||||
addExtensionMap( pp );
|
||||
|
||||
// close the loaded library
|
||||
pp->Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << "* [DEBUG] deleting plugin";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
delete pp;
|
||||
}
|
||||
|
||||
++sPL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << "* [DEBUG] plugins loaded";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath,
|
||||
std::list< wxString >& aPluginList )
|
||||
{
|
||||
// list potential plugins given a search path
|
||||
|
||||
wxString nameFilter; // filter for user-loadable libraries (aka modules)
|
||||
wxString lName; // stores name of enumerated files
|
||||
wxString fName; // full name of file
|
||||
wxDir wd;
|
||||
wd.Open( aPath );
|
||||
|
||||
if( !wd.IsOpened() )
|
||||
return;
|
||||
|
||||
nameFilter = wxT( "*" );
|
||||
|
||||
#ifndef __WXMAC__
|
||||
nameFilter.Append( wxDynamicLibrary::GetDllExt( wxDL_MODULE ) );
|
||||
#else
|
||||
// wxDynamicLibrary::GetDllExt( wxDL_MODULE ) will return ".bundle" on OS X.
|
||||
// This might be correct, but cmake builds a ".so" for a library MODULE.
|
||||
// Per definition a loadable "xxx.bundle" is similar to an "xxx.app" app
|
||||
// bundle being a folder with some special content in it. We obviously don't
|
||||
// want to have that here for our loadable module, so just use ".so".
|
||||
nameFilter.Append( ".so" );
|
||||
#endif
|
||||
|
||||
wxString lp = wd.GetNameWithSep();
|
||||
|
||||
if( wd.GetFirst( &lName, nameFilter, wxDIR_FILES ) )
|
||||
{
|
||||
fName = lp + lName;
|
||||
checkPluginName( fName, aPluginList );
|
||||
|
||||
while( wd.GetNext( &lName ) )
|
||||
{
|
||||
fName = lp + lName;
|
||||
checkPluginName( fName, aPluginList );
|
||||
}
|
||||
}
|
||||
|
||||
wd.Close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
|
||||
std::list< wxString >& aPluginList )
|
||||
{
|
||||
// check the existence of a plugin name and add it to the list
|
||||
|
||||
if( aPath.empty() || !wxFileName::FileExists( aPath ) )
|
||||
return;
|
||||
|
||||
wxFileName path;
|
||||
|
||||
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
|
||||
path.Assign( ExpandEnvVarSubstitutions( aPath ) );
|
||||
else
|
||||
path.Assign( aPath );
|
||||
|
||||
path.Normalize();
|
||||
|
||||
// determine if the path is already in the list
|
||||
wxString wxpath = path.GetFullPath();
|
||||
std::list< wxString >::iterator bl = aPluginList.begin();
|
||||
std::list< wxString >::iterator el = aPluginList.end();
|
||||
|
||||
while( bl != el )
|
||||
{
|
||||
if( 0 == (*bl).Cmp( wxpath ) )
|
||||
return;
|
||||
|
||||
++bl;
|
||||
}
|
||||
|
||||
aPluginList.push_back( wxpath );
|
||||
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * [INFO] found 3D plugin '%s'\n",
|
||||
wxpath.GetData() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath,
|
||||
std::list< wxString >& aSearchList )
|
||||
{
|
||||
// check the existence of a path and add it to the path search list
|
||||
if( aPath.empty() )
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * [INFO] checking for 3D plugins in '%s'\n",
|
||||
aPath.GetData() );
|
||||
#endif
|
||||
|
||||
wxFileName path;
|
||||
|
||||
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
|
||||
path.Assign( ExpandEnvVarSubstitutions( aPath ), "" );
|
||||
else
|
||||
path.Assign( aPath, "" );
|
||||
|
||||
path.Normalize();
|
||||
|
||||
if( !wxFileName::DirExists( path.GetFullPath() ) )
|
||||
return;
|
||||
|
||||
// determine if the directory is already in the list
|
||||
wxString wxpath = path.GetFullPath();
|
||||
std::list< wxString >::iterator bl = aSearchList.begin();
|
||||
std::list< wxString >::iterator el = aSearchList.end();
|
||||
|
||||
while( bl != el )
|
||||
{
|
||||
if( 0 == (*bl).Cmp( wxpath ) )
|
||||
return;
|
||||
|
||||
++bl;
|
||||
}
|
||||
|
||||
aSearchList.push_back( wxpath );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::addFilterString( const wxString& aFilterString )
|
||||
{
|
||||
// add an entry to the file filter list
|
||||
if( aFilterString.empty() )
|
||||
return;
|
||||
|
||||
std::list< wxString >::iterator sFF = m_FileFilters.begin();
|
||||
std::list< wxString >::iterator eFF = m_FileFilters.end();
|
||||
|
||||
while( sFF != eFF )
|
||||
{
|
||||
if( 0 == (*sFF).Cmp( aFilterString ) )
|
||||
return;
|
||||
|
||||
++sFF;
|
||||
}
|
||||
|
||||
m_FileFilters.push_back( aFilterString );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin )
|
||||
{
|
||||
// add entries to the extension map
|
||||
if( NULL == aPlugin )
|
||||
return;
|
||||
|
||||
int nExt = aPlugin->GetNExtensions();
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] adding " << nExt << " extensions";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
for( int i = 0; i < nExt; ++i )
|
||||
{
|
||||
char const* cp = aPlugin->GetModelExtension( i );
|
||||
wxString ws;
|
||||
|
||||
if( cp )
|
||||
ws = wxString::FromUTF8Unchecked( cp );
|
||||
|
||||
if( !ws.empty() )
|
||||
{
|
||||
m_ExtMap.insert( std::pair< const wxString, KICAD_PLUGIN_LDR_3D* >( ws, aPlugin ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const
|
||||
{
|
||||
return &m_FileFilters;
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::string& aPluginInfo )
|
||||
{
|
||||
wxFileName raw( aFileName );
|
||||
wxString ext = raw.GetExt();
|
||||
|
||||
#ifdef WIN32
|
||||
// note: plugins only have a lowercase filter within Windows; including an uppercase
|
||||
// filter will result in duplicate file entries and should be avoided.
|
||||
ext.LowerCase();
|
||||
#endif
|
||||
|
||||
std::pair < std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator,
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator > items;
|
||||
|
||||
items = m_ExtMap.equal_range( ext );
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator sL = items.first;
|
||||
|
||||
while( sL != items.second )
|
||||
{
|
||||
if( sL->second->CanRender() )
|
||||
{
|
||||
SCENEGRAPH* sp = sL->second->Load( aFileName.ToUTF8() );
|
||||
|
||||
if( NULL != sp )
|
||||
{
|
||||
sL->second->GetPluginInfo( aPluginInfo );
|
||||
return sp;
|
||||
}
|
||||
}
|
||||
|
||||
++sL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::ClosePlugins( void )
|
||||
{
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator sP = m_Plugins.begin();
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator eP = m_Plugins.end();
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] closing " << m_Plugins.size() << " plugins";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
while( sP != eP )
|
||||
{
|
||||
(*sP)->Close();
|
||||
++sP;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_PLUGIN_MANAGER::CheckTag( const char* aTag )
|
||||
{
|
||||
if( NULL == aTag || aTag[0] == 0 || m_Plugins.empty() )
|
||||
return false;
|
||||
|
||||
std::string tname = aTag;
|
||||
std::string pname; // plugin name
|
||||
|
||||
size_t cpos = tname.find( ':' );
|
||||
|
||||
// if there is no colon or plugin name then the tag is bad
|
||||
if( cpos == std::string::npos || cpos == 0 )
|
||||
return false;
|
||||
|
||||
pname = tname.substr( 0, cpos );
|
||||
std::string ptag; // tag from the plugin
|
||||
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator pS = m_Plugins.begin();
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator pE = m_Plugins.end();
|
||||
|
||||
while( pS != pE )
|
||||
{
|
||||
ptag.clear();
|
||||
(*pS)->GetPluginInfo( ptag );
|
||||
|
||||
// if the plugin name matches then the version
|
||||
// must also match
|
||||
if( !ptag.compare( 0, pname.size(), pname ) )
|
||||
{
|
||||
if( ptag.compare( tname ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
++pS;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_plugin_manager.h
|
||||
* manages 3D model plugins
|
||||
*/
|
||||
|
||||
#ifndef PLUGIN_MANAGER_3D_H
|
||||
#define PLUGIN_MANAGER_3D_H
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <wx/string.h>
|
||||
|
||||
class wxWindow;
|
||||
class KICAD_PLUGIN_LDR_3D;
|
||||
class SCENEGRAPH;
|
||||
|
||||
class S3D_PLUGIN_MANAGER
|
||||
{
|
||||
private:
|
||||
/// list of discovered plugins
|
||||
std::list< KICAD_PLUGIN_LDR_3D* > m_Plugins;
|
||||
|
||||
/// mapping of extensions to available plugins
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* > m_ExtMap;
|
||||
|
||||
/// list of file filters
|
||||
std::list< wxString > m_FileFilters;
|
||||
|
||||
/// load plugins
|
||||
void loadPlugins( void );
|
||||
|
||||
/// list potential plugins
|
||||
void listPlugins( const wxString& aPath, std::list< wxString >& aPluginList );
|
||||
|
||||
/// check the existence of a plugin name and add it to the list
|
||||
void checkPluginName( const wxString& aPath, std::list< wxString >& aPluginList );
|
||||
|
||||
/// check the existence of a path and add it to the path search list
|
||||
void checkPluginPath( const wxString& aPath, std::list< wxString >& aSearchList );
|
||||
|
||||
/// add an entry to the file filter list
|
||||
void addFilterString( const wxString& aFilterString );
|
||||
|
||||
/// add entries to the extension map
|
||||
void addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin );
|
||||
|
||||
public:
|
||||
S3D_PLUGIN_MANAGER();
|
||||
virtual ~S3D_PLUGIN_MANAGER();
|
||||
|
||||
/**
|
||||
* Function GetFileFilters
|
||||
* returns the list of file filters; this will contain at least
|
||||
* the default "All Files (*.*)|*.*" and the file filters supported
|
||||
* by any available plugins
|
||||
*
|
||||
* @return a pointer to the internal filter list
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters( void ) const;
|
||||
|
||||
SCENEGRAPH* Load3DModel( const wxString& aFileName, std::string& aPluginInfo );
|
||||
|
||||
/**
|
||||
* Function ClosePlugins
|
||||
* iterates through all discovered plugins and closes them to
|
||||
* reclaim memory. The individual plugins will be automatically
|
||||
* reloaded as calls are made to load specific models.
|
||||
*/
|
||||
void ClosePlugins( void );
|
||||
|
||||
/**
|
||||
* Function CheckTag
|
||||
* checks the given tag and returns true if the plugin named in the tag
|
||||
* is not loaded or the plugin is loaded and the version matches
|
||||
*/
|
||||
bool CheckTag( const char* aTag );
|
||||
};
|
||||
|
||||
#endif // PLUGIN_MANAGER_3D_H
|
||||
@@ -1 +0,0 @@
|
||||
add_subdirectory( sg )
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <wx/filename.h>
|
||||
|
||||
#include "3d_info.h"
|
||||
#include "3d_cache.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
#include "3d_cache_dialogs.h"
|
||||
#include "dlg_3d_pathconfig.h"
|
||||
#include "dlg_select_3dmodel.h"
|
||||
|
||||
|
||||
bool S3D::Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard, MODULE_3D_SETTINGS* aModel )
|
||||
{
|
||||
if( NULL == aModel )
|
||||
return false;
|
||||
|
||||
DLG_SELECT_3DMODEL* dm = new DLG_SELECT_3DMODEL( aParent, aCache, aModel,
|
||||
prevModelSelectDir, prevModelWildcard );
|
||||
|
||||
if( wxID_OK == dm->ShowModal() )
|
||||
{
|
||||
delete dm;
|
||||
return true;
|
||||
}
|
||||
|
||||
delete dm;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::Configure3DPaths( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver )
|
||||
{
|
||||
DLG_3D_PATH_CONFIG* dp = new DLG_3D_PATH_CONFIG( aParent, aResolver );
|
||||
|
||||
if( wxID_OK == dp->ShowModal() )
|
||||
{
|
||||
delete dp;
|
||||
return true;
|
||||
}
|
||||
|
||||
delete dp;
|
||||
return false;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CACHE_DIALOGS_3D_H
|
||||
#define CACHE_DIALOGS_3D_H
|
||||
|
||||
#include <wx/window.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
bool Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard, MODULE_3D_SETTINGS* aModel );
|
||||
|
||||
bool Configure3DPaths( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver );
|
||||
}
|
||||
|
||||
#endif // CACHE_DIALOGS_3D_H
|
||||
@@ -1,383 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <wx/msgdlg.h>
|
||||
#include <pgm_base.h>
|
||||
#include <html_messagebox.h>
|
||||
#include "3d_cache/dialogs/dlg_3d_pathconfig.h"
|
||||
#include "3d_cache/3d_filename_resolver.h"
|
||||
|
||||
DLG_3D_PATH_CONFIG::DLG_3D_PATH_CONFIG( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver ) :
|
||||
DLG_3D_PATH_CONFIG_BASE( aParent ), m_resolver( aResolver )
|
||||
{
|
||||
initDialog();
|
||||
|
||||
GetSizer()->SetSizeHints( this );
|
||||
Centre();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::initDialog()
|
||||
{
|
||||
m_Aliases->EnableEditing( true );
|
||||
|
||||
// Gives a min width to each column, when the user drags a column
|
||||
m_Aliases->SetColMinimalWidth( 0, 80 );
|
||||
m_Aliases->SetColMinimalWidth( 1, 300 );
|
||||
m_Aliases->SetColMinimalWidth( 2, 120 );
|
||||
m_Aliases->SetColMinimalAcceptableWidth( 80 );
|
||||
|
||||
// Set column sizes to this min value
|
||||
m_Aliases->SetColSize( 0, 80 );
|
||||
m_Aliases->SetColSize( 1, 300 );
|
||||
m_Aliases->SetColSize( 2, 120 );
|
||||
|
||||
m_EnvVars->SetColMinimalWidth( 0, 80 );
|
||||
m_EnvVars->SetColMinimalWidth( 1, 300 );
|
||||
m_EnvVars->SetColMinimalAcceptableWidth( 80 );
|
||||
m_EnvVars->SetColSize( 0, 80 );
|
||||
m_EnvVars->SetColSize( 1, 300 );
|
||||
|
||||
if( m_resolver )
|
||||
{
|
||||
updateEnvVars();
|
||||
|
||||
// prohibit these characters in the alias names: []{}()%~<>"='`;:.,&?/\|$
|
||||
m_aliasValidator.SetStyle( wxFILTER_EXCLUDE_CHAR_LIST );
|
||||
m_aliasValidator.SetCharExcludes( wxT( "{}[]()%~<>\"='`;:.,&?/\\|$" ) );
|
||||
|
||||
const std::list< S3D_ALIAS >* rpaths = m_resolver->GetPaths();
|
||||
std::list< S3D_ALIAS >::const_iterator rI = rpaths->begin();
|
||||
std::list< S3D_ALIAS >::const_iterator rE = rpaths->end();
|
||||
size_t listsize = rpaths->size();
|
||||
size_t listidx = 0;
|
||||
|
||||
while( rI != rE && ( (*rI).m_alias.StartsWith( "${" ) || (*rI).m_alias.StartsWith( "$(" ) ) )
|
||||
{
|
||||
++listidx;
|
||||
++rI;
|
||||
}
|
||||
|
||||
if( listidx < listsize )
|
||||
m_curdir = (*rI).m_pathexp;
|
||||
else
|
||||
return;
|
||||
|
||||
listsize = listsize - listidx - m_Aliases->GetNumberRows();
|
||||
|
||||
// note: if the list allocation fails we have bigger problems
|
||||
// and there is no point in trying to notify the user here
|
||||
if( listsize > 0 && !m_Aliases->InsertRows( 0, listsize ) )
|
||||
return;
|
||||
|
||||
int nitems = 0;
|
||||
wxGridCellTextEditor* pEdAlias;
|
||||
|
||||
while( rI != rE )
|
||||
{
|
||||
m_Aliases->SetCellValue( nitems, 0, rI->m_alias );
|
||||
|
||||
if( 0 == nitems )
|
||||
{
|
||||
m_Aliases->SetCellEditor( nitems, 0, new wxGridCellTextEditor );
|
||||
pEdAlias = (wxGridCellTextEditor*) m_Aliases->GetCellEditor( nitems, 0 );
|
||||
pEdAlias->SetValidator( m_aliasValidator );
|
||||
pEdAlias->DecRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
pEdAlias->IncRef();
|
||||
m_Aliases->SetCellEditor( nitems, 0, pEdAlias );
|
||||
}
|
||||
|
||||
m_Aliases->SetCellValue( nitems, 1, rI->m_pathvar );
|
||||
m_Aliases->SetCellValue( nitems++, 2, rI->m_description );
|
||||
|
||||
// TODO: implement a wxGridCellEditor which invokes a wxDirDialog
|
||||
|
||||
++rI;
|
||||
}
|
||||
|
||||
m_Aliases->AutoSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DLG_3D_PATH_CONFIG::TransferDataFromWindow()
|
||||
{
|
||||
if( NULL == m_resolver )
|
||||
{
|
||||
wxMessageBox( _( "[BUG] No valid resolver; data will not be updated" ),
|
||||
_( "Update 3D search path list" ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<S3D_ALIAS> alist;
|
||||
S3D_ALIAS alias;
|
||||
|
||||
int ni = m_Aliases->GetNumberRows();
|
||||
|
||||
if( ni <= 0 )
|
||||
{
|
||||
// note: UI usability: we should ask a user if they're sure they
|
||||
// want to clear the entire path list
|
||||
m_resolver->UpdatePathList( alist );
|
||||
return true;
|
||||
}
|
||||
|
||||
for( int i = 0; i < ni; ++i )
|
||||
{
|
||||
alias.m_alias = m_Aliases->GetCellValue( i, 0 );
|
||||
alias.m_pathvar = m_Aliases->GetCellValue( i, 1 );
|
||||
alias.m_description = m_Aliases->GetCellValue( i, 2 );
|
||||
|
||||
if( !alias.m_alias.empty() && !alias.m_pathvar.empty() )
|
||||
alist.push_back( alias );
|
||||
|
||||
}
|
||||
|
||||
return m_resolver->UpdatePathList( alist );
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::OnAddAlias( wxCommandEvent& event )
|
||||
{
|
||||
int ni = m_Aliases->GetNumberRows();
|
||||
|
||||
if( m_Aliases->InsertRows( ni, 1 ) )
|
||||
{
|
||||
wxGridCellTextEditor* pEdAlias;
|
||||
pEdAlias = (wxGridCellTextEditor*) m_Aliases->GetCellEditor( 0, 0 );
|
||||
m_Aliases->SetCellEditor( ni, 0, pEdAlias );
|
||||
m_Aliases->SelectRow( ni, false );
|
||||
m_Aliases->AutoSize();
|
||||
Fit();
|
||||
|
||||
// TODO: set the editors on any newly created rows
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::OnDelAlias( wxCommandEvent& event )
|
||||
{
|
||||
wxArrayInt sel = m_Aliases->GetSelectedRows();
|
||||
|
||||
if( sel.empty() )
|
||||
{
|
||||
wxMessageBox( _( "No entry selected" ), _( "Delete alias entry" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( sel.size() > 1 )
|
||||
{
|
||||
wxMessageBox( _( "Multiple entries selected; please\nselect only one entry" ),
|
||||
_( "Delete alias entry" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_Aliases->GetNumberRows() > 1 )
|
||||
{
|
||||
int ni = sel.front();
|
||||
m_Aliases->DeleteRows( ni, 1 );
|
||||
|
||||
if( ni >= m_Aliases->GetNumberRows() )
|
||||
ni = m_Aliases->GetNumberRows() - 1;
|
||||
|
||||
m_Aliases->SelectRow( ni, false );
|
||||
m_Aliases->AutoSize();
|
||||
Fit();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Aliases->SetCellValue( 0, 0, wxEmptyString );
|
||||
m_Aliases->SetCellValue( 0, 1, wxEmptyString );
|
||||
m_Aliases->SetCellValue( 0, 2, wxEmptyString );
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::OnAliasMoveUp( wxCommandEvent& event )
|
||||
{
|
||||
wxArrayInt sel = m_Aliases->GetSelectedRows();
|
||||
|
||||
if( sel.empty() )
|
||||
{
|
||||
wxMessageBox( _( "No entry selected" ), _( "Move alias up" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( sel.size() > 1 )
|
||||
{
|
||||
wxMessageBox( _( "Multiple entries selected; please\nselect only one entry" ),
|
||||
_( "Move alias up" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
int ci = sel.front();
|
||||
|
||||
if( ci > 0 )
|
||||
{
|
||||
S3D_ALIAS al0;
|
||||
al0.m_alias = m_Aliases->GetCellValue( ci, 0 );
|
||||
al0.m_pathvar = m_Aliases->GetCellValue( ci, 1 );
|
||||
al0.m_description = m_Aliases->GetCellValue( ci, 2 );
|
||||
|
||||
int ni = ci - 1;
|
||||
m_Aliases->SetCellValue( ci, 0, m_Aliases->GetCellValue( ni, 0 ) );
|
||||
m_Aliases->SetCellValue( ci, 1, m_Aliases->GetCellValue( ni, 1 ) );
|
||||
m_Aliases->SetCellValue( ci, 2, m_Aliases->GetCellValue( ni, 2 ) );
|
||||
|
||||
m_Aliases->SetCellValue( ni, 0, al0.m_alias );
|
||||
m_Aliases->SetCellValue( ni, 1, al0.m_pathvar );
|
||||
m_Aliases->SetCellValue( ni, 2, al0.m_description );
|
||||
m_Aliases->SelectRow( ni, false );
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::OnAliasMoveDown( wxCommandEvent& event )
|
||||
{
|
||||
wxArrayInt sel = m_Aliases->GetSelectedRows();
|
||||
|
||||
if( sel.empty() )
|
||||
{
|
||||
wxMessageBox( _( "No entry selected" ), _( "Move alias down" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( sel.size() > 1 )
|
||||
{
|
||||
wxMessageBox( _( "Multiple entries selected; please\nselect only one entry" ),
|
||||
_( "Move alias down" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
int ni = m_Aliases->GetNumberRows() - 1;
|
||||
int ci = sel.front();
|
||||
|
||||
if( ci < ni )
|
||||
{
|
||||
S3D_ALIAS al0;
|
||||
al0.m_alias = m_Aliases->GetCellValue( ci, 0 );
|
||||
al0.m_pathvar = m_Aliases->GetCellValue( ci, 1 );
|
||||
al0.m_description = m_Aliases->GetCellValue( ci, 2 );
|
||||
|
||||
ni = ci + 1;
|
||||
m_Aliases->SetCellValue( ci, 0, m_Aliases->GetCellValue( ni, 0 ) );
|
||||
m_Aliases->SetCellValue( ci, 1, m_Aliases->GetCellValue( ni, 1 ) );
|
||||
m_Aliases->SetCellValue( ci, 2, m_Aliases->GetCellValue( ni, 2 ) );
|
||||
|
||||
m_Aliases->SetCellValue( ni, 0, al0.m_alias );
|
||||
m_Aliases->SetCellValue( ni, 1, al0.m_pathvar );
|
||||
m_Aliases->SetCellValue( ni, 2, al0.m_description );
|
||||
m_Aliases->SelectRow( ni, false );
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::OnConfigEnvVar( wxCommandEvent& event )
|
||||
{
|
||||
Pgm().ConfigurePaths( this );
|
||||
updateEnvVars();
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::updateEnvVars( void )
|
||||
{
|
||||
if( !m_resolver )
|
||||
return;
|
||||
|
||||
std::list< wxString > epaths;
|
||||
|
||||
m_resolver->GetKicadPaths( epaths );
|
||||
size_t nitems = epaths.size();
|
||||
size_t nrows = m_EnvVars->GetNumberRows();
|
||||
bool resize = nrows != nitems; // true after adding/removing env vars
|
||||
|
||||
if( nrows > nitems )
|
||||
{
|
||||
size_t ni = nrows - nitems;
|
||||
m_EnvVars->DeleteRows( 0, ni );
|
||||
}
|
||||
else if( nrows < nitems )
|
||||
{
|
||||
size_t ni = nitems - nrows;
|
||||
m_EnvVars->InsertRows( 0, ni );
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
|
||||
for( const auto& i : epaths )
|
||||
{
|
||||
wxString val = ExpandEnvVarSubstitutions( i );
|
||||
m_EnvVars->SetCellValue( j, 0, i );
|
||||
m_EnvVars->SetCellValue( j, 1, val );
|
||||
m_EnvVars->SetReadOnly( j, 0, true );
|
||||
m_EnvVars->SetReadOnly( j, 1, true );
|
||||
wxGridCellAttr* ap = m_EnvVars->GetOrCreateCellAttr( j, 0 );
|
||||
ap->SetReadOnly( true );
|
||||
ap->SetBackgroundColour( *wxLIGHT_GREY );
|
||||
m_EnvVars->SetRowAttr( j, ap );
|
||||
++j;
|
||||
}
|
||||
|
||||
m_EnvVars->AutoSize();
|
||||
|
||||
// Resizing the full dialog is sometimes needed for a clean display
|
||||
// i.e. when adding/removing Kicad environment variables
|
||||
if( resize )
|
||||
GetSizer()->SetSizeHints( this );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::OnHelp( wxCommandEvent& event )
|
||||
{
|
||||
wxString msg = _( "Enter the name and path for each 3D alias variable.<br>KiCad "
|
||||
"environment variables and their values are shown for "
|
||||
"reference only and cannot be edited." );
|
||||
msg << "<br><br><b>";
|
||||
msg << _( "Alias names may not contain any of the characters " );
|
||||
msg << "{}[]()%~<>\"='`;:.,&?/\\|$";
|
||||
msg << "</b>";
|
||||
|
||||
HTML_MESSAGE_BOX dlg( GetParent(), _( "Environment Variable Help" ) );
|
||||
dlg.AddHTML_Text( msg );
|
||||
dlg.ShowModal();
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DLG_3D_PATHCONFIG_H
|
||||
#define DLG_3D_PATHCONFIG_H
|
||||
|
||||
#include <wx/valtext.h>
|
||||
#include "dlg_3d_pathconfig_base.h"
|
||||
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
|
||||
class DLG_3D_PATH_CONFIG : public DLG_3D_PATH_CONFIG_BASE
|
||||
{
|
||||
private:
|
||||
S3D_FILENAME_RESOLVER* m_resolver;
|
||||
wxString m_curdir;
|
||||
wxTextValidator m_aliasValidator;
|
||||
|
||||
void initDialog();
|
||||
|
||||
void OnAddAlias( wxCommandEvent& event ) override;
|
||||
void OnDelAlias( wxCommandEvent& event ) override;
|
||||
void OnAliasMoveUp( wxCommandEvent& event ) override;
|
||||
void OnAliasMoveDown( wxCommandEvent& event ) override;
|
||||
void OnConfigEnvVar( wxCommandEvent& event ) override;
|
||||
void OnHelp( wxCommandEvent& event ) override;
|
||||
|
||||
public:
|
||||
DLG_3D_PATH_CONFIG( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver );
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
private:
|
||||
void updateEnvVars( void );
|
||||
};
|
||||
|
||||
#endif // DLG_3D_PATHCONFIG_H
|
||||
@@ -1,162 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Nov 22 2017)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dlg_3d_pathconfig_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DLG_3D_PATH_CONFIG_BASE::DLG_3D_PATH_CONFIG_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
|
||||
|
||||
wxBoxSizer* bSizerMain;
|
||||
bSizerMain = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bSizer5;
|
||||
bSizer5 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_EnvVars = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
// Grid
|
||||
m_EnvVars->CreateGrid( 1, 2 );
|
||||
m_EnvVars->EnableEditing( true );
|
||||
m_EnvVars->EnableGridLines( true );
|
||||
m_EnvVars->EnableDragGridSize( false );
|
||||
m_EnvVars->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_EnvVars->SetColSize( 0, 150 );
|
||||
m_EnvVars->SetColSize( 1, 300 );
|
||||
m_EnvVars->EnableDragColMove( false );
|
||||
m_EnvVars->EnableDragColSize( true );
|
||||
m_EnvVars->SetColLabelSize( 30 );
|
||||
m_EnvVars->SetColLabelValue( 0, _("Name") );
|
||||
m_EnvVars->SetColLabelValue( 1, _("Path") );
|
||||
m_EnvVars->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
|
||||
|
||||
// Rows
|
||||
m_EnvVars->EnableDragRowSize( true );
|
||||
m_EnvVars->SetRowLabelSize( 80 );
|
||||
m_EnvVars->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
|
||||
|
||||
// Label Appearance
|
||||
|
||||
// Cell Defaults
|
||||
m_EnvVars->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
|
||||
m_EnvVars->SetMinSize( wxSize( 250,100 ) );
|
||||
|
||||
bSizer5->Add( m_EnvVars, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_btnEnvCfg = new wxButton( this, wxID_ANY, _("Configure Environment Variables"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer5->Add( m_btnEnvCfg, 0, wxALIGN_CENTER|wxALL, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( bSizer5, 0, wxEXPAND, 5 );
|
||||
|
||||
m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bSizerMain->Add( m_staticline2, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
wxBoxSizer* bSizerGrid;
|
||||
bSizerGrid = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_Aliases = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
// Grid
|
||||
m_Aliases->CreateGrid( 1, 3 );
|
||||
m_Aliases->EnableEditing( true );
|
||||
m_Aliases->EnableGridLines( true );
|
||||
m_Aliases->EnableDragGridSize( false );
|
||||
m_Aliases->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_Aliases->SetColSize( 0, 80 );
|
||||
m_Aliases->SetColSize( 1, 300 );
|
||||
m_Aliases->SetColSize( 2, 120 );
|
||||
m_Aliases->EnableDragColMove( false );
|
||||
m_Aliases->EnableDragColSize( true );
|
||||
m_Aliases->SetColLabelSize( 30 );
|
||||
m_Aliases->SetColLabelValue( 0, _("Alias") );
|
||||
m_Aliases->SetColLabelValue( 1, _("Path") );
|
||||
m_Aliases->SetColLabelValue( 2, _("Description") );
|
||||
m_Aliases->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
|
||||
|
||||
// Rows
|
||||
m_Aliases->AutoSizeRows();
|
||||
m_Aliases->EnableDragRowSize( false );
|
||||
m_Aliases->SetRowLabelSize( 80 );
|
||||
m_Aliases->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
|
||||
|
||||
// Label Appearance
|
||||
|
||||
// Cell Defaults
|
||||
m_Aliases->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
|
||||
m_Aliases->SetMinSize( wxSize( -1,150 ) );
|
||||
|
||||
bSizerGrid->Add( m_Aliases, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( bSizerGrid, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizerButtons;
|
||||
bSizerButtons = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_btnAddAlias = new wxButton( this, wxID_ANY, _("Add Alias"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerButtons->Add( m_btnAddAlias, 0, wxALL, 5 );
|
||||
|
||||
m_btnDelAlias = new wxButton( this, wxID_ANY, _("Remove Alias"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerButtons->Add( m_btnDelAlias, 0, wxALL, 5 );
|
||||
|
||||
m_btnMoveUp = new wxButton( this, wxID_ANY, _("Move Up"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerButtons->Add( m_btnMoveUp, 0, wxALL, 5 );
|
||||
|
||||
m_btnMoveDown = new wxButton( this, wxID_ANY, _("Move Down"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerButtons->Add( m_btnMoveDown, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( bSizerButtons, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bSizerMain->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
m_sdbSizer2 = new wxStdDialogButtonSizer();
|
||||
m_sdbSizer2OK = new wxButton( this, wxID_OK );
|
||||
m_sdbSizer2->AddButton( m_sdbSizer2OK );
|
||||
m_sdbSizer2Cancel = new wxButton( this, wxID_CANCEL );
|
||||
m_sdbSizer2->AddButton( m_sdbSizer2Cancel );
|
||||
m_sdbSizer2Help = new wxButton( this, wxID_HELP );
|
||||
m_sdbSizer2->AddButton( m_sdbSizer2Help );
|
||||
m_sdbSizer2->Realize();
|
||||
|
||||
bSizerMain->Add( m_sdbSizer2, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bSizerMain );
|
||||
this->Layout();
|
||||
bSizerMain->Fit( this );
|
||||
|
||||
this->Centre( wxBOTH );
|
||||
|
||||
// Connect Events
|
||||
m_btnEnvCfg->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnConfigEnvVar ), NULL, this );
|
||||
m_btnAddAlias->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnAddAlias ), NULL, this );
|
||||
m_btnDelAlias->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnDelAlias ), NULL, this );
|
||||
m_btnMoveUp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnAliasMoveUp ), NULL, this );
|
||||
m_btnMoveDown->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnAliasMoveDown ), NULL, this );
|
||||
m_sdbSizer2Help->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnHelp ), NULL, this );
|
||||
}
|
||||
|
||||
DLG_3D_PATH_CONFIG_BASE::~DLG_3D_PATH_CONFIG_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_btnEnvCfg->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnConfigEnvVar ), NULL, this );
|
||||
m_btnAddAlias->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnAddAlias ), NULL, this );
|
||||
m_btnDelAlias->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnDelAlias ), NULL, this );
|
||||
m_btnMoveUp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnAliasMoveUp ), NULL, this );
|
||||
m_btnMoveDown->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnAliasMoveDown ), NULL, this );
|
||||
m_sdbSizer2Help->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnHelp ), NULL, this );
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,67 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Nov 22 2017)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __DLG_3D_PATHCONFIG_BASE_H__
|
||||
#define __DLG_3D_PATHCONFIG_BASE_H__
|
||||
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
#include "dialog_shim.h"
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/statline.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class DLG_3D_PATH_CONFIG_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class DLG_3D_PATH_CONFIG_BASE : public DIALOG_SHIM
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxGrid* m_EnvVars;
|
||||
wxButton* m_btnEnvCfg;
|
||||
wxStaticLine* m_staticline2;
|
||||
wxGrid* m_Aliases;
|
||||
wxButton* m_btnAddAlias;
|
||||
wxButton* m_btnDelAlias;
|
||||
wxButton* m_btnMoveUp;
|
||||
wxButton* m_btnMoveDown;
|
||||
wxStaticLine* m_staticline1;
|
||||
wxStdDialogButtonSizer* m_sdbSizer2;
|
||||
wxButton* m_sdbSizer2OK;
|
||||
wxButton* m_sdbSizer2Cancel;
|
||||
wxButton* m_sdbSizer2Help;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnConfigEnvVar( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnAddAlias( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnDelAlias( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnAliasMoveUp( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnAliasMoveDown( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnHelp( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DLG_3D_PATH_CONFIG_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("3D Search Path Configuration"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
~DLG_3D_PATH_CONFIG_BASE();
|
||||
|
||||
};
|
||||
|
||||
#endif //__DLG_3D_PATHCONFIG_BASE_H__
|
||||
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2017-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <set>
|
||||
#include "dlg_select_3dmodel.h"
|
||||
#include "project.h"
|
||||
#include "3d_cache/3d_info.h"
|
||||
#include "3d_cache/3d_cache.h"
|
||||
#include "3d_cache_dialogs.h"
|
||||
#include <3d_model_viewer/c3d_model_viewer.h>
|
||||
#include <common_ogl/cogl_att_list.h>
|
||||
#include <pcbnew/class_module.h>
|
||||
|
||||
#define ID_FILE_TREE ( wxID_LAST + 1 )
|
||||
#define ID_SET_DIR ( ID_FILE_TREE + 1 )
|
||||
#define ID_CFG_PATHS ( ID_SET_DIR + 1 )
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE( DLG_SELECT_3DMODEL, DIALOG_SHIM )
|
||||
EVT_DIRCTRL_SELECTIONCHANGED( ID_FILE_TREE, DLG_SELECT_3DMODEL::OnSelectionChanged )
|
||||
EVT_DIRCTRL_FILEACTIVATED( ID_FILE_TREE, DLG_SELECT_3DMODEL::OnFileActivated )
|
||||
EVT_CHOICE( ID_SET_DIR, DLG_SELECT_3DMODEL::SetRootDir )
|
||||
EVT_BUTTON( ID_CFG_PATHS, DLG_SELECT_3DMODEL::Cfg3DPaths )
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
DLG_SELECT_3DMODEL::DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheManager,
|
||||
MODULE_3D_SETTINGS* aModelItem, wxString& prevModelSelectDir, int& prevModelWildcard ) :
|
||||
DIALOG_SHIM( aParent, wxID_ANY, _( "Select 3D Model" ), wxDefaultPosition,
|
||||
wxSize( 500,200 ), wxCAPTION | wxRESIZE_BORDER | wxCLOSE_BOX
|
||||
| wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxSYSTEM_MENU ),
|
||||
m_model( aModelItem ), m_cache( aCacheManager ), m_previousDir( prevModelSelectDir ),
|
||||
m_previousFilterIndex( prevModelWildcard )
|
||||
{
|
||||
SetSizeHints( wxSize( 500,200 ), wxDefaultSize );
|
||||
|
||||
if( NULL != m_cache )
|
||||
m_resolver = m_cache->GetResolver();
|
||||
else
|
||||
m_resolver = NULL;
|
||||
|
||||
wxBoxSizer* bSizer0 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bSizer1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxBoxSizer* bSizer2 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
// set to NULL to avoid segfaults when m_FileTree is instantiated
|
||||
// and wxGenericDirCtrl events are posted
|
||||
m_modelViewer = NULL;
|
||||
dirChoices = NULL;
|
||||
|
||||
m_FileTree = new wxGenericDirCtrl( this, ID_FILE_TREE, prevModelSelectDir, wxDefaultPosition,
|
||||
wxSize( 300,100 ), wxDIRCTRL_3D_INTERNAL | wxDIRCTRL_EDIT_LABELS
|
||||
| wxDIRCTRL_SELECT_FIRST | wxDIRCTRL_SHOW_FILTERS|wxSUNKEN_BORDER, wxEmptyString, 0 );
|
||||
|
||||
|
||||
m_FileTree->ShowHidden( false );
|
||||
m_FileTree->SetMinSize( wxSize( 300, 400 ) );
|
||||
m_FileTree->SetLabel( wxT( "3D_MODEL_SELECTOR" ) );
|
||||
|
||||
bSizer2->Add( m_FileTree, 1, wxEXPAND | wxALL, 5 );
|
||||
bSizer1->Add( bSizer2, 3, wxEXPAND, 5 );
|
||||
|
||||
m_modelViewer = new C3D_MODEL_VIEWER( this, COGL_ATT_LIST::GetAttributesList( true ), m_cache );
|
||||
m_modelViewer->SetMinSize( wxSize( 500, 400 ) );
|
||||
|
||||
bSizer1->Add( m_modelViewer, 5, wxEXPAND | wxALL | wxCENTER, 5 );
|
||||
|
||||
// create the filter list
|
||||
if( NULL != m_cache )
|
||||
{
|
||||
std::list< wxString > const* fl = m_cache->GetFileFilters();
|
||||
std::list< wxString >::const_iterator sL = fl->begin();
|
||||
std::list< wxString >::const_iterator eL = fl->end();
|
||||
wxString filter;
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
filter.Append( *sL );
|
||||
|
||||
++sL;
|
||||
|
||||
if( sL != eL )
|
||||
filter.Append( wxT( "|" ) );
|
||||
}
|
||||
|
||||
if( !filter.empty() )
|
||||
m_FileTree->SetFilter( filter );
|
||||
else
|
||||
m_FileTree->SetFilter( wxT( "*.*" ) );
|
||||
|
||||
if( prevModelWildcard >= 0 && prevModelWildcard < (int)fl->size() )
|
||||
m_FileTree->SetFilterIndex( prevModelWildcard );
|
||||
else
|
||||
{
|
||||
prevModelWildcard = 0;
|
||||
m_FileTree->SetFilterIndex( 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_FileTree->SetFilter( wxT( "*.*" ) );
|
||||
prevModelWildcard = 0;
|
||||
m_FileTree->SetFilterIndex( 0 );
|
||||
}
|
||||
|
||||
// Add the path choice box and config button
|
||||
wxBoxSizer* hboxDirChoice = new wxBoxSizer( wxHORIZONTAL );
|
||||
dirChoices = new wxChoice( this, ID_SET_DIR, wxDefaultPosition, wxSize( 320, 20 ) );
|
||||
dirChoices->SetMinSize( wxSize( 320, 12 ) );
|
||||
|
||||
wxStaticText* stDirChoice = new wxStaticText( this, -1, _( "Paths:" ) );
|
||||
wxButton* cfgPaths = new wxButton( this, ID_CFG_PATHS, _( "Configure Paths" ) );
|
||||
hboxDirChoice->Add( stDirChoice, 0, wxALL | wxCENTER, 5 );
|
||||
hboxDirChoice->Add( dirChoices, 1, wxEXPAND | wxALL, 5 );
|
||||
hboxDirChoice->Add( cfgPaths, 0, wxALL, 5 );
|
||||
|
||||
wxButton* btn_OK = new wxButton( this, wxID_OK, _( "OK" ) );
|
||||
wxButton* btn_Cancel = new wxButton( this, wxID_CANCEL, _( "Cancel" ) );
|
||||
|
||||
wxStdDialogButtonSizer* hSizer1 = new wxStdDialogButtonSizer();
|
||||
hSizer1->AddButton( btn_OK );
|
||||
hSizer1->AddButton( btn_Cancel );
|
||||
hSizer1->Realize();
|
||||
|
||||
bSizer0->Add( bSizer1, 1, wxALL | wxEXPAND, 5 );
|
||||
bSizer0->Add( hboxDirChoice, 0, wxALL | wxEXPAND, 5 );
|
||||
bSizer0->Add( hSizer1, 0, wxALL | wxEXPAND, 5 );
|
||||
|
||||
updateDirChoiceList();
|
||||
|
||||
SetSizerAndFit( bSizer0 );
|
||||
Layout();
|
||||
Centre( wxBOTH );
|
||||
|
||||
m_modelViewer->Refresh();
|
||||
m_modelViewer->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
bool DLG_SELECT_3DMODEL::TransferDataFromWindow()
|
||||
{
|
||||
if( NULL == m_model || NULL == m_FileTree )
|
||||
return true;
|
||||
|
||||
m_model->m_Scale.x = 1.0;
|
||||
m_model->m_Scale.y = 1.0;
|
||||
m_model->m_Scale.z = 1.0;
|
||||
|
||||
m_model->m_Rotation.x = 0.0;
|
||||
m_model->m_Rotation.y = 0.0;
|
||||
m_model->m_Rotation.z = 0.0;
|
||||
|
||||
m_model->m_Offset = m_model->m_Rotation;
|
||||
m_model->m_Filename.clear();
|
||||
|
||||
wxString name = m_FileTree->GetFilePath();
|
||||
|
||||
if( name.empty() )
|
||||
return true;
|
||||
|
||||
m_previousDir = m_FileTree->GetPath();
|
||||
m_previousFilterIndex = m_FileTree->GetFilterIndex();
|
||||
|
||||
// file selection mode: retrieve the filename and specify a
|
||||
// path relative to one of the config paths
|
||||
wxFileName fname = m_FileTree->GetFilePath();
|
||||
fname.Normalize();
|
||||
m_model->m_Filename = m_resolver->ShortenPath( fname.GetFullPath() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::OnSelectionChanged( wxTreeEvent& event )
|
||||
{
|
||||
if( m_modelViewer )
|
||||
m_modelViewer->Set3DModel( m_FileTree->GetFilePath() );
|
||||
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::OnFileActivated( wxTreeEvent& event )
|
||||
{
|
||||
if( m_modelViewer )
|
||||
m_modelViewer->Set3DModel( m_FileTree->GetFilePath() );
|
||||
|
||||
event.Skip();
|
||||
SetEscapeId( wxID_OK );
|
||||
Close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::SetRootDir( wxCommandEvent& event )
|
||||
{
|
||||
if( m_FileTree )
|
||||
m_FileTree->SetPath( dirChoices->GetString( dirChoices->GetSelection() ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::Cfg3DPaths( wxCommandEvent& event )
|
||||
{
|
||||
if( S3D::Configure3DPaths( this, m_resolver ) )
|
||||
updateDirChoiceList();
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::updateDirChoiceList( void )
|
||||
{
|
||||
if( NULL == m_FileTree || NULL == m_resolver || NULL == dirChoices )
|
||||
return;
|
||||
|
||||
std::list< S3D_ALIAS > const* md = m_resolver->GetPaths();
|
||||
std::list< S3D_ALIAS >::const_iterator sL = md->begin();
|
||||
std::list< S3D_ALIAS >::const_iterator eL = md->end();
|
||||
std::set< wxString > cl;
|
||||
wxString prjDir;
|
||||
|
||||
// extract the current project dir
|
||||
if( sL != eL )
|
||||
{
|
||||
prjDir = sL->m_pathexp;
|
||||
++sL;
|
||||
}
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
if( !sL->m_pathexp.empty() && sL->m_pathexp.compare( prjDir ) )
|
||||
cl.insert( sL->m_pathexp );
|
||||
|
||||
++sL;
|
||||
}
|
||||
|
||||
if( !cl.empty() )
|
||||
{
|
||||
dirChoices->Clear();
|
||||
|
||||
if( !prjDir.empty() )
|
||||
dirChoices->Append( prjDir );
|
||||
|
||||
std::set< wxString >::const_iterator sI = cl.begin();
|
||||
std::set< wxString >::const_iterator eI = cl.end();
|
||||
|
||||
while( sI != eI )
|
||||
{
|
||||
dirChoices->Append( *sI );
|
||||
++sI;
|
||||
}
|
||||
|
||||
dirChoices->Select( 0 );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file dlg_select_3dmodel.h
|
||||
* creates a dialog to select 3D model files
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DLG_SELECT_3DMODEL_H
|
||||
#define DLG_SELECT_3DMODEL_H
|
||||
|
||||
#include <wx/event.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/dirctrl.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/frame.h>
|
||||
|
||||
#include <dialog_shim.h>
|
||||
|
||||
class MODULE_3D_SETTINGS;
|
||||
class S3D_CACHE;
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
class C3D_MODEL_VIEWER;
|
||||
|
||||
class DLG_SELECT_3DMODEL : public DIALOG_SHIM
|
||||
{
|
||||
private:
|
||||
MODULE_3D_SETTINGS* m_model; // data for the selected model
|
||||
S3D_CACHE* m_cache; // cache manager
|
||||
S3D_FILENAME_RESOLVER* m_resolver; // 3D filename resolver
|
||||
|
||||
wxString& m_previousDir;
|
||||
int& m_previousFilterIndex;
|
||||
|
||||
wxGenericDirCtrl* m_FileTree;
|
||||
C3D_MODEL_VIEWER* m_modelViewer;
|
||||
wxChoice* dirChoices;
|
||||
|
||||
void updateDirChoiceList( void );
|
||||
|
||||
public:
|
||||
DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheManager, MODULE_3D_SETTINGS* aModelItem,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard );
|
||||
|
||||
bool TransferDataFromWindow() override;
|
||||
void OnSelectionChanged( wxTreeEvent& event );
|
||||
void OnFileActivated( wxTreeEvent& event );
|
||||
void SetRootDir( wxCommandEvent& event );
|
||||
void Cfg3DPaths( wxCommandEvent& event );
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
#endif // DLG_SELECT_3DMODEL_H
|
||||
@@ -1,353 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Jan 12 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "panel_prev_3d_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PANEL_PREV_3D_BASE::PANEL_PREV_3D_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
|
||||
{
|
||||
wxBoxSizer* bSizermain;
|
||||
bSizermain = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxBoxSizer* bSizerLeft;
|
||||
bSizerLeft = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bSizerScale;
|
||||
bSizerScale = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_staticTextScale = new wxStaticText( this, wxID_ANY, _("Scale"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextScale->Wrap( -1 );
|
||||
bSizerScale->Add( m_staticTextScale, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxFlexGridSizer* fgSizerScale;
|
||||
fgSizerScale = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerScale->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerScale->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText1 = new wxStaticText( this, wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText1->Wrap( -1 );
|
||||
fgSizerScale->Add( m_staticText1, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
xscale = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerScale->Add( xscale, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinXscale = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerScale->Add( m_spinXscale, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText2 = new wxStaticText( this, wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText2->Wrap( -1 );
|
||||
fgSizerScale->Add( m_staticText2, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
yscale = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerScale->Add( yscale, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT|wxTOP, 5 );
|
||||
|
||||
m_spinYscale = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerScale->Add( m_spinYscale, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText3 = new wxStaticText( this, wxID_ANY, _("Z:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText3->Wrap( -1 );
|
||||
fgSizerScale->Add( m_staticText3, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
zscale = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerScale->Add( zscale, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_spinZscale = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerScale->Add( m_spinZscale, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
bSizerScale->Add( fgSizerScale, 0, wxEXPAND|wxRIGHT|wxLEFT, 10 );
|
||||
|
||||
|
||||
bSizerLeft->Add( bSizerScale, 0, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizerRotation;
|
||||
bSizerRotation = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_staticTextRot = new wxStaticText( this, wxID_ANY, _("Rotation (degrees)"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextRot->Wrap( -1 );
|
||||
bSizerRotation->Add( m_staticTextRot, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxFlexGridSizer* fgSizerRotate;
|
||||
fgSizerRotate = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerRotate->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerRotate->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText11 = new wxStaticText( this, wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText11->Wrap( -1 );
|
||||
fgSizerRotate->Add( m_staticText11, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
xrot = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
#ifdef __WXGTK__
|
||||
if ( !xrot->HasFlag( wxTE_MULTILINE ) )
|
||||
{
|
||||
xrot->SetMaxLength( 9 );
|
||||
}
|
||||
#else
|
||||
xrot->SetMaxLength( 9 );
|
||||
#endif
|
||||
fgSizerRotate->Add( xrot, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinXrot = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerRotate->Add( m_spinXrot, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText21 = new wxStaticText( this, wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText21->Wrap( -1 );
|
||||
fgSizerRotate->Add( m_staticText21, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
yrot = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
#ifdef __WXGTK__
|
||||
if ( !yrot->HasFlag( wxTE_MULTILINE ) )
|
||||
{
|
||||
yrot->SetMaxLength( 9 );
|
||||
}
|
||||
#else
|
||||
yrot->SetMaxLength( 9 );
|
||||
#endif
|
||||
fgSizerRotate->Add( yrot, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT|wxTOP, 5 );
|
||||
|
||||
m_spinYrot = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerRotate->Add( m_spinYrot, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText31 = new wxStaticText( this, wxID_ANY, _("Z:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText31->Wrap( -1 );
|
||||
fgSizerRotate->Add( m_staticText31, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
zrot = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
#ifdef __WXGTK__
|
||||
if ( !zrot->HasFlag( wxTE_MULTILINE ) )
|
||||
{
|
||||
zrot->SetMaxLength( 9 );
|
||||
}
|
||||
#else
|
||||
zrot->SetMaxLength( 9 );
|
||||
#endif
|
||||
fgSizerRotate->Add( zrot, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_spinZrot = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerRotate->Add( m_spinZrot, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
bSizerRotation->Add( fgSizerRotate, 0, wxEXPAND|wxRIGHT|wxLEFT, 10 );
|
||||
|
||||
|
||||
bSizerLeft->Add( bSizerRotation, 0, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizerOffset;
|
||||
bSizerOffset = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_staticTextOffset = new wxStaticText( this, wxID_ANY, _("Offset"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextOffset->Wrap( -1 );
|
||||
bSizerOffset->Add( m_staticTextOffset, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxFlexGridSizer* fgSizerOffset;
|
||||
fgSizerOffset = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerOffset->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerOffset->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText12 = new wxStaticText( this, wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText12->Wrap( -1 );
|
||||
fgSizerOffset->Add( m_staticText12, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
xoff = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerOffset->Add( xoff, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinXoffset = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerOffset->Add( m_spinXoffset, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText22 = new wxStaticText( this, wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText22->Wrap( -1 );
|
||||
fgSizerOffset->Add( m_staticText22, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
yoff = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerOffset->Add( yoff, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxTOP, 5 );
|
||||
|
||||
m_spinYoffset = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerOffset->Add( m_spinYoffset, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText32 = new wxStaticText( this, wxID_ANY, _("Z:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText32->Wrap( -1 );
|
||||
fgSizerOffset->Add( m_staticText32, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
zoff = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerOffset->Add( zoff, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinZoffset = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerOffset->Add( m_spinZoffset, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
|
||||
bSizerOffset->Add( fgSizerOffset, 0, wxEXPAND|wxLEFT|wxRIGHT, 10 );
|
||||
|
||||
|
||||
bSizerLeft->Add( bSizerOffset, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizerLeft, 0, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizerRight;
|
||||
bSizerRight = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_SizerPanelView = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
bSizerRight->Add( m_SizerPanelView, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizer3DButtons;
|
||||
bSizer3DButtons = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
|
||||
bSizer3DButtons->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_fgSizerButtons = new wxFlexGridSizer( 0, 4, 0, 0 );
|
||||
m_fgSizerButtons->AddGrowableCol( 0 );
|
||||
m_fgSizerButtons->AddGrowableCol( 1 );
|
||||
m_fgSizerButtons->AddGrowableCol( 2 );
|
||||
m_fgSizerButtons->AddGrowableCol( 3 );
|
||||
m_fgSizerButtons->SetFlexibleDirection( wxBOTH );
|
||||
m_fgSizerButtons->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_bpvISO = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_bpvISO->SetToolTip( _("Change to isometric perspective") );
|
||||
|
||||
m_fgSizerButtons->Add( m_bpvISO, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpvLeft = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_fgSizerButtons->Add( m_bpvLeft, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpvFront = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_fgSizerButtons->Add( m_bpvFront, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpvTop = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_fgSizerButtons->Add( m_bpvTop, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpUpdate = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_bpUpdate->SetToolTip( _("Reload board and 3D models") );
|
||||
|
||||
m_fgSizerButtons->Add( m_bpUpdate, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpvRight = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_fgSizerButtons->Add( m_bpvRight, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpvBack = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_fgSizerButtons->Add( m_bpvBack, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpvBottom = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_fgSizerButtons->Add( m_bpvBottom, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer3DButtons->Add( m_fgSizerButtons, 6, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer3DButtons->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizerRight->Add( bSizer3DButtons, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizerRight, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bSizermain );
|
||||
this->Layout();
|
||||
bSizermain->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
xscale->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
xscale->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXscale->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinXscale->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
yscale->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
yscale->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYscale->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinYscale->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
zscale->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
zscale->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZscale->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinZscale->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
xrot->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
xrot->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXrot->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinXrot->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
yrot->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
yrot->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYrot->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinYrot->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
zrot->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
zrot->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZrot->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinZrot->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
xoff->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
xoff->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinXoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
yoff->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
yoff->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinYoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
zoff->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
zoff->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinZoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
m_bpvISO->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DISO ), NULL, this );
|
||||
m_bpvLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DLeft ), NULL, this );
|
||||
m_bpvFront->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DFront ), NULL, this );
|
||||
m_bpvTop->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DTop ), NULL, this );
|
||||
m_bpUpdate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DUpdate ), NULL, this );
|
||||
m_bpvRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DRight ), NULL, this );
|
||||
m_bpvBack->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBack ), NULL, this );
|
||||
m_bpvBottom->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBottom ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_PREV_3D_BASE::~PANEL_PREV_3D_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
xscale->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
xscale->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXscale->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinXscale->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
yscale->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
yscale->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYscale->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinYscale->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
zscale->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
zscale->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZscale->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinZscale->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
xrot->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
xrot->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXrot->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinXrot->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
yrot->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
yrot->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYrot->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinYrot->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
zrot->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
zrot->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZrot->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinZrot->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
xoff->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
xoff->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinXoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
yoff->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
yoff->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinYoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
zoff->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
zoff->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinZoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
m_bpvISO->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DISO ), NULL, this );
|
||||
m_bpvLeft->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DLeft ), NULL, this );
|
||||
m_bpvFront->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DFront ), NULL, this );
|
||||
m_bpvTop->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DTop ), NULL, this );
|
||||
m_bpUpdate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DUpdate ), NULL, this );
|
||||
m_bpvRight->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DRight ), NULL, this );
|
||||
m_bpvBack->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBack ), NULL, this );
|
||||
m_bpvBottom->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBottom ), NULL, this );
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,110 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Jan 12 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __PANEL_PREV_3D_BASE_H__
|
||||
#define __PANEL_PREV_3D_BASE_H__
|
||||
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/spinbutt.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_PREV_3D_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_PREV_3D_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticText* m_staticTextScale;
|
||||
wxStaticText* m_staticText1;
|
||||
wxTextCtrl* xscale;
|
||||
wxSpinButton* m_spinXscale;
|
||||
wxStaticText* m_staticText2;
|
||||
wxTextCtrl* yscale;
|
||||
wxSpinButton* m_spinYscale;
|
||||
wxStaticText* m_staticText3;
|
||||
wxTextCtrl* zscale;
|
||||
wxSpinButton* m_spinZscale;
|
||||
wxStaticText* m_staticTextRot;
|
||||
wxStaticText* m_staticText11;
|
||||
wxTextCtrl* xrot;
|
||||
wxSpinButton* m_spinXrot;
|
||||
wxStaticText* m_staticText21;
|
||||
wxTextCtrl* yrot;
|
||||
wxSpinButton* m_spinYrot;
|
||||
wxStaticText* m_staticText31;
|
||||
wxTextCtrl* zrot;
|
||||
wxSpinButton* m_spinZrot;
|
||||
wxStaticText* m_staticTextOffset;
|
||||
wxStaticText* m_staticText12;
|
||||
wxTextCtrl* xoff;
|
||||
wxSpinButton* m_spinXoffset;
|
||||
wxStaticText* m_staticText22;
|
||||
wxSpinButton* m_spinYoffset;
|
||||
wxStaticText* m_staticText32;
|
||||
wxTextCtrl* zoff;
|
||||
wxSpinButton* m_spinZoffset;
|
||||
wxBoxSizer* m_SizerPanelView;
|
||||
wxFlexGridSizer* m_fgSizerButtons;
|
||||
wxBitmapButton* m_bpvISO;
|
||||
wxBitmapButton* m_bpvLeft;
|
||||
wxBitmapButton* m_bpvFront;
|
||||
wxBitmapButton* m_bpvTop;
|
||||
wxBitmapButton* m_bpUpdate;
|
||||
wxBitmapButton* m_bpvRight;
|
||||
wxBitmapButton* m_bpvBack;
|
||||
wxBitmapButton* m_bpvBottom;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void onMouseWheelScale( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void updateOrientation( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onDecrementScale( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementScale( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onMouseWheelRot( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void onDecrementRot( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementRot( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onMouseWheelOffset( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void onDecrementOffset( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementOffset( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void View3DISO( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DLeft( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DFront( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DTop( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DUpdate( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DRight( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DBack( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DBottom( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
wxTextCtrl* yoff;
|
||||
|
||||
PANEL_PREV_3D_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL );
|
||||
~PANEL_PREV_3D_BASE();
|
||||
|
||||
};
|
||||
|
||||
#endif //__PANEL_PREV_3D_BASE_H__
|
||||
@@ -1,693 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2015-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file panel_prev_model.cpp
|
||||
*/
|
||||
|
||||
#include <3d_canvas/eda_3d_canvas.h>
|
||||
#include <common_ogl/cogl_att_list.h>
|
||||
#include <cstdlib>
|
||||
#include <limits.h>
|
||||
#include <bitmaps.h>
|
||||
|
||||
#include <wx/valnum.h>
|
||||
#include <wx/tglbtn.h>
|
||||
|
||||
#include "project.h"
|
||||
#include "panel_prev_model.h"
|
||||
#include <class_board.h>
|
||||
|
||||
|
||||
PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, S3D_CACHE* aCacheManager,
|
||||
MODULE* aModuleCopy,
|
||||
COLORS_DESIGN_SETTINGS *aColors,
|
||||
std::vector<MODULE_3D_SETTINGS> *aParentInfoList ) :
|
||||
PANEL_PREV_3D_BASE( aParent, wxID_ANY )
|
||||
{
|
||||
initPanel();
|
||||
|
||||
// Initialize the color settings to draw the board and the footprint
|
||||
if( aColors )
|
||||
m_dummyBoard->SetColorsSettings( aColors );
|
||||
else
|
||||
{
|
||||
static COLORS_DESIGN_SETTINGS defaultColors( FRAME_PCB_DISPLAY3D );
|
||||
m_dummyBoard->SetColorsSettings( &defaultColors );
|
||||
}
|
||||
|
||||
if( NULL != aCacheManager )
|
||||
m_resolver = aCacheManager->GetResolver();
|
||||
|
||||
m_parentInfoList = aParentInfoList;
|
||||
|
||||
m_dummyBoard->Add( (MODULE*)aModuleCopy );
|
||||
m_copyModule = aModuleCopy;
|
||||
|
||||
// Set 3d viewer configuration for preview
|
||||
m_settings3Dviewer = new CINFO3D_VISU();
|
||||
|
||||
// Create the 3D canvas
|
||||
m_previewPane = new EDA_3D_CANVAS( this,
|
||||
COGL_ATT_LIST::GetAttributesList( true ),
|
||||
m_dummyBoard,
|
||||
*m_settings3Dviewer,
|
||||
aCacheManager );
|
||||
|
||||
m_SizerPanelView->Add( m_previewPane, 1, wxEXPAND );
|
||||
|
||||
m_previewPane->Connect( wxEVT_ENTER_WINDOW,
|
||||
wxMouseEventHandler( PANEL_PREV_3D::onEnterPreviewCanvas ),
|
||||
NULL, this );
|
||||
}
|
||||
|
||||
|
||||
PANEL_PREV_3D::~PANEL_PREV_3D()
|
||||
{
|
||||
m_previewPane->Disconnect( wxEVT_ENTER_WINDOW,
|
||||
wxMouseEventHandler( PANEL_PREV_3D::onEnterPreviewCanvas ),
|
||||
NULL, this );
|
||||
|
||||
delete m_settings3Dviewer;
|
||||
delete m_dummyBoard;
|
||||
delete m_previewPane;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::initPanel()
|
||||
{
|
||||
m_resolver = NULL;
|
||||
currentModelFile.clear();
|
||||
m_dummyBoard = new BOARD();
|
||||
m_currentSelectedIdx = -1;
|
||||
|
||||
// Set the bitmap of 3D view buttons:
|
||||
m_bpvTop->SetBitmap( KiBitmap( axis3d_top_xpm ) );
|
||||
m_bpvFront->SetBitmap( KiBitmap( axis3d_front_xpm ) );
|
||||
m_bpvBack->SetBitmap( KiBitmap( axis3d_back_xpm ) );
|
||||
m_bpvLeft->SetBitmap( KiBitmap( axis3d_left_xpm ) );
|
||||
m_bpvRight->SetBitmap( KiBitmap( axis3d_right_xpm ) );
|
||||
m_bpvBottom->SetBitmap( KiBitmap( axis3d_bottom_xpm ) );
|
||||
m_bpvISO->SetBitmap( KiBitmap( ortho_xpm ) );
|
||||
m_bpUpdate->SetBitmap( KiBitmap( reload_xpm ) );
|
||||
|
||||
// Set the min and max values of spin buttons (mandatory on Linux)
|
||||
// They are not used, so they are set to min and max 32 bits int values
|
||||
// (the min and max values supported by a wxSpinButton)
|
||||
// It avoids blocking the up or down arrows when reaching this limit after
|
||||
// a few clicks.
|
||||
wxSpinButton* spinButtonList[] =
|
||||
{
|
||||
m_spinXscale, m_spinYscale, m_spinZscale,
|
||||
m_spinXrot, m_spinYrot, m_spinZrot,
|
||||
m_spinXoffset,m_spinYoffset, m_spinZoffset
|
||||
};
|
||||
|
||||
for( int ii = 0; ii < 9; ii++ )
|
||||
{
|
||||
spinButtonList[ii]->SetRange( INT_MIN, INT_MAX );
|
||||
}
|
||||
|
||||
wxString units;
|
||||
|
||||
switch( g_UserUnit )
|
||||
{
|
||||
case INCHES:
|
||||
units = _( "inches" );
|
||||
break;
|
||||
case MILLIMETRES:
|
||||
units = _( "mm" );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( !units.IsEmpty() )
|
||||
{
|
||||
units = wxString::Format( _( "Offset (%s)" ), units );
|
||||
m_staticTextOffset->SetLabel( units );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief checkRotation
|
||||
* Ensure -MAX_ROTATION <= rotation <= MAX_ROTATION
|
||||
* aRotation will be normalized between -MAX_ROTATION and MAX_ROTATION
|
||||
* @param aRotation: in out parameter
|
||||
*/
|
||||
static void checkRotation( double& aRotation )
|
||||
{
|
||||
if( aRotation > MAX_ROTATION )
|
||||
{
|
||||
int n = aRotation / MAX_ROTATION;
|
||||
aRotation -= MAX_ROTATION * n;
|
||||
}
|
||||
else if( aRotation < -MAX_ROTATION )
|
||||
{
|
||||
int n = -aRotation / MAX_ROTATION;
|
||||
aRotation += MAX_ROTATION * n;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool validateFloatTextCtrl( wxTextCtrl* aTextCtrl )
|
||||
{
|
||||
if( aTextCtrl == NULL )
|
||||
return false;
|
||||
|
||||
if( aTextCtrl->GetLineLength(0) == 0 ) // This will skip the got and event with empty field
|
||||
return false;
|
||||
|
||||
if( aTextCtrl->GetLineLength(0) == 1 )
|
||||
{
|
||||
if( (aTextCtrl->GetLineText(0).compare( "." ) == 0) ||
|
||||
(aTextCtrl->GetLineText(0).compare( "," ) == 0) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void incrementTextCtrl( wxTextCtrl* aTextCtrl, double aInc, double aMinval, double aMaxval )
|
||||
{
|
||||
if( !validateFloatTextCtrl( aTextCtrl ) )
|
||||
return;
|
||||
|
||||
double curr_value = 0;
|
||||
|
||||
aTextCtrl->GetValue().ToDouble( &curr_value );
|
||||
curr_value += aInc;
|
||||
|
||||
if( curr_value > aMaxval )
|
||||
curr_value = aMaxval;
|
||||
|
||||
if( curr_value < aMinval )
|
||||
curr_value = aMinval;
|
||||
|
||||
aTextCtrl->SetValue( wxString::Format( "%.4f", curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::SetModelDataIdx( int idx, bool aReloadPreviewModule )
|
||||
{
|
||||
wxASSERT( m_parentInfoList != NULL );
|
||||
|
||||
if( m_parentInfoList && (idx >= 0) )
|
||||
{
|
||||
wxASSERT( (unsigned int)idx < (*m_parentInfoList).size() );
|
||||
|
||||
if( (unsigned int)idx < (*m_parentInfoList).size() )
|
||||
{
|
||||
m_currentSelectedIdx = -1; // In case that we receive events on the
|
||||
// next updates, it will set first an
|
||||
// invalid selection
|
||||
|
||||
const MODULE_3D_SETTINGS *aModel = (const MODULE_3D_SETTINGS *)&((*m_parentInfoList)[idx]);
|
||||
|
||||
xscale->SetValue( wxString::Format( "%.4f", aModel->m_Scale.x ) );
|
||||
yscale->SetValue( wxString::Format( "%.4f", aModel->m_Scale.y ) );
|
||||
zscale->SetValue( wxString::Format( "%.4f", aModel->m_Scale.z ) );
|
||||
|
||||
xrot->SetValue( wxString::Format( "%.2f", aModel->m_Rotation.x ) );
|
||||
yrot->SetValue( wxString::Format( "%.2f", aModel->m_Rotation.y ) );
|
||||
zrot->SetValue( wxString::Format( "%.2f", aModel->m_Rotation.z ) );
|
||||
|
||||
// Convert from internal units (mm) to user units
|
||||
|
||||
double scaler = 1;
|
||||
|
||||
switch( g_UserUnit )
|
||||
{
|
||||
case MILLIMETRES:
|
||||
scaler = 1.0f;
|
||||
break;
|
||||
case INCHES:
|
||||
scaler = 25.4f;
|
||||
break;
|
||||
default:
|
||||
wxASSERT( 0 );
|
||||
}
|
||||
|
||||
xoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.x / scaler ) );
|
||||
yoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.y / scaler ) );
|
||||
zoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.z / scaler ) );
|
||||
|
||||
UpdateModelName( aModel->m_Filename );
|
||||
|
||||
if( aReloadPreviewModule && m_previewPane )
|
||||
{
|
||||
updateListOnModelCopy();
|
||||
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Request_refresh();
|
||||
}
|
||||
|
||||
m_currentSelectedIdx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::ResetModelData( bool aReloadPreviewModule )
|
||||
{
|
||||
m_currentSelectedIdx = -1;
|
||||
|
||||
xscale->SetValue( wxString::FromDouble( 1.0 ) );
|
||||
yscale->SetValue( wxString::FromDouble( 1.0 ) );
|
||||
zscale->SetValue( wxString::FromDouble( 1.0 ) );
|
||||
|
||||
xrot->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
yrot->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
zrot->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
|
||||
xoff->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
yoff->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
zoff->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
|
||||
// This will update the model on the preview board with the current list of 3d shapes
|
||||
if( aReloadPreviewModule )
|
||||
{
|
||||
updateListOnModelCopy();
|
||||
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Request_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
if( m_previewPane )
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::UpdateModelName( wxString const& aModelName )
|
||||
{
|
||||
bool newModel = false;
|
||||
|
||||
m_modelInfo.m_Filename = aModelName;
|
||||
|
||||
// if the model name is a directory simply clear the current model
|
||||
if( aModelName.empty() || wxFileName::DirExists( aModelName ) )
|
||||
{
|
||||
currentModelFile.clear();
|
||||
m_modelInfo.m_Filename.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString newModelFile;
|
||||
|
||||
if( m_resolver )
|
||||
newModelFile = m_resolver->ResolvePath( aModelName );
|
||||
|
||||
if( !newModelFile.empty() && newModelFile.Cmp( currentModelFile ) )
|
||||
newModel = true;
|
||||
|
||||
currentModelFile = newModelFile;
|
||||
}
|
||||
|
||||
if( currentModelFile.empty() || newModel )
|
||||
{
|
||||
updateListOnModelCopy();
|
||||
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
if( currentModelFile.empty() )
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_previewPane )
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
if( m_previewPane )
|
||||
m_previewPane->SetFocus();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::updateOrientation( wxCommandEvent &event )
|
||||
{
|
||||
wxTextCtrl *textCtrl = (wxTextCtrl *)event.GetEventObject();
|
||||
|
||||
if( textCtrl == NULL )
|
||||
return;
|
||||
|
||||
if( textCtrl->GetLineLength(0) == 0 ) // This will skip the got and event with empty field
|
||||
return;
|
||||
|
||||
if( textCtrl->GetLineLength(0) == 1 )
|
||||
if( (textCtrl->GetLineText(0).compare( "." ) == 0) ||
|
||||
(textCtrl->GetLineText(0).compare( "," ) == 0) )
|
||||
return;
|
||||
|
||||
SGPOINT scale;
|
||||
SGPOINT rotation;
|
||||
SGPOINT offset;
|
||||
|
||||
getOrientationVars( scale, rotation, offset );
|
||||
|
||||
m_modelInfo.m_Scale.x = scale.x;
|
||||
m_modelInfo.m_Scale.y = scale.y;
|
||||
m_modelInfo.m_Scale.z = scale.z;
|
||||
m_modelInfo.m_Offset.x = offset.x;
|
||||
m_modelInfo.m_Offset.y = offset.y;
|
||||
m_modelInfo.m_Offset.z = offset.z;
|
||||
m_modelInfo.m_Rotation.x = rotation.x;
|
||||
m_modelInfo.m_Rotation.y = rotation.y;
|
||||
m_modelInfo.m_Rotation.z = rotation.z;
|
||||
|
||||
if( m_currentSelectedIdx >= 0 )
|
||||
{
|
||||
// This will update the parent list with the new data
|
||||
(*m_parentInfoList)[m_currentSelectedIdx] = m_modelInfo;
|
||||
|
||||
// It will update the copy model in the preview board
|
||||
updateListOnModelCopy();
|
||||
|
||||
// Since the OpenGL render does not need to be reloaded to update the
|
||||
// shapes position, we just request to redraw again the canvas
|
||||
if( m_previewPane )
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onIncrementRot( wxSpinEvent& event )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xrot;
|
||||
|
||||
if( spinCtrl == m_spinYrot )
|
||||
textCtrl = yrot;
|
||||
else if( spinCtrl == m_spinZrot )
|
||||
textCtrl = zrot;
|
||||
|
||||
incrementTextCtrl( textCtrl, ROTATION_INCREMENT, -MAX_ROTATION, MAX_ROTATION );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onDecrementRot( wxSpinEvent& event )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xrot;
|
||||
|
||||
if( spinCtrl == m_spinYrot )
|
||||
textCtrl = yrot;
|
||||
else if( spinCtrl == m_spinZrot )
|
||||
textCtrl = zrot;
|
||||
|
||||
incrementTextCtrl( textCtrl, -ROTATION_INCREMENT, -MAX_ROTATION, MAX_ROTATION );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onIncrementScale( wxSpinEvent& event )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xscale;
|
||||
|
||||
if( spinCtrl == m_spinYscale )
|
||||
textCtrl = yscale;
|
||||
else if( spinCtrl == m_spinZscale )
|
||||
textCtrl = zscale;
|
||||
|
||||
incrementTextCtrl( textCtrl, SCALE_INCREMENT, 1/MAX_SCALE, MAX_SCALE );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onDecrementScale( wxSpinEvent& event )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xscale;
|
||||
|
||||
if( spinCtrl == m_spinYscale )
|
||||
textCtrl = yscale;
|
||||
else if( spinCtrl == m_spinZscale )
|
||||
textCtrl = zscale;
|
||||
|
||||
incrementTextCtrl( textCtrl, -SCALE_INCREMENT, 1/MAX_SCALE, MAX_SCALE );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onIncrementOffset( wxSpinEvent& event )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xoff;
|
||||
|
||||
if( spinCtrl == m_spinYoffset )
|
||||
textCtrl = yoff;
|
||||
else if( spinCtrl == m_spinZoffset )
|
||||
textCtrl = zoff;
|
||||
|
||||
double step = OFFSET_INCREMENT_MM;
|
||||
|
||||
if( g_UserUnit == INCHES )
|
||||
step = OFFSET_INCREMENT_MIL/1000.0;
|
||||
|
||||
incrementTextCtrl( textCtrl, step, -MAX_OFFSET, MAX_OFFSET );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onDecrementOffset( wxSpinEvent& event )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xoff;
|
||||
|
||||
if( spinCtrl == m_spinYoffset )
|
||||
textCtrl = yoff;
|
||||
else if( spinCtrl == m_spinZoffset )
|
||||
textCtrl = zoff;
|
||||
|
||||
double step = OFFSET_INCREMENT_MM;
|
||||
|
||||
if( g_UserUnit == INCHES )
|
||||
step = OFFSET_INCREMENT_MIL/1000.0;
|
||||
|
||||
incrementTextCtrl( textCtrl, -step, -MAX_OFFSET, MAX_OFFSET );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onMouseWheelScale( wxMouseEvent& event )
|
||||
{
|
||||
wxTextCtrl* textCtrl = (wxTextCtrl*) event.GetEventObject();
|
||||
|
||||
double step = SCALE_INCREMENT;
|
||||
|
||||
if( event.ShiftDown( ) )
|
||||
step = SCALE_INCREMENT_FINE;
|
||||
|
||||
if( event.GetWheelRotation() >= 0 )
|
||||
step = -step;
|
||||
|
||||
incrementTextCtrl( textCtrl, step, 1/MAX_SCALE, MAX_SCALE );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onMouseWheelRot( wxMouseEvent& event )
|
||||
{
|
||||
wxTextCtrl* textCtrl = (wxTextCtrl*) event.GetEventObject();
|
||||
|
||||
wxKeyboardState kbdState;
|
||||
|
||||
double step = ROTATION_INCREMENT_WHEEL;
|
||||
|
||||
if( event.ShiftDown( ) )
|
||||
step = ROTATION_INCREMENT_WHEEL_FINE;
|
||||
|
||||
if( event.GetWheelRotation() >= 0 )
|
||||
step = -step;
|
||||
|
||||
incrementTextCtrl( textCtrl, step, -MAX_ROTATION, MAX_ROTATION );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onMouseWheelOffset( wxMouseEvent& event )
|
||||
{
|
||||
wxTextCtrl* textCtrl = (wxTextCtrl*) event.GetEventObject();
|
||||
|
||||
double step = OFFSET_INCREMENT_MM;
|
||||
|
||||
if( event.ShiftDown( ) )
|
||||
step = OFFSET_INCREMENT_MM_FINE;
|
||||
|
||||
if( g_UserUnit == INCHES )
|
||||
{
|
||||
step = OFFSET_INCREMENT_MIL/1000.0;
|
||||
if( event.ShiftDown( ) )
|
||||
step = OFFSET_INCREMENT_MIL_FINE/1000.0;
|
||||
}
|
||||
|
||||
if( event.GetWheelRotation() >= 0 )
|
||||
step = -step;
|
||||
|
||||
incrementTextCtrl( textCtrl, step, -MAX_OFFSET, MAX_OFFSET );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::getOrientationVars( SGPOINT& aScale, SGPOINT& aRotation, SGPOINT& aOffset )
|
||||
{
|
||||
if( NULL == xscale || NULL == yscale || NULL == zscale
|
||||
|| NULL == xrot || NULL == yrot || NULL == zrot
|
||||
|| NULL == xoff || NULL == yoff || NULL == zoff )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
xscale->GetValue().ToDouble( &aScale.x );
|
||||
yscale->GetValue().ToDouble( &aScale.y );
|
||||
zscale->GetValue().ToDouble( &aScale.z );
|
||||
|
||||
xrot->GetValue().ToDouble( &aRotation.x );
|
||||
yrot->GetValue().ToDouble( &aRotation.y );
|
||||
zrot->GetValue().ToDouble( &aRotation.z );
|
||||
|
||||
checkRotation( aRotation.x );
|
||||
checkRotation( aRotation.y );
|
||||
checkRotation( aRotation.z );
|
||||
|
||||
xoff->GetValue().ToDouble( &aOffset.x );
|
||||
yoff->GetValue().ToDouble( &aOffset.y );
|
||||
zoff->GetValue().ToDouble( &aOffset.z );
|
||||
|
||||
// Convert from user units to internal units (mm)
|
||||
|
||||
double scaler = 1.0f;
|
||||
|
||||
switch( g_UserUnit )
|
||||
{
|
||||
case MILLIMETRES:
|
||||
scaler = 1.0f;
|
||||
break;
|
||||
case INCHES:
|
||||
scaler = 25.4f;
|
||||
break;
|
||||
default:
|
||||
wxASSERT( 0 );
|
||||
}
|
||||
|
||||
aOffset.x *= scaler;
|
||||
aOffset.y *= scaler;
|
||||
aOffset.z *= scaler;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool PANEL_PREV_3D::ValidateWithMessage( wxString& aErrorMessage )
|
||||
{
|
||||
bool invalidScale = false;
|
||||
|
||||
for( unsigned int idx = 0; idx < m_parentInfoList->size(); ++idx )
|
||||
{
|
||||
wxString msg;
|
||||
bool addError = false;
|
||||
MODULE_3D_SETTINGS& s3dshape = (*m_parentInfoList)[idx];
|
||||
|
||||
SGPOINT scale;
|
||||
scale.x = s3dshape.m_Scale.x;
|
||||
scale.y = s3dshape.m_Scale.y;
|
||||
scale.z = s3dshape.m_Scale.z;
|
||||
|
||||
if( 1/MAX_SCALE > scale.x || MAX_SCALE < scale.x )
|
||||
{
|
||||
invalidScale = true;
|
||||
addError = true;
|
||||
msg += _( "Invalid X scale" );
|
||||
}
|
||||
|
||||
if( 1/MAX_SCALE > scale.y || MAX_SCALE < scale.y )
|
||||
{
|
||||
invalidScale = true;
|
||||
addError = true;
|
||||
|
||||
if( !msg.IsEmpty() )
|
||||
msg += "\n";
|
||||
|
||||
msg += _( "Invalid Y scale" );
|
||||
}
|
||||
|
||||
if( 1/MAX_SCALE > scale.z || MAX_SCALE < scale.z )
|
||||
{
|
||||
invalidScale = true;
|
||||
addError = true;
|
||||
|
||||
if( !msg.IsEmpty() )
|
||||
msg += "\n";
|
||||
|
||||
msg += _( "Invalid Z scale" );
|
||||
}
|
||||
|
||||
if( addError )
|
||||
{
|
||||
msg.Prepend( s3dshape.m_Filename + "\n" );
|
||||
|
||||
if( !aErrorMessage.IsEmpty() )
|
||||
aErrorMessage += "\n\n";
|
||||
|
||||
aErrorMessage += msg;
|
||||
}
|
||||
}
|
||||
|
||||
if( !aErrorMessage.IsEmpty() )
|
||||
{
|
||||
aErrorMessage += "\n\n";
|
||||
aErrorMessage += wxString::Format( "Min value = %.4f and max value = %.4f",
|
||||
1/MAX_SCALE, MAX_SCALE );
|
||||
}
|
||||
|
||||
return invalidScale == false;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::updateListOnModelCopy()
|
||||
{
|
||||
auto draw3D = &m_copyModule->Models();
|
||||
draw3D->clear();
|
||||
draw3D->insert( draw3D->end(), m_parentInfoList->begin(), m_parentInfoList->end() );
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2015-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file panel_prev_model.h
|
||||
* @brief Defines a panel which is to be added to a wxFileDialog via
|
||||
* SetExtraControl();
|
||||
* The panel shows a preview of the module being edited and provides controls
|
||||
* to set the offset/rotation/scale of each model 3d shape as per KiCad's
|
||||
* current behavior. The panel may also be used in the 3D configuration dialog
|
||||
* to tune the positioning of the models without invoking a file selector dialog.
|
||||
*/
|
||||
|
||||
#ifndef PANEL_PREV_MODEL_H
|
||||
#define PANEL_PREV_MODEL_H
|
||||
|
||||
#include "panel_prev_3d_base.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <3d_canvas/eda_3d_canvas.h>
|
||||
|
||||
// Define min and max parameter values
|
||||
#define MAX_SCALE 10000.0
|
||||
#define MAX_ROTATION 180.0
|
||||
#define MAX_OFFSET 1000.0
|
||||
|
||||
#define SCALE_INCREMENT_FINE 0.02
|
||||
#define SCALE_INCREMENT 0.1
|
||||
|
||||
#define ROTATION_INCREMENT 5 // in degrees, for spin button command
|
||||
#define ROTATION_INCREMENT_WHEEL 15 // in degrees, for mouse wheel command
|
||||
#define ROTATION_INCREMENT_WHEEL_FINE 1 // in degrees, for mouse wheel command
|
||||
|
||||
#define OFFSET_INCREMENT_MM 0.5
|
||||
#define OFFSET_INCREMENT_MM_FINE 0.1
|
||||
|
||||
#define OFFSET_INCREMENT_MIL 25.0
|
||||
#define OFFSET_INCREMENT_MIL_FINE 5.0
|
||||
|
||||
|
||||
// Declared classes to create pointers
|
||||
class S3D_CACHE;
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
class BOARD;
|
||||
class CINFO3D_VISU;
|
||||
class MODULE;
|
||||
class COLORS_DESIGN_SETTINGS;
|
||||
|
||||
class PANEL_PREV_3D: public PANEL_PREV_3D_BASE
|
||||
{
|
||||
public:
|
||||
PANEL_PREV_3D( wxWindow* aParent, S3D_CACHE* aCacheManager,
|
||||
MODULE* aModuleCopy,
|
||||
COLORS_DESIGN_SETTINGS *aColors,
|
||||
std::vector<MODULE_3D_SETTINGS> *aParentInfoList = NULL );
|
||||
|
||||
~PANEL_PREV_3D();
|
||||
|
||||
private:
|
||||
wxString currentModelFile; ///< Used to check if the model file was changed
|
||||
S3D_FILENAME_RESOLVER *m_resolver; ///< Used to get the full path name
|
||||
|
||||
/// The 3D canvas
|
||||
EDA_3D_CANVAS *m_previewPane;
|
||||
|
||||
/// A dummy board used to store the copy moduled
|
||||
BOARD *m_dummyBoard;
|
||||
|
||||
/// The settings that will be used for this 3D viewer canvas
|
||||
CINFO3D_VISU *m_settings3Dviewer;
|
||||
|
||||
/// A pointer to a new copy of the original module
|
||||
MODULE *m_copyModule;
|
||||
|
||||
/// A pointer to the parent MODULE_3D_SETTINGS list that we will use to copy to the preview module
|
||||
std::vector<MODULE_3D_SETTINGS> *m_parentInfoList;
|
||||
|
||||
/// The current selected index of the MODULE_3D_SETTINGS list
|
||||
int m_currentSelectedIdx;
|
||||
|
||||
/// Current MODULE_3D_SETTINGS that is being edited
|
||||
MODULE_3D_SETTINGS m_modelInfo;
|
||||
|
||||
// Methods of the class
|
||||
private:
|
||||
void initPanel();
|
||||
|
||||
/**
|
||||
* @brief updateOrientation - it will receive the events from editing the fields
|
||||
* @param event
|
||||
*/
|
||||
void updateOrientation( wxCommandEvent &event ) override;
|
||||
|
||||
void onMouseWheelScale( wxMouseEvent& event ) override;
|
||||
void onMouseWheelRot( wxMouseEvent& event ) override;
|
||||
void onMouseWheelOffset( wxMouseEvent& event ) override;
|
||||
|
||||
void onIncrementRot( wxSpinEvent& event ) override;
|
||||
void onDecrementRot( wxSpinEvent& event ) override;
|
||||
void onIncrementScale( wxSpinEvent& event ) override;
|
||||
void onDecrementScale( wxSpinEvent& event ) override;
|
||||
void onIncrementOffset( wxSpinEvent& event ) override;
|
||||
void onDecrementOffset( wxSpinEvent& event ) override;
|
||||
|
||||
/**
|
||||
* @brief getOrientationVars - gets the transformation from entries and validate it
|
||||
* @param aScale: output scale var
|
||||
* @param aRotation: output rotation var
|
||||
* @param aOffset: output offset var
|
||||
*/
|
||||
void getOrientationVars( SGPOINT& aScale, SGPOINT& aRotation, SGPOINT& aOffset );
|
||||
|
||||
/**
|
||||
* @brief updateListOnModelCopy - copy the current shape list to the copy of module that is on
|
||||
* the preview dummy board
|
||||
*/
|
||||
void updateListOnModelCopy();
|
||||
|
||||
|
||||
void onEnterPreviewCanvas( wxMouseEvent& event )
|
||||
{
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
|
||||
void View3DISO( wxCommandEvent& event ) override
|
||||
{
|
||||
m_settings3Dviewer->CameraGet().ToggleProjection();
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
void View3DLeft( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( GR_KB_SHIFT + 'X' );
|
||||
}
|
||||
|
||||
void View3DFront( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( 'Y' );
|
||||
}
|
||||
|
||||
void View3DTop( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( 'Z' );
|
||||
}
|
||||
|
||||
void View3DUpdate( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
void View3DRight( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( 'X' );
|
||||
}
|
||||
|
||||
void View3DBack( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( GR_KB_SHIFT + 'Y' );
|
||||
}
|
||||
|
||||
void View3DBottom( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( GR_KB_SHIFT + 'Z' );
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief SetModelDataIdx - This will set the index of the INFO list that was set on the parent.
|
||||
* So we will update our values to edit based on the index on that list.
|
||||
* @param idx - The index that was selected
|
||||
* @param aReloadPreviewModule: if need to update the preview module
|
||||
*/
|
||||
void SetModelDataIdx( int idx, bool aReloadPreviewModule = false );
|
||||
|
||||
/**
|
||||
* @brief ResetModelData - Clear the values and reload the preview board
|
||||
* @param aReloadPreviewModule: if need to update the preview module
|
||||
*/
|
||||
void ResetModelData( bool aReloadPreviewModule = false );
|
||||
|
||||
void UpdateModelName( wxString const& aModel );
|
||||
|
||||
/**
|
||||
* @brief verify X,Y and Z scale factors are acceptable (> 0.001 and < 1000.0)
|
||||
* @return false if one (or more) value is not acceptable.
|
||||
* @param aErrorMessage is a wxString to store error messages, if any
|
||||
*/
|
||||
bool ValidateWithMessage( wxString& aErrorMessage );
|
||||
|
||||
bool Validate() override
|
||||
{
|
||||
wxString temp;
|
||||
return ValidateWithMessage(temp);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PANEL_PREV_MODEL_H
|
||||
@@ -1,102 +0,0 @@
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_SOURCE_DIR}/3d-viewer
|
||||
)
|
||||
|
||||
set( SG_FILES
|
||||
sg_base.cpp
|
||||
sg_node.cpp
|
||||
sg_helpers.cpp
|
||||
scenegraph.cpp
|
||||
sg_appearance.cpp
|
||||
sg_faceset.cpp
|
||||
sg_shape.cpp
|
||||
sg_colors.cpp
|
||||
sg_coords.cpp
|
||||
sg_normals.cpp
|
||||
sg_index.cpp
|
||||
sg_coordindex.cpp
|
||||
ifsg_node.cpp
|
||||
ifsg_transform.cpp
|
||||
ifsg_appearance.cpp
|
||||
ifsg_index.cpp
|
||||
ifsg_coordindex.cpp
|
||||
ifsg_colors.cpp
|
||||
ifsg_coords.cpp
|
||||
ifsg_faceset.cpp
|
||||
ifsg_normals.cpp
|
||||
ifsg_shape.cpp
|
||||
ifsg_api.cpp
|
||||
)
|
||||
|
||||
if( MINGW )
|
||||
list( APPEND SG_FILES ${CMAKE_SOURCE_DIR}/common/streamwrapper.cpp )
|
||||
endif( MINGW )
|
||||
|
||||
add_library( kicad_3dsg SHARED ${SG_FILES} )
|
||||
|
||||
if( APPLE )
|
||||
# puts library into the main kicad.app bundle in build tree
|
||||
set_target_properties( kicad_3dsg PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "${OSX_BUNDLE_BUILD_LIB_DIR}"
|
||||
INSTALL_NAME_DIR "${OSX_BUNDLE_BUILD_LIB_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
find_file( S3DSG_VERSION_FILE sg_version.h
|
||||
PATHS ${CMAKE_SOURCE_DIR}/include/plugins/3dapi NO_DEFAULT_PATH )
|
||||
|
||||
if( NOT ${S3DSG_VERSION_FILE} STREQUAL "S3DSG_VERSION_FILE-NOTFOUND" )
|
||||
|
||||
# extract the "#define KICADSG_VERSION_*" lines
|
||||
file( STRINGS ${S3DSG_VERSION_FILE} _version
|
||||
REGEX "^[' ','\t']*#define[' ','\t']*KICADSG_VERSION_.*" )
|
||||
|
||||
foreach( SVAR ${_version} )
|
||||
string( REGEX MATCH KICADSG_VERSION_[M,A,J,O,R,I,N,P,T,C,H,E,V]* _VARNAME ${SVAR} )
|
||||
string( REGEX MATCH [0-9]+ _VALUE ${SVAR} )
|
||||
|
||||
if( NOT ${_VARNAME} STREQUAL "" )
|
||||
if( NOT ${_VALUE} STREQUAL "" )
|
||||
set( ${_VARNAME} ${_VALUE} )
|
||||
else()
|
||||
set( ${_VARNAME} 0 )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
|
||||
if( NOT KICADSG_VERSION_MAJOR AND NOT ${KICADSG_VERSION_MAJOR} STREQUAL "0" )
|
||||
message( FATAL_ERROR "Cannot determine the S3DSG library version" )
|
||||
endif()
|
||||
|
||||
#ensure that NOT SG_VERSION* will evaluate to '0'
|
||||
if( NOT KICADSG_VERSION_MINOR )
|
||||
set( KICADSG_VERSION_MINOR 0 )
|
||||
endif()
|
||||
|
||||
if( NOT KICADSG_VERSION_PATCH )
|
||||
set( KICADSG_VERSION_PATCH 0 )
|
||||
endif()
|
||||
|
||||
set_target_properties( kicad_3dsg
|
||||
PROPERTIES SOVERSION
|
||||
${KICADSG_VERSION_MAJOR}.${KICADSG_VERSION_MINOR}.${KICADSG_VERSION_PATCH} )
|
||||
|
||||
message( STATUS "S3DSG version: ${KICADSG_VERSION_MAJOR}.${KICADSG_VERSION_MINOR}.${KICADSG_VERSION_PATCH}" )
|
||||
else()
|
||||
message( FATAL_ERROR "Cannot determine the S3DSG library version" )
|
||||
endif()
|
||||
|
||||
unset( S3DSG_VERSION_FILE CACHE )
|
||||
|
||||
# Define a flag to expose the appropriate EXPORT macro at build time
|
||||
target_compile_definitions( kicad_3dsg PRIVATE -DCOMPILE_SGLIB )
|
||||
|
||||
target_link_libraries( kicad_3dsg ${wxWidgets_LIBRARIES} )
|
||||
|
||||
install( TARGETS
|
||||
kicad_3dsg
|
||||
DESTINATION ${KICAD_LIB}
|
||||
COMPONENT binary
|
||||
)
|
||||
@@ -1,671 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
#include "plugins/3dapi/sg_version.h"
|
||||
#include "streamwrapper.h"
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
#include "3d_cache/sg/scenegraph.h"
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
#include "3d_cache/sg/sg_shape.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
static char BadNode[] = " * [BUG] NULL pointer passed for aNode\n";
|
||||
#endif
|
||||
|
||||
// version format of the cache file
|
||||
#define SG_VERSION_TAG "VERSION:2"
|
||||
|
||||
|
||||
static void formatMaterial( SMATERIAL& mat, SGAPPEARANCE const* app )
|
||||
{
|
||||
float v0, v1, v2;
|
||||
|
||||
app->ambient.GetColor( v0, v1, v2 );
|
||||
mat.m_Ambient.x = v0;
|
||||
mat.m_Ambient.y = v1;
|
||||
mat.m_Ambient.z = v2;
|
||||
|
||||
app->diffuse.GetColor( v0, v1, v2 );
|
||||
mat.m_Diffuse.x = v0;
|
||||
mat.m_Diffuse.y = v1;
|
||||
mat.m_Diffuse.z = v2;
|
||||
mat.m_Ambient.x *= v0;
|
||||
mat.m_Ambient.y *= v1;
|
||||
mat.m_Ambient.z *= v2;
|
||||
|
||||
app->emissive.GetColor( v0, v1, v2 );
|
||||
mat.m_Emissive.x = v0;
|
||||
mat.m_Emissive.y = v1;
|
||||
mat.m_Emissive.z = v2;
|
||||
|
||||
app->specular.GetColor( v0, v1, v2 );
|
||||
mat.m_Specular.x = v0;
|
||||
mat.m_Specular.y = v1;
|
||||
mat.m_Specular.z = v2;
|
||||
|
||||
mat.m_Shininess = app->shininess;
|
||||
mat.m_Transparency = app->transparency;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
bool reuse, bool renameNodes )
|
||||
{
|
||||
if( NULL == filename || filename[0] == 0 )
|
||||
return false;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( filename );
|
||||
|
||||
if( wxFileName::Exists( ofile ) )
|
||||
{
|
||||
if( !overwrite )
|
||||
return false;
|
||||
|
||||
// make sure we make no attempt to write a directory
|
||||
if( !wxFileName::FileExists( ofile ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == aTopNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aTopNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_TRANSFORM != aTopNode->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] aTopNode is not a SCENEGRAPH object";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
OPEN_OSTREAM( op, filename );
|
||||
|
||||
if( op.fail() )
|
||||
{
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "failed to open file" << " '" << filename << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
|
||||
op.imbue( std::locale( "C" ) );
|
||||
op << "#VRML V2.0 utf8\n";
|
||||
|
||||
if( renameNodes )
|
||||
{
|
||||
aTopNode->ResetNodeIndex();
|
||||
aTopNode->ReNameNodes();
|
||||
}
|
||||
|
||||
aTopNode->WriteVRML( op, reuse );
|
||||
|
||||
if( !op.fail() )
|
||||
{
|
||||
CLOSE_STREAM( op );
|
||||
return true;
|
||||
}
|
||||
|
||||
CLOSE_STREAM( op );
|
||||
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "problems encountered writing file" << " '" << filename << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void S3D::ResetNodeIndex( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aNode->ResetNodeIndex();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::RenameNodes( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aNode->ReNameNodes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::DestroyNode( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
delete aNode;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
const char* aPluginInfo )
|
||||
{
|
||||
if( NULL == aFileName || aFileName[0] == 0 )
|
||||
return false;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( aFileName );
|
||||
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if( wxFileName::Exists( ofile ) )
|
||||
{
|
||||
if( !overwrite )
|
||||
{
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "file exists; not overwriting" << " '";
|
||||
errmsg << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure we make no attempt to write a directory
|
||||
if( !wxFileName::FileExists( aFileName ) )
|
||||
{
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "specified path is a directory" << " '";
|
||||
errmsg << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
OPEN_OSTREAM( output, aFileName );
|
||||
|
||||
if( output.fail() )
|
||||
{
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "failed to open file" << " '" << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
|
||||
output << "(" << SG_VERSION_TAG << ")";
|
||||
|
||||
if( NULL != aPluginInfo && aPluginInfo[0] != 0 )
|
||||
output << "(" << aPluginInfo << ")";
|
||||
else
|
||||
output << "(INTERNAL:0.0.0.0)";
|
||||
|
||||
bool rval = aNode->WriteCache( output, NULL );
|
||||
CLOSE_STREAM( output );
|
||||
|
||||
if( !rval )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] problems encountered writing cache file '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
// delete the defective file
|
||||
wxRemoveFile( ofile );
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
bool (*aTagCheck)( const char*, void* ) )
|
||||
{
|
||||
if( NULL == aFileName || aFileName[0] == 0 )
|
||||
return NULL;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( aFileName );
|
||||
|
||||
if( !wxFileName::FileExists( aFileName ) )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = _( "no such file" );
|
||||
ostr << " * [INFO] " << errmsg.ToUTF8() << " '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SGNODE* np = new SCENEGRAPH( NULL );
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] failed to instantiate SCENEGRAPH";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPEN_ISTREAM( file, aFileName );
|
||||
|
||||
if( file.fail() )
|
||||
{
|
||||
delete np;
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = _( "failed to open file" );
|
||||
ostr << " * [INFO] " << errmsg.ToUTF8() << " '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// from SG_VERSION_TAG 1, read the version tag; if it's not the expected tag
|
||||
// then we fail to read the cache file
|
||||
do
|
||||
{
|
||||
std::string name;
|
||||
char schar;
|
||||
file.get( schar );
|
||||
|
||||
if( '(' != schar )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; missing left parenthesis at position ";
|
||||
ostr << file.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
CLOSE_STREAM( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file.get( schar );
|
||||
|
||||
while( ')' != schar && file.good() )
|
||||
{
|
||||
name.push_back( schar );
|
||||
file.get( schar );
|
||||
}
|
||||
|
||||
if( name.compare( SG_VERSION_TAG ) )
|
||||
{
|
||||
CLOSE_STREAM( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
// from SG_VERSION_TAG 2, read the PluginInfo string and check that it matches
|
||||
// version tag; if it's not the expected tag then we fail to read the file
|
||||
do
|
||||
{
|
||||
std::string name;
|
||||
char schar;
|
||||
file.get( schar );
|
||||
|
||||
if( '(' != schar )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; missing left parenthesis at position ";
|
||||
ostr << file.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
CLOSE_STREAM( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file.get( schar );
|
||||
|
||||
while( ')' != schar && file.good() )
|
||||
{
|
||||
name.push_back( schar );
|
||||
file.get( schar );
|
||||
}
|
||||
|
||||
// check the plugin tag
|
||||
if( NULL != aTagCheck && NULL != aPluginMgr && !aTagCheck( name.c_str(), aPluginMgr ) )
|
||||
{
|
||||
CLOSE_STREAM( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
bool rval = np->ReadCache( file, NULL );
|
||||
CLOSE_STREAM( file );
|
||||
|
||||
if( !rval )
|
||||
{
|
||||
delete np;
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "problems encountered reading cache file";
|
||||
ostr << " * [INFO] " << errmsg.ToUTF8() << " '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return np;
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D::GetModel( SCENEGRAPH* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return NULL;
|
||||
|
||||
if( aNode->GetNodeType() != S3D::SGTYPE_TRANSFORM )
|
||||
return NULL;
|
||||
|
||||
S3D::MATLIST materials;
|
||||
std::vector< SMESH > meshes;
|
||||
|
||||
// the materials list shall have a default color; although the VRML
|
||||
// default is an opaque black, the default used here shall be a median
|
||||
// gray in hopes that it may help highlight faulty models; this color is
|
||||
// also typical of MCAD applications. When a model has no associated
|
||||
// material color it shall be assigned the index 0.
|
||||
SGAPPEARANCE app( NULL );
|
||||
app.ambient = SGCOLOR( 0.6, 0.6, 0.6 );
|
||||
app.diffuse = SGCOLOR( 0.6, 0.6, 0.6 );
|
||||
app.specular = app.diffuse;
|
||||
app.shininess = 0.05;
|
||||
app.transparency = 0.0;
|
||||
|
||||
materials.matorder.push_back( &app );
|
||||
materials.matmap.insert( std::pair< SGAPPEARANCE const*, int >( &app, 0 ) );
|
||||
|
||||
if( aNode->Prepare( NULL, materials, meshes ) )
|
||||
{
|
||||
if( meshes.empty() )
|
||||
return NULL;
|
||||
|
||||
S3DMODEL* model = S3D::New3DModel();
|
||||
|
||||
// add all the materials
|
||||
size_t j = materials.matorder.size();
|
||||
SMATERIAL* lmat = new SMATERIAL[j];
|
||||
|
||||
for( size_t i = 0; i < j; ++i )
|
||||
formatMaterial( lmat[i], materials.matorder[i] );
|
||||
|
||||
model->m_Materials = lmat;
|
||||
model->m_MaterialsSize = j;
|
||||
|
||||
// add all the meshes
|
||||
j = meshes.size();
|
||||
SMESH* lmesh = new SMESH[j];
|
||||
|
||||
for( size_t i = 0; i < j; ++i )
|
||||
lmesh[i] = meshes[i];
|
||||
|
||||
model->m_Meshes = lmesh;
|
||||
model->m_MeshesSize = j;
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
size_t j = meshes.size();
|
||||
|
||||
for( size_t i = 0; i < j; ++i )
|
||||
S3D::Free3DMesh( meshes[i] );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Destroy3DModel( S3DMODEL** aModel )
|
||||
{
|
||||
if( NULL == aModel || NULL == *aModel )
|
||||
return;
|
||||
|
||||
S3DMODEL* m = *aModel;
|
||||
S3D::FREE_S3DMODEL( *m );
|
||||
delete m;
|
||||
*aModel = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void Free3DModel( S3DMODEL& aModel )
|
||||
{
|
||||
S3D::FREE_S3DMODEL( aModel );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Free3DMesh( SMESH& aMesh )
|
||||
{
|
||||
S3D::FREE_SMESH( aMesh );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D::New3DModel( void )
|
||||
{
|
||||
S3DMODEL* mp = new S3DMODEL;
|
||||
S3D::INIT_S3DMODEL( *mp );
|
||||
return mp;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Init3DMaterial( SMATERIAL& aMat )
|
||||
{
|
||||
S3D::INIT_SMATERIAL( aMat );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Init3DMesh( SMESH& aMesh )
|
||||
{
|
||||
S3D::INIT_SMESH( aMesh );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::GetLibVersion( unsigned char* Major, unsigned char* Minor,
|
||||
unsigned char* Patch, unsigned char* Revision )
|
||||
{
|
||||
if( Major )
|
||||
*Major = KICADSG_VERSION_MAJOR;
|
||||
|
||||
if( Minor )
|
||||
*Minor = KICADSG_VERSION_MINOR;
|
||||
|
||||
if( Revision )
|
||||
*Revision = KICADSG_VERSION_REVISION;
|
||||
|
||||
if( Patch )
|
||||
*Patch = KICADSG_VERSION_PATCH;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGVECTOR S3D::CalcTriNorm( const SGPOINT& p1, const SGPOINT& p2, const SGPOINT& p3 )
|
||||
{
|
||||
glm::dvec3 tri = glm::dvec3( 0.0, 0.0, 0.0 );
|
||||
glm::dvec3 pts[3];
|
||||
|
||||
pts[0] = glm::dvec3( p1.x, p1.y, p1.z );
|
||||
pts[1] = glm::dvec3( p2.x, p2.y, p2.z );
|
||||
pts[2] = glm::dvec3( p3.x, p3.y, p3.z );
|
||||
|
||||
// degenerate points are given a default 0, 0, 1 normal
|
||||
if( S3D::degenerate( pts ) )
|
||||
return SGVECTOR( 0.0, 0.0, 1.0 );
|
||||
|
||||
// normal
|
||||
tri = glm::cross( pts[1] - pts[0], pts[2] - pts[0] );
|
||||
glm::normalize( tri );
|
||||
|
||||
return SGVECTOR( tri.x, tri.y, tri.z );
|
||||
}
|
||||
|
||||
|
||||
S3D::SGTYPES S3D::GetSGNodeType( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return SGTYPE_END;
|
||||
|
||||
return aNode->GetNodeType();
|
||||
}
|
||||
|
||||
|
||||
SGNODE* S3D::GetSGNodeParent( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return NULL;
|
||||
|
||||
return aNode->GetParent();
|
||||
}
|
||||
|
||||
|
||||
bool S3D::AddSGNodeRef( SGNODE* aParent, SGNODE* aChild )
|
||||
{
|
||||
if( NULL == aParent || NULL == aChild )
|
||||
return false;
|
||||
|
||||
return aParent->AddRefNode( aChild );
|
||||
}
|
||||
|
||||
|
||||
bool S3D::AddSGNodeChild( SGNODE* aParent, SGNODE* aChild )
|
||||
{
|
||||
if( NULL == aParent || NULL == aChild )
|
||||
return false;
|
||||
|
||||
return aParent->AddChildNode( aChild );
|
||||
}
|
||||
|
||||
|
||||
void S3D::AssociateSGNodeWrapper( SGNODE* aObject, SGNODE** aRefPtr )
|
||||
{
|
||||
if( NULL == aObject || NULL == aRefPtr || aObject != *aRefPtr )
|
||||
return;
|
||||
|
||||
aObject->AssociateWrapper( aRefPtr );
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,472 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
#include "plugins/3dapi/ifsg_appearance.h"
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_APPEARANCE::IFSG_APPEARANCE( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_APPEARANCE::IFSG_APPEARANCE( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_APPEARANCE::IFSG_APPEARANCE( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_APPEARANCE != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGAPPEARANCE( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGAPPEARANCE";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject << "\n";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject << "\n";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetShininess( float aShininess )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aShininess < 0 || aShininess > 1.0 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] shininess out of range [0..1]";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGAPPEARANCE*)m_node)->shininess = aShininess;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetTransparency( float aTransparency )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aTransparency < 0 || aTransparency > 1.0 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] transparency out of range [0..1]";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGAPPEARANCE*)m_node)->transparency = aTransparency;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,267 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_colors.h"
|
||||
#include "3d_cache/sg/sg_colors.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COLORS::IFSG_COLORS( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COLORS::IFSG_COLORS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COLORS::IFSG_COLORS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_COLORS != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGCOLORS( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGCOLORS";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGCOLORS*)m_node)->GetColorList( aListSize, aColorList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->SetColorList( aListSize, aColorList );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::AddColor( double aRedValue, double aGreenValue, double aBlueValue )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->AddColor( aRedValue, aGreenValue, aBlueValue );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::AddColor( const SGCOLOR& aColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->AddColor( aColor );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_coordindex.h"
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COORDINDEX::IFSG_COORDINDEX( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDINDEX::IFSG_COORDINDEX( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDINDEX::IFSG_COORDINDEX( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
if( !pp )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDINDEX::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_COORDINDEX != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDINDEX::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGCOORDINDEX( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGCOORDINDEX";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDINDEX::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -1,267 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_coords.h"
|
||||
#include "3d_cache/sg/sg_coords.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COORDS::IFSG_COORDS( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDS::IFSG_COORDS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDS::IFSG_COORDS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_COORDS != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGCOORDS( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGCOORDS";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGCOORDS*)m_node)->GetCoordsList( aListSize, aCoordsList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->SetCoordsList( aListSize, aCoordsList );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->AddCoord( aXValue, aYValue, aZValue );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::AddCoord( const SGPOINT& aPoint )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->AddCoord( aPoint );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_faceset.h"
|
||||
#include "3d_cache/sg/sg_faceset.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_FACESET::IFSG_FACESET( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_FACESET::IFSG_FACESET( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_FACESET::IFSG_FACESET( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_FACESET::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_FACESET != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_FACESET::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGFACESET( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGFACESET";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_FACESET::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_FACESET::CalcNormals( SGNODE** aPtr )
|
||||
{
|
||||
if( m_node )
|
||||
return ((SGFACESET*)m_node)->CalcNormals( aPtr );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_index.h"
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_INDEX::IFSG_INDEX() : IFSG_NODE()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_INDEX::GetIndices( size_t& nIndices, int*& aIndexList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGINDEX*)m_node)->GetIndices( nIndices, aIndexList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_INDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGINDEX*)m_node)->SetIndices( nIndices, aIndexList );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_INDEX::AddIndex( int aIndex )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGINDEX*)m_node)->AddIndex( aIndex );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,296 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_node.h"
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
|
||||
// collection of common error strings used by the wrappers
|
||||
char BadObject[] = " * [BUG] operating on an invalid wrapper (object may have been deleted)";
|
||||
char BadOperand[] = " * [BUG] parameter aNode is an invalid wrapper; its data may have been deleted";
|
||||
char BadParent[] = " * [BUG] invalid parent node (data may have been deleted)";
|
||||
char WrongParent[] = " * [BUG] parent node type is incompatible";
|
||||
|
||||
IFSG_NODE::IFSG_NODE()
|
||||
{
|
||||
m_node = NULL;
|
||||
}
|
||||
|
||||
|
||||
IFSG_NODE::~IFSG_NODE()
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void IFSG_NODE::Destroy( void )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* IFSG_NODE::GetRawPtr( void )
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
|
||||
S3D::SGTYPES IFSG_NODE::GetNodeType( void ) const
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
|
||||
return m_node->GetNodeType();
|
||||
}
|
||||
|
||||
|
||||
SGNODE* IFSG_NODE::GetParent( void ) const
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->GetParent();
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::SetParent( SGNODE* aParent )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->SetParent( aParent );
|
||||
}
|
||||
|
||||
|
||||
const char* IFSG_NODE::GetName( void )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->GetName();
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::SetName( const char *aName )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->SetName( aName );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const char * IFSG_NODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->GetNodeTypeName( aNodeType );
|
||||
}
|
||||
|
||||
|
||||
SGNODE* IFSG_NODE::FindNode( const char *aNodeName )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->FindNode( aNodeName, NULL );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddRefNode( aNode );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::AddRefNode( IFSG_NODE& aNode )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = aNode.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadOperand;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddRefNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddChildNode( aNode );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::AddChildNode( IFSG_NODE& aNode )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = aNode.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadOperand;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddChildNode( np );
|
||||
}
|
||||
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_normals.h"
|
||||
#include "3d_cache/sg/sg_normals.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_NORMALS::IFSG_NORMALS( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_NORMALS::IFSG_NORMALS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_NORMALS::IFSG_NORMALS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_NORMALS != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGNORMALS( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGNORMALS";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGNORMALS*)m_node)->GetNormalList( aListSize, aNormalList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->SetNormalList( aListSize, aNormalList );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::AddNormal( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->AddNormal( aXValue, aYValue, aZValue );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::AddNormal( const SGVECTOR& aNormal )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->AddNormal( aNormal );
|
||||
return true;
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_shape.h"
|
||||
#include "3d_cache/sg/sg_shape.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_SHAPE::IFSG_SHAPE( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_SHAPE::IFSG_SHAPE( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_SHAPE::IFSG_SHAPE( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_SHAPE::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_SHAPE != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_SHAPE::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGSHAPE( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGSHAPE";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_SHAPE::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_transform.h"
|
||||
#include "3d_cache/sg/scenegraph.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
IFSG_TRANSFORM::IFSG_TRANSFORM( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SCENEGRAPH( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_TRANSFORM::IFSG_TRANSFORM( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SCENEGRAPH( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_TRANSFORM != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SCENEGRAPH( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SCENEGRAPH";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetRotation( const SGVECTOR& aRotationAxis, double aAngle )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->rotation_axis = aRotationAxis;
|
||||
((SCENEGRAPH*)m_node)->rotation_angle = aAngle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetScale( const SGPOINT& aScale )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale = aScale;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetScale( double aScale )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aScale < 1e-8 && aScale > -1e-8 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] |scale| is < 1e-8 - this seems strange";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale = SGPOINT( aScale, aScale, aScale );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetTranslation( const SGPOINT& aTranslation )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->translation = aTranslation;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetScaleOrientation( const SGVECTOR& aScaleAxis, double aAngle )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale_axis = aScaleAxis;
|
||||
((SCENEGRAPH*)m_node)->scale_angle = aAngle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetCenter( const SGPOINT& aCenter )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->center = aCenter;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,817 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/ext.hpp>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/scenegraph.h"
|
||||
#include "3d_cache/sg/sg_shape.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
SCENEGRAPH::SCENEGRAPH( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_TRANSFORM;
|
||||
rotation_angle = 0.0;
|
||||
scale_angle = 0.0;
|
||||
|
||||
scale.x = 1.0;
|
||||
scale.y = 1.0;
|
||||
scale.z = 1.0;
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SCENEGRAPH (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH::~SCENEGRAPH()
|
||||
{
|
||||
// drop references
|
||||
DROP_REFS( SCENEGRAPH, m_RTransforms );
|
||||
DROP_REFS( SGSHAPE, m_RShape );
|
||||
|
||||
// delete owned objects
|
||||
DEL_OBJS( SCENEGRAPH, m_Transforms );
|
||||
DEL_OBJS( SGSHAPE, m_Shape );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a transform may be parent to a transform
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
FIND_NODE( SCENEGRAPH, aNodeName, m_Transforms, aCaller );
|
||||
FIND_NODE( SGSHAPE, aNodeName, m_Shape, aCaller );
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
|
||||
|
||||
void SCENEGRAPH::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
switch( aNode->GetNodeType() )
|
||||
{
|
||||
case S3D::SGTYPE_TRANSFORM:
|
||||
UNLINK_NODE( S3D::SGTYPE_TRANSFORM, SCENEGRAPH, aNode, m_Transforms, m_RTransforms, isChild );
|
||||
break;
|
||||
|
||||
case S3D::SGTYPE_SHAPE:
|
||||
UNLINK_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unlinkNode() did not find its target";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SCENEGRAPH::unlinkChildNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, true );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SCENEGRAPH::unlinkRefNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, false );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ADD_NODE( S3D::SGTYPE_TRANSFORM, SCENEGRAPH, aNode, m_Transforms, m_RTransforms, isChild );
|
||||
ADD_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] object '" << aNode->GetName();
|
||||
ostr << "' is not a valid type for this object (" << aNode->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
return addNode( aNode, false );
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
return addNode( aNode, true );
|
||||
}
|
||||
|
||||
|
||||
void SCENEGRAPH::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
|
||||
// rename all shapes
|
||||
do
|
||||
{
|
||||
std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
|
||||
std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
(*sL)->ReNameNodes();
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while(0);
|
||||
|
||||
// rename all transforms
|
||||
do
|
||||
{
|
||||
std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
|
||||
std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
(*sL)->ReNameNodes();
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( m_Transforms.empty() && m_RTransforms.empty()
|
||||
&& m_Shape.empty() && m_RShape.empty() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string tmp;
|
||||
|
||||
if( aReuseFlag )
|
||||
{
|
||||
if( !m_written )
|
||||
{
|
||||
aFile << "DEF " << GetName() << " Transform {\n";
|
||||
m_written = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << "USE " << GetName() << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " Transform {\n";
|
||||
}
|
||||
|
||||
// convert center to 1VRML unit = 0.1 inch
|
||||
SGPOINT pt = center;
|
||||
pt.x /= 2.54;
|
||||
pt.y /= 2.54;
|
||||
pt.z /= 2.54;
|
||||
|
||||
S3D::FormatPoint( tmp, pt );
|
||||
aFile << " center " << tmp << "\n";
|
||||
S3D::FormatOrientation( tmp, rotation_axis, rotation_angle );
|
||||
aFile << " rotation " << tmp << "\n";
|
||||
S3D::FormatPoint( tmp, scale );
|
||||
aFile << " scale " << tmp << "\n";
|
||||
S3D::FormatOrientation( tmp, scale_axis, scale_angle );
|
||||
aFile << " scaleOrientation " << tmp << "\n";
|
||||
|
||||
// convert translation to 1VRML unit = 0.1 inch
|
||||
pt = translation;
|
||||
pt.x /= 2.54;
|
||||
pt.y /= 2.54;
|
||||
pt.z /= 2.54;
|
||||
S3D::FormatPoint( tmp, pt );
|
||||
aFile << " translation " << tmp << "\n";
|
||||
|
||||
aFile << " children [\n";
|
||||
|
||||
if( !m_Transforms.empty() )
|
||||
{
|
||||
std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
|
||||
std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
(*sL)->WriteVRML( aFile, aReuseFlag );
|
||||
++sL;
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_RTransforms.empty() )
|
||||
{
|
||||
std::vector< SCENEGRAPH* >::iterator sL = m_RTransforms.begin();
|
||||
std::vector< SCENEGRAPH* >::iterator eL = m_RTransforms.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
(*sL)->WriteVRML( aFile, aReuseFlag );
|
||||
++sL;
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_Shape.empty() )
|
||||
{
|
||||
std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
|
||||
std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
(*sL)->WriteVRML( aFile, aReuseFlag );
|
||||
++sL;
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_RShape.empty() )
|
||||
{
|
||||
std::vector< SGSHAPE* >::iterator sL = m_RShape.begin();
|
||||
std::vector< SGSHAPE* >::iterator eL = m_RShape.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
(*sL)->WriteVRML( aFile, aReuseFlag );
|
||||
++sL;
|
||||
}
|
||||
}
|
||||
|
||||
aFile << "] }\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode && NULL != m_Parent )
|
||||
{
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
// ensure unique node names
|
||||
ResetNodeIndex();
|
||||
ReNameNodes();
|
||||
}
|
||||
|
||||
if( aFile.fail() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
S3D::WritePoint( aFile, center );
|
||||
S3D::WritePoint( aFile, translation );
|
||||
S3D::WriteVector( aFile, rotation_axis );
|
||||
aFile.write( (char*)&rotation_angle, sizeof( rotation_angle ) );
|
||||
S3D::WritePoint( aFile, scale );
|
||||
S3D::WriteVector( aFile, scale_axis );
|
||||
aFile.write( (char*)&scale_angle, sizeof( scale_angle ) );
|
||||
|
||||
// Transfer ownership of any Transform references which hadn't been written
|
||||
size_t asize = m_RTransforms.size();
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < asize; ++i )
|
||||
{
|
||||
if( !m_RTransforms[i]->isWritten() )
|
||||
{
|
||||
m_RTransforms[i]->SwapParent( this );
|
||||
--asize;
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer ownership of any Shape references which hadn't been written
|
||||
asize = m_RShape.size();
|
||||
|
||||
for( i = 0; i < asize; ++i )
|
||||
{
|
||||
if( !m_RShape[i]->isWritten() )
|
||||
{
|
||||
m_RShape[i]->SwapParent( this );
|
||||
--asize;
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
asize = m_Transforms.size();
|
||||
aFile.write( (char*)&asize, sizeof( size_t ) );
|
||||
asize = m_RTransforms.size();
|
||||
aFile.write( (char*)&asize, sizeof( size_t ) );
|
||||
asize = m_Shape.size();
|
||||
aFile.write( (char*)&asize, sizeof( size_t ) );
|
||||
asize = m_RShape.size();
|
||||
aFile.write( (char*)&asize, sizeof( size_t ) );
|
||||
asize = m_Transforms.size();
|
||||
|
||||
// write child transforms
|
||||
for( i = 0; i < asize; ++i )
|
||||
{
|
||||
if( !m_Transforms[i]->WriteCache( aFile, this ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream while writing child transforms";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// write referenced transform names
|
||||
asize = m_RTransforms.size();
|
||||
for( i = 0; i < asize; ++i )
|
||||
aFile << "[" << m_RTransforms[i]->GetName() << "]";
|
||||
|
||||
// write child shapes
|
||||
asize = m_Shape.size();
|
||||
for( i = 0; i < asize; ++i )
|
||||
{
|
||||
if( !m_Shape[i]->WriteCache( aFile, this ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream while writing child shapes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// write referenced transform names
|
||||
asize = m_RShape.size();
|
||||
for( i = 0; i < asize; ++i )
|
||||
aFile << "[" << m_RShape[i]->GetName() << "]";
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !m_Transforms.empty() || !m_RTransforms.empty()
|
||||
|| !m_Shape.empty() || !m_RShape.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name; // name of the node
|
||||
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
// we need to read the tag and verify its type
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; tag mismatch at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Name = name;
|
||||
}
|
||||
|
||||
// read fixed member data
|
||||
S3D::ReadPoint( aFile, center );
|
||||
S3D::ReadPoint( aFile, translation );
|
||||
S3D::ReadVector( aFile, rotation_axis );
|
||||
aFile.read( (char*)&rotation_angle, sizeof( rotation_angle ) );
|
||||
S3D::ReadPoint( aFile, scale );
|
||||
S3D::ReadVector( aFile, scale_axis );
|
||||
aFile.read( (char*)&scale_angle, sizeof( scale_angle ) );
|
||||
|
||||
size_t sizeCT = 0; // child transforms
|
||||
size_t sizeRT = 0; // referenced transforms
|
||||
size_t sizeCS = 0; // child shapes
|
||||
size_t sizeRS = 0; // referenced shapes
|
||||
|
||||
aFile.read( (char*)&sizeCT, sizeof( size_t ) );
|
||||
aFile.read( (char*)&sizeRT, sizeof( size_t ) );
|
||||
aFile.read( (char*)&sizeCS, sizeof( size_t ) );
|
||||
aFile.read( (char*)&sizeRS, sizeof( size_t ) );
|
||||
|
||||
size_t i;
|
||||
|
||||
// read child transforms
|
||||
for( i = 0; i < sizeCT; ++i )
|
||||
{
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child transform tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SCENEGRAPH* sp = new SCENEGRAPH( this );
|
||||
sp->SetName( name.c_str() );
|
||||
|
||||
if( !sp->ReadCache( aFile, this ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading transform '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// read referenced transforms
|
||||
for( i = 0; i < sizeRT; ++i )
|
||||
{
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref transform tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* sp = FindNode( name.c_str(), this );
|
||||
|
||||
if( !sp )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref transform '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_TRANSFORM != sp->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not TRANSFORM '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
AddRefNode( sp );
|
||||
}
|
||||
|
||||
// read child shapes
|
||||
for( i = 0; i < sizeCS; ++i )
|
||||
{
|
||||
if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child shape tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGSHAPE* sp = new SGSHAPE( this );
|
||||
sp->SetName( name.c_str() );
|
||||
|
||||
if( !sp->ReadCache( aFile, this ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading shape '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// read referenced shapes
|
||||
for( i = 0; i < sizeRS; ++i )
|
||||
{
|
||||
if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref shape tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* sp = FindNode( name.c_str(), this );
|
||||
|
||||
if( !sp )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref shape '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_SHAPE != sp->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGSHAPE '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
AddRefNode( sp );
|
||||
}
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes )
|
||||
{
|
||||
// calculate the accumulated transform
|
||||
double rX, rY, rZ;
|
||||
// rotation
|
||||
rotation_axis.GetVector( rX, rY, rZ );
|
||||
glm::dmat4 rM = glm::rotate( glm::dmat4( 1.0 ), rotation_angle, glm::dvec3( rX, rY, rZ ) );
|
||||
// translation
|
||||
glm::dmat4 tM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( translation.x, translation.y, translation.z ) );
|
||||
// center
|
||||
glm::dmat4 cM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( center.x, center.y, center.z ) );
|
||||
glm::dmat4 ncM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( -center.x, -center.y, -center.z ) );
|
||||
// scale
|
||||
glm::dmat4 sM = glm::scale( glm::dmat4( 1.0 ), glm::dvec3( scale.x, scale.y, scale.z ) );
|
||||
// scaleOrientation
|
||||
scale_axis.GetVector( rX, rY, rZ );
|
||||
glm::dmat4 srM = glm::rotate( glm::dmat4( 1.0 ), scale_angle, glm::dvec3( rX, rY, rZ ) );
|
||||
glm::dmat4 nsrM = glm::rotate( glm::dmat4( 1.0 ), -scale_angle, glm::dvec3( rX, rY, rZ ) );
|
||||
|
||||
// resultant point:
|
||||
// P' = T x C x R x SR x S x -SR x -C x P
|
||||
// resultant transform:
|
||||
// tx0 = tM * cM * rM * srM * sM * nsrM * ncM
|
||||
glm::dmat4 tx0;
|
||||
|
||||
if( NULL != aTransform )
|
||||
tx0 = (*aTransform) * tM * cM * rM * srM * sM * nsrM * ncM;
|
||||
else
|
||||
tx0 = tM * cM * rM * srM * sM * nsrM * ncM;
|
||||
|
||||
bool ok = true;
|
||||
|
||||
// prepare all shapes
|
||||
do
|
||||
{
|
||||
std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
|
||||
std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
|
||||
|
||||
while( sL != eL && ok )
|
||||
{
|
||||
ok = (*sL)->Prepare( &tx0, materials, meshes );
|
||||
++sL;
|
||||
}
|
||||
|
||||
sL = m_RShape.begin();
|
||||
eL = m_RShape.end();
|
||||
|
||||
while( sL != eL && ok )
|
||||
{
|
||||
ok = (*sL)->Prepare( &tx0, materials, meshes );
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while(0);
|
||||
|
||||
// prepare all transforms
|
||||
do
|
||||
{
|
||||
std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
|
||||
std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
|
||||
|
||||
while( sL != eL && ok )
|
||||
{
|
||||
ok = (*sL)->Prepare( &tx0, materials, meshes );
|
||||
++sL;
|
||||
}
|
||||
|
||||
sL = m_RTransforms.begin();
|
||||
eL = m_RTransforms.end();
|
||||
|
||||
while( sL != eL && ok )
|
||||
{
|
||||
ok = (*sL)->Prepare( &tx0, materials, meshes );
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while(0);
|
||||
|
||||
return ok;
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file scenegraph.h
|
||||
* defines the basic data set required to represent a 3D model;
|
||||
* this model must remain compatible with VRML2.0 in order to
|
||||
* facilitate VRML export of scene graph data created by available
|
||||
* 3D plugins.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SCENE_GRAPH_H
|
||||
#define SCENE_GRAPH_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGSHAPE;
|
||||
|
||||
class SCENEGRAPH : public SGNODE
|
||||
{
|
||||
private:
|
||||
// The following are items which may be defined for reuse
|
||||
// in a VRML output file. They do not necessarily correspond
|
||||
// to the use of DEF within a VRML input file; it is the
|
||||
// responsibility of the plugin to perform any necessary
|
||||
// conversions to comply with the restrictions imposed by
|
||||
// this scene graph structure
|
||||
std::vector< SCENEGRAPH* > m_Transforms; // local Transform nodes
|
||||
std::vector< SGSHAPE* > m_Shape; // local Shape nodes
|
||||
|
||||
std::vector< SCENEGRAPH* > m_RTransforms; // referenced Transform nodes
|
||||
std::vector< SGSHAPE* > m_RShape; // referenced Shape nodes
|
||||
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
public:
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
// note: order of transformation is Translate, Rotate, Offset
|
||||
SGPOINT center;
|
||||
SGPOINT translation;
|
||||
SGVECTOR rotation_axis;
|
||||
double rotation_angle; // radians
|
||||
SGPOINT scale;
|
||||
SGVECTOR scale_axis;
|
||||
double scale_angle; // radians
|
||||
|
||||
SCENEGRAPH( SGNODE* aParent );
|
||||
virtual ~SCENEGRAPH();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
bool Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes );
|
||||
};
|
||||
|
||||
/*
|
||||
p.120
|
||||
Transform {
|
||||
center 0 0 0
|
||||
children []
|
||||
rotation 0 0 1 0
|
||||
scale 1 1 1
|
||||
scaleOrientation 0 0 1 0
|
||||
translation 0 0 0
|
||||
bboxCenter 0 0 0
|
||||
bboxSize -1 -1 -1
|
||||
}
|
||||
*/
|
||||
|
||||
#endif // SCENE_GRAPH_H
|
||||
@@ -1,452 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
SGAPPEARANCE::SGAPPEARANCE( SGNODE* aParent ) : SGNODE( aParent)
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_APPEARANCE;
|
||||
|
||||
// defaults in accord with VRML2.0 spec
|
||||
ambient.SetColor( 0.05317, 0.17879, 0.01804 );
|
||||
shininess = 0.2;
|
||||
transparency = 0.0;
|
||||
diffuse.SetColor( 0.8, 0.8, 0.8 );
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGAPPEARANCE (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( NULL != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGAPPEARANCE::~SGAPPEARANCE()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGSHAPE may be parent to a SGAPPEARANCE
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
return emissive.SetColor( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return emissive.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetEmissive( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
return emissive.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
return diffuse.SetColor( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return diffuse.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetDiffuse( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
return diffuse.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
return specular.SetColor( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return specular.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
bool SGAPPEARANCE::SetSpecular( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
return specular.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetAmbient( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
return ambient.SetColor( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetAmbient( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ambient.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetAmbient( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
return ambient.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGAPPEARANCE::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGAPPEARANCE::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGAPPEARANCE::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SGAPPEARANCE::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( aReuseFlag )
|
||||
{
|
||||
if( !m_written )
|
||||
{
|
||||
aFile << " appearance DEF " << GetName() << " Appearance {\n";
|
||||
m_written = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " appearance USE " << GetName() << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " appearance Appearance {\n";
|
||||
}
|
||||
|
||||
aFile << " material Material {\n";
|
||||
|
||||
std::string tmp;
|
||||
float ambr, ambg, ambb;
|
||||
ambient.GetColor( ambr, ambg, ambb );
|
||||
float amb = ( 0.212671 * ambr + 0.71516 * ambg + 0.072169 * ambb );
|
||||
diffuse.GetColor( ambr, ambg, ambb );
|
||||
float den = ( 0.212671 * ambr + 0.71516 * ambg + 0.072169 * ambb );
|
||||
|
||||
if( den < 0.004 )
|
||||
den = 0.004;
|
||||
|
||||
amb /= den;
|
||||
|
||||
if( amb > 1.0 )
|
||||
amb = 1.0;
|
||||
|
||||
S3D::FormatFloat( tmp, amb );
|
||||
aFile << " ambientIntensity " << tmp << "\n";
|
||||
|
||||
float red, green, blue;
|
||||
diffuse.GetColor( red, green, blue );
|
||||
S3D::FormatFloat( tmp, red );
|
||||
aFile << " diffuseColor " << tmp << " ";
|
||||
S3D::FormatFloat( tmp, green );
|
||||
aFile << tmp << " ";
|
||||
S3D::FormatFloat( tmp, blue);
|
||||
aFile << tmp << "\n";
|
||||
|
||||
emissive.GetColor( red, green, blue );
|
||||
S3D::FormatFloat( tmp, red );
|
||||
aFile << " emissiveColor " << tmp << " ";
|
||||
S3D::FormatFloat( tmp, green );
|
||||
aFile << tmp << " ";
|
||||
S3D::FormatFloat( tmp, blue);
|
||||
aFile << tmp << "\n";
|
||||
|
||||
S3D::FormatFloat( tmp, shininess );
|
||||
aFile << " shininess " << tmp << "\n";
|
||||
|
||||
specular.GetColor( red, green, blue );
|
||||
S3D::FormatFloat( tmp, red );
|
||||
aFile << " specularColor " << tmp << " ";
|
||||
S3D::FormatFloat( tmp, green );
|
||||
aFile << tmp << " ";
|
||||
S3D::FormatFloat( tmp, blue);
|
||||
aFile << tmp << "\n";
|
||||
|
||||
S3D::FormatFloat( tmp, transparency );
|
||||
aFile << " transparency " << tmp << "\n";
|
||||
|
||||
aFile << "} }\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
S3D::WriteColor( aFile, ambient );
|
||||
aFile.write( (char*)&shininess, sizeof(shininess) );
|
||||
aFile.write( (char*)&transparency, sizeof(transparency) );
|
||||
S3D::WriteColor( aFile, diffuse );
|
||||
S3D::WriteColor( aFile, emissive );
|
||||
S3D::WriteColor( aFile, specular );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
S3D::ReadColor( aFile, ambient );
|
||||
aFile.read( (char*)&shininess, sizeof(shininess) );
|
||||
aFile.read( (char*)&transparency, sizeof(transparency) );
|
||||
S3D::ReadColor( aFile, diffuse );
|
||||
S3D::ReadColor( aFile, emissive );
|
||||
S3D::ReadColor( aFile, specular );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_appearance.h
|
||||
* defines the generic material appearance of a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_APPEARANCE_H
|
||||
#define SG_APPEARANCE_H
|
||||
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGAPPEARANCE : public SGNODE
|
||||
{
|
||||
public:
|
||||
float shininess; // default 0.2
|
||||
float transparency; // default 0.0
|
||||
SGCOLOR ambient; // default 0.05317 0.17879 0.01804
|
||||
SGCOLOR diffuse; // default 0.8 0.8 0.8
|
||||
SGCOLOR emissive; // default 0.0 0.0 0.0
|
||||
SGCOLOR specular; // default 0.0 0.0 0.0
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGAPPEARANCE( SGNODE* aParent );
|
||||
virtual ~SGAPPEARANCE();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
bool SetEmissive( float aRVal, float aGVal, float aBVal );
|
||||
bool SetEmissive( const SGCOLOR* aRGBColor );
|
||||
bool SetEmissive( const SGCOLOR& aRGBColor );
|
||||
|
||||
bool SetDiffuse( float aRVal, float aGVal, float aBVal );
|
||||
bool SetDiffuse( const SGCOLOR* aRGBColor );
|
||||
bool SetDiffuse( const SGCOLOR& aRGBColor );
|
||||
|
||||
bool SetSpecular( float aRVal, float aGVal, float aBVal );
|
||||
bool SetSpecular( const SGCOLOR* aRGBColor );
|
||||
bool SetSpecular( const SGCOLOR& aRGBColor );
|
||||
|
||||
bool SetAmbient( float aRVal, float aGVal, float aBVal );
|
||||
bool SetAmbient( const SGCOLOR* aRGBColor );
|
||||
bool SetAmbient( const SGCOLOR& aRGBColor );
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
};
|
||||
|
||||
#endif // SG_APPEARANCE_H
|
||||
@@ -1,340 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/sg_base.h"
|
||||
|
||||
|
||||
SGCOLOR::SGCOLOR()
|
||||
{
|
||||
red = 0.0;
|
||||
green = 0.0;
|
||||
blue = 0.0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SGCOLOR::SGCOLOR( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
if( !checkRange( aRVal, aGVal, aBVal ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid value passed to constructor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
red = 0.0;
|
||||
green = 0.0;
|
||||
blue = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
red = aRVal;
|
||||
green = aGVal;
|
||||
blue = aBVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( float& aRedVal, float& aGreenVal, float& aBlueVal ) const
|
||||
{
|
||||
aRedVal = red;
|
||||
aGreenVal = green;
|
||||
aBlueVal = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( SGCOLOR& aColor ) const
|
||||
{
|
||||
aColor.red = red;
|
||||
aColor.green = green;
|
||||
aColor.blue = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( SGCOLOR* aColor ) const
|
||||
{
|
||||
if( NULL == aColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aColor->red = red;
|
||||
aColor->green = green;
|
||||
aColor->blue = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::SetColor( float aRedVal, float aGreenVal, float aBlueVal )
|
||||
{
|
||||
if( !checkRange( aRedVal, aGreenVal, aBlueVal ) )
|
||||
return false;
|
||||
|
||||
red = aRedVal;
|
||||
green = aGreenVal;
|
||||
blue = aBlueVal;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::SetColor( const SGCOLOR& aColor )
|
||||
{
|
||||
red = aColor.red;
|
||||
green = aColor.green;
|
||||
blue = aColor.blue;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::SetColor( const SGCOLOR* aColor )
|
||||
{
|
||||
if( NULL == aColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
red = aColor->red;
|
||||
green = aColor->green;
|
||||
blue = aColor->blue;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::checkRange( float aRedVal, float aGreenVal, float aBlueVal ) const
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
if( aRedVal < 0.0 || aRedVal > 1.0 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid RED value: " << aRedVal;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if( aGreenVal < 0.0 || aGreenVal > 1.0 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if( ok )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__ );
|
||||
}
|
||||
wxLogTrace( MASK_3D_SG, " * [BUG] invalid GREEN value: %f\n", aGreenVal );
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if( aBlueVal < 0.0 || aBlueVal > 1.0 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if( ok )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__ );
|
||||
}
|
||||
wxLogTrace( MASK_3D_SG, " * [BUG] invalid BLUE value: %f\n", aBlueVal );
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
SGPOINT::SGPOINT()
|
||||
{
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
z = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGPOINT::SGPOINT( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
z = aZVal;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( double& aXVal, double& aYVal, double& aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
z = aZVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( SGPOINT& aPoint )
|
||||
{
|
||||
x = aPoint.x;
|
||||
y = aPoint.y;
|
||||
z = aPoint.z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( SGPOINT* aPoint )
|
||||
{
|
||||
if( NULL == aPoint )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aPoint";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
x = aPoint->x;
|
||||
y = aPoint->y;
|
||||
z = aPoint->z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::SetPoint( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
z = aZVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::SetPoint( const SGPOINT& aPoint )
|
||||
{
|
||||
x = aPoint.x;
|
||||
y = aPoint.y;
|
||||
z = aPoint.z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGVECTOR::SGVECTOR()
|
||||
{
|
||||
vx = 0.0;
|
||||
vy = 0.0;
|
||||
vz = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGVECTOR::SGVECTOR( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
vx = aXVal;
|
||||
vy = aYVal;
|
||||
vz = aZVal;
|
||||
normalize();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::GetVector( double& aXVal, double& aYVal, double& aZVal ) const
|
||||
{
|
||||
aXVal = vx;
|
||||
aYVal = vy;
|
||||
aZVal = vz;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::SetVector( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
vx = aXVal;
|
||||
vy = aYVal;
|
||||
vz = aZVal;
|
||||
normalize();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::SetVector( const SGVECTOR& aVector )
|
||||
{
|
||||
aVector.GetVector( vx, vy, vz );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::normalize( void )
|
||||
{
|
||||
double dx = vx * vx;
|
||||
double dy = vy * vy;
|
||||
double dz = vz * vz;
|
||||
double dv2 = sqrt( dx + dy + dz );
|
||||
|
||||
if( (dx + dy + dz) < 1e-8 )
|
||||
{
|
||||
// use the default; the numbers are too small
|
||||
// to be believable
|
||||
vx = 0.0;
|
||||
vy = 0.0;
|
||||
vz = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
vx /= dv2;
|
||||
vy /= dv2;
|
||||
vz /= dv2;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGVECTOR& SGVECTOR::operator=( const SGVECTOR& source )
|
||||
{
|
||||
vx = source.vx;
|
||||
vy = source.vy;
|
||||
vz = source.vz;
|
||||
return *this;
|
||||
}
|
||||
@@ -1,367 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_colors.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
SGCOLORS::SGCOLORS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COLORS;
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGCOLORS (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOLORS::~SGCOLORS()
|
||||
{
|
||||
colors.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGCOLORS
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGCOLORS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
|
||||
{
|
||||
if( colors.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aColorList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
aListSize = colors.size();
|
||||
aColorList = &colors[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
{
|
||||
colors.clear();
|
||||
|
||||
if( 0 == aListSize || NULL == aColorList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < aListSize; ++i )
|
||||
colors.push_back( aColorList[i] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::AddColor( double aRedValue, double aGreenValue, double aBlueValue )
|
||||
{
|
||||
colors.push_back( SGCOLOR( aRedValue, aGreenValue, aBlueValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::AddColor( const SGCOLOR& aColor )
|
||||
{
|
||||
colors.push_back( aColor );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( colors.empty() )
|
||||
return false;
|
||||
|
||||
if( aReuseFlag )
|
||||
{
|
||||
if( !m_written )
|
||||
{
|
||||
aFile << "color DEF " << GetName() << " Color { color [\n ";
|
||||
m_written = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << "color USE " << GetName() << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << "color Color { color [\n ";
|
||||
}
|
||||
|
||||
std::string tmp;
|
||||
size_t n = colors.size();
|
||||
bool nline = false;
|
||||
|
||||
for( size_t i = 0; i < n; )
|
||||
{
|
||||
S3D::FormatColor( tmp, colors[i] );
|
||||
float r,g,b;
|
||||
colors[i].GetColor(r, g, b);
|
||||
aFile << tmp ;
|
||||
++i;
|
||||
|
||||
if( i < n )
|
||||
{
|
||||
aFile << ",";
|
||||
|
||||
if( nline )
|
||||
{
|
||||
aFile << "\n ";
|
||||
nline = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nline = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
aFile << "] }\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
size_t ncolors = colors.size();
|
||||
aFile.write( (char*)&ncolors, sizeof(size_t) );
|
||||
|
||||
for( size_t i = 0; i < ncolors; ++i )
|
||||
S3D::WriteColor( aFile, colors[i] );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !colors.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t ncolors;
|
||||
aFile.read( (char*)&ncolors, sizeof(size_t) );
|
||||
SGCOLOR tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
for( size_t i = 0; i < ncolors; ++i )
|
||||
{
|
||||
if( !S3D::ReadColor( aFile, tmp ) || aFile.fail() )
|
||||
return false;
|
||||
|
||||
colors.push_back( tmp );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_colors.h
|
||||
* defines an RGB color set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COLORS_H
|
||||
#define SG_COLORS_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGCOLORS : public SGNODE
|
||||
{
|
||||
public:
|
||||
std::vector< SGCOLOR > colors;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGCOLORS( SGNODE* aParent );
|
||||
virtual ~SGCOLORS();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool GetColorList( size_t& aListSize, SGCOLOR*& aColorList );
|
||||
void SetColorList( size_t aListSize, const SGCOLOR* aColorList );
|
||||
void AddColor( double aRedValue, double aGreenValue, double aBlueValue );
|
||||
void AddColor( const SGCOLOR& aColor );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
};
|
||||
|
||||
#endif // SG_COLORS_H
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
|
||||
|
||||
SGCOORDINDEX::SGCOORDINDEX( SGNODE* aParent ) : SGINDEX( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COORDINDEX;
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOORDINDEX::~SGCOORDINDEX()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDINDEX::GatherCoordIndices( std::vector< int >& aIndexList )
|
||||
{
|
||||
if( index.empty() )
|
||||
return;
|
||||
|
||||
aIndexList.insert( aIndexList.end(), index.begin(), index.end() );
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_coordindex.h
|
||||
* defines an coordinate index set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COORDINDEX_H
|
||||
#define SG_COORDINDEX_H
|
||||
|
||||
#include "3d_cache/sg/sg_index.h"
|
||||
|
||||
/**
|
||||
* Class SGCOORDINDEX
|
||||
* is a class which maintains a coordinate index list. Users
|
||||
* must ensure that coordinate indices are specified as
|
||||
* triplets (triangular faces) since no checking is performed.
|
||||
* In instances where it is not possible to determine which
|
||||
* side of the triangle is to be rendered (for example IGES
|
||||
* entities) then the user must supply each triplet in both
|
||||
* point orders.
|
||||
*/
|
||||
class SGCOORDINDEX : public SGINDEX
|
||||
{
|
||||
public:
|
||||
SGCOORDINDEX( SGNODE* aParent );
|
||||
virtual ~SGCOORDINDEX();
|
||||
|
||||
/**
|
||||
* Function GatherCoordIndices
|
||||
* adds all coordinate indices to the given list
|
||||
* in preparation for a normals calculation
|
||||
*/
|
||||
void GatherCoordIndices( std::vector< int >& aIndexList );
|
||||
};
|
||||
|
||||
#endif // SG_COORDINDEX_H
|
||||
@@ -1,431 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_coords.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
#include "3d_cache/sg/sg_normals.h"
|
||||
#include "3d_cache/sg/sg_faceset.h"
|
||||
|
||||
|
||||
SGCOORDS::SGCOORDS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COORDS;
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGCOORDS (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOORDS::~SGCOORDS()
|
||||
{
|
||||
coords.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGCOORDS
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGCOORDS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
|
||||
{
|
||||
if( coords.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aCoordsList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
aListSize = coords.size();
|
||||
aCoordsList = &coords[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
{
|
||||
coords.clear();
|
||||
|
||||
if( 0 == aListSize || NULL == aCoordsList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < aListSize; ++i )
|
||||
coords.push_back( aCoordsList[i] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
coords.push_back( SGPOINT( aXValue, aYValue, aZValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::AddCoord( const SGPOINT& aPoint )
|
||||
{
|
||||
coords.push_back( aPoint );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( coords.empty() )
|
||||
return false;
|
||||
|
||||
if( aReuseFlag )
|
||||
{
|
||||
if( !m_written )
|
||||
{
|
||||
aFile << " coord DEF " << GetName() << " Coordinate { point [\n ";
|
||||
m_written = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " coord USE " << GetName() << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " coord Coordinate { point [\n ";
|
||||
}
|
||||
|
||||
std::string tmp;
|
||||
size_t n = coords.size();
|
||||
bool nline = false;
|
||||
SGPOINT pt;
|
||||
|
||||
for( size_t i = 0; i < n; )
|
||||
{
|
||||
// ensure VRML output has 1U = 0.1 inch as per legacy kicad expectations
|
||||
pt = coords[i];
|
||||
pt.x /= 2.54;
|
||||
pt.y /= 2.54;
|
||||
pt.z /= 2.54;
|
||||
S3D::FormatPoint( tmp, pt );
|
||||
aFile << tmp ;
|
||||
++i;
|
||||
|
||||
if( i < n )
|
||||
{
|
||||
aFile << ",";
|
||||
|
||||
if( nline )
|
||||
{
|
||||
aFile << "\n ";
|
||||
nline = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nline = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
aFile << "] }\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
size_t npts = coords.size();
|
||||
aFile.write( (char*)&npts, sizeof(size_t) );
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
S3D::WritePoint( aFile, coords[i] );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !coords.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t npts;
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
SGPOINT tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
{
|
||||
if( !S3D::ReadPoint( aFile, tmp ) || aFile.fail() )
|
||||
return false;
|
||||
|
||||
coords.push_back( tmp );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::CalcNormals( SGFACESET* callingNode, SGNODE** aPtr )
|
||||
{
|
||||
if( aPtr )
|
||||
*aPtr = NULL;
|
||||
|
||||
if( NULL == m_Parent || NULL == callingNode )
|
||||
return false;
|
||||
|
||||
// the parent and all references must have indices; collect all
|
||||
// indices into one std::vector<>
|
||||
std::vector< int > ilist;
|
||||
SGNORMALS* np = NULL;
|
||||
|
||||
if( callingNode == m_Parent )
|
||||
{
|
||||
((SGFACESET*)m_Parent)->GatherCoordIndices( ilist );
|
||||
|
||||
std::list< SGNODE* >::iterator sB = m_BackPointers.begin();
|
||||
std::list< SGNODE* >::iterator eB = m_BackPointers.end();
|
||||
|
||||
while( sB != eB )
|
||||
{
|
||||
SGFACESET* fp = (SGFACESET*)(*sB);
|
||||
fp->GatherCoordIndices( ilist );
|
||||
++sB;
|
||||
}
|
||||
|
||||
np = ((SGFACESET*)m_Parent)->m_Normals;
|
||||
|
||||
if( !np )
|
||||
np = new SGNORMALS( m_Parent );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
callingNode->GatherCoordIndices( ilist );
|
||||
np = callingNode->m_Normals;
|
||||
|
||||
if( !np )
|
||||
np = new SGNORMALS( callingNode );
|
||||
|
||||
}
|
||||
|
||||
if( S3D::CalcTriangleNormals( coords, ilist, np->norms ) )
|
||||
{
|
||||
if( aPtr )
|
||||
*aPtr = np;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
delete np;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_coords.h
|
||||
* defines a vertex coordinate set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COORDS_H
|
||||
#define SG_COORDS_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGFACESET;
|
||||
|
||||
class SGCOORDS : public SGNODE
|
||||
{
|
||||
public:
|
||||
std::vector< SGPOINT > coords;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGCOORDS( SGNODE* aParent );
|
||||
virtual ~SGCOORDS();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList );
|
||||
void SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList );
|
||||
void AddCoord( double aXValue, double aYValue, double aZValue );
|
||||
void AddCoord( const SGPOINT& aPoint );
|
||||
|
||||
/**
|
||||
* Function CalcNormals
|
||||
* calculates normals for this coordinate list and sets the
|
||||
* normals list in the parent SGFACESET
|
||||
*/
|
||||
bool CalcNormals( SGFACESET* callingNode, SGNODE** aPtr = NULL );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
};
|
||||
|
||||
#endif // SG_COORDS_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_faceset.h
|
||||
* defines an indexed face set for a scenegraph
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SG_FACESET_H
|
||||
#define SG_FACESET_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
|
||||
class SGCOLORS;
|
||||
class SGCOORDS;
|
||||
class SGNORMALS;
|
||||
class SGCOLORINDEX;
|
||||
class SGCOORDINDEX;
|
||||
|
||||
class SGFACESET : public SGNODE
|
||||
{
|
||||
private:
|
||||
bool valid;
|
||||
bool validated;
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
public:
|
||||
// owned objects
|
||||
SGCOLORS* m_Colors;
|
||||
SGCOORDS* m_Coords;
|
||||
SGCOORDINDEX* m_CoordIndices;
|
||||
SGNORMALS* m_Normals;
|
||||
|
||||
// referenced objects
|
||||
SGCOLORS* m_RColors;
|
||||
SGCOORDS* m_RCoords;
|
||||
SGNORMALS* m_RNormals;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
// validate the data held by this face set
|
||||
bool validate( void );
|
||||
|
||||
public:
|
||||
SGFACESET( SGNODE* aParent );
|
||||
virtual ~SGFACESET();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode( const char *aNodeName, const SGNODE *aCaller ) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool CalcNormals( SGNODE** aPtr );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
/**
|
||||
* Function GatherCoordIndices
|
||||
* adds all internal coordinate indices to the given list
|
||||
* in preparation for a normals calculation
|
||||
*/
|
||||
void GatherCoordIndices( std::vector< int >& aIndexList );
|
||||
};
|
||||
|
||||
/*
|
||||
p.88
|
||||
IndexedFaceSet {
|
||||
color NULL
|
||||
coord NULL
|
||||
normal NULL
|
||||
texCoord NULL
|
||||
ccw TRUE
|
||||
colorIndex []
|
||||
colorPerVertex TRUE
|
||||
convex TRUE
|
||||
coordIndex []
|
||||
creaseAngle 0
|
||||
normalIndex []
|
||||
normalPerVertex TRUE
|
||||
solid TRUE
|
||||
texCoordIndex []
|
||||
}
|
||||
*/
|
||||
|
||||
#endif // SG_FACESET_H
|
||||
@@ -1,539 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
|
||||
// formats a floating point number for text output to a VRML file
|
||||
void S3D::FormatFloat( std::string& result, double value )
|
||||
{
|
||||
if( value < 1e-8 && value > -1e-8 )
|
||||
{
|
||||
result = "0";
|
||||
return;
|
||||
}
|
||||
|
||||
// note: many VRML implementations use float so we use the max.
|
||||
// precision here of 8 digits.
|
||||
std::ostringstream out;
|
||||
out << std::setprecision( 8 ) << value;
|
||||
|
||||
result = out.str();
|
||||
|
||||
size_t p = result.find( "." );
|
||||
|
||||
// trim trailing 0 if appropriate
|
||||
|
||||
if( std::string::npos == p )
|
||||
return;
|
||||
|
||||
p = result.find_first_of( "eE" );
|
||||
|
||||
if( std::string::npos == p )
|
||||
{
|
||||
while( '0' == *(result.rbegin()) )
|
||||
result.erase( result.size() - 1 );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( '0' != result.at( p -1 ) )
|
||||
return;
|
||||
|
||||
// trim all 0 to the left of 'p'
|
||||
std::string tmp = result.substr( p );
|
||||
result = result.substr( 0, p );
|
||||
|
||||
while( '0' == *(result.rbegin()) )
|
||||
result.erase( result.size() - 1 );
|
||||
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// format orientation data for VRML output
|
||||
void S3D::FormatOrientation( std::string& result, const SGVECTOR& axis, double rotation )
|
||||
{
|
||||
double aX;
|
||||
double aY;
|
||||
double aZ;
|
||||
|
||||
axis.GetVector( aX, aY, aZ );
|
||||
FormatFloat( result, aX );
|
||||
std::string tmp;
|
||||
FormatFloat( tmp, aY );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
FormatFloat( tmp, aZ );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
FormatFloat( tmp, rotation );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// format point data for VRML output
|
||||
void S3D::FormatPoint( std::string& result, const SGPOINT& point )
|
||||
{
|
||||
FormatFloat( result, point.x );
|
||||
|
||||
std::string tmp;
|
||||
FormatFloat( tmp, point.y );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
FormatFloat( tmp, point.z );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// format vector data for VRML output
|
||||
void S3D::FormatVector( std::string& result, const SGVECTOR& aVector )
|
||||
{
|
||||
double X, Y, Z;
|
||||
aVector.GetVector( X, Y, Z );
|
||||
FormatFloat( result, X );
|
||||
|
||||
std::string tmp;
|
||||
FormatFloat( tmp, Y );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
FormatFloat( tmp, Z );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// format Color data for VRML output
|
||||
void S3D::FormatColor( std::string& result, const SGCOLOR& aColor )
|
||||
{
|
||||
float R, G, B;
|
||||
aColor.GetColor( R, G, B );
|
||||
FormatFloat( result, R );
|
||||
|
||||
std::string tmp;
|
||||
FormatFloat( tmp, G );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
FormatFloat( tmp, B );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WritePoint( std::ostream& aFile, const SGPOINT& aPoint )
|
||||
{
|
||||
aFile.write( (char*)&aPoint.x, sizeof(aPoint.x) );
|
||||
aFile.write( (char*)&aPoint.y, sizeof(aPoint.y) );
|
||||
aFile.write( (char*)&aPoint.z, sizeof(aPoint.z) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WriteVector( std::ostream& aFile, const SGVECTOR& aVector )
|
||||
{
|
||||
double x, y, z;
|
||||
aVector.GetVector( x, y, z );
|
||||
aFile.write( (char*)&x, sizeof(double) );
|
||||
aFile.write( (char*)&y, sizeof(double) );
|
||||
aFile.write( (char*)&z, sizeof(double) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WriteColor( std::ostream& aFile, const SGCOLOR& aColor )
|
||||
{
|
||||
float r, g, b;
|
||||
aColor.GetColor( r, g, b );
|
||||
aFile.write( (char*)&r, sizeof(float) );
|
||||
aFile.write( (char*)&g, sizeof(float) );
|
||||
aFile.write( (char*)&b, sizeof(float) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
{
|
||||
char schar;
|
||||
aFile.get( schar );
|
||||
|
||||
if( '[' != schar )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; missing left bracket at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
aFile.get( schar );
|
||||
|
||||
while( ']' != schar && aFile.good() )
|
||||
{
|
||||
name.push_back( schar );
|
||||
aFile.get( schar );
|
||||
}
|
||||
|
||||
if( schar != ']' )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; could not find right bracket";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
|
||||
aName = name;
|
||||
size_t upos = name.find( '_' );
|
||||
|
||||
if( std::string::npos == upos )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; no underscore in name '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
|
||||
name = name.substr( 0, upos );
|
||||
S3D::SGTYPES types[S3D::SGTYPE_END] = {
|
||||
SGTYPE_TRANSFORM,
|
||||
SGTYPE_APPEARANCE,
|
||||
SGTYPE_COLORS,
|
||||
SGTYPE_COLORINDEX,
|
||||
SGTYPE_FACESET,
|
||||
SGTYPE_COORDS,
|
||||
SGTYPE_COORDINDEX,
|
||||
SGTYPE_NORMALS,
|
||||
SGTYPE_SHAPE
|
||||
};
|
||||
|
||||
for( int i = 0; i < S3D::SGTYPE_END; ++i )
|
||||
{
|
||||
if( !name.compare( S3D::GetNodeTypeName( types[i] ) ) )
|
||||
return types[i];
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; no node type matching '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::ReadPoint( std::istream& aFile, SGPOINT& aPoint )
|
||||
{
|
||||
aFile.read( (char*)&aPoint.x, sizeof( aPoint.x ) );
|
||||
aFile.read( (char*)&aPoint.y, sizeof( aPoint.y ) );
|
||||
aFile.read( (char*)&aPoint.z, sizeof( aPoint.z ) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::ReadVector( std::istream& aFile, SGVECTOR& aVector )
|
||||
{
|
||||
double x, y, z;
|
||||
aFile.read( (char*)&x, sizeof(double) );
|
||||
aFile.read( (char*)&y, sizeof(double) );
|
||||
aFile.read( (char*)&z, sizeof(double) );
|
||||
aVector.SetVector( x, y, z );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::ReadColor( std::istream& aFile, SGCOLOR& aColor )
|
||||
{
|
||||
float r, g, b;
|
||||
aFile.read( (char*)&r, sizeof(float) );
|
||||
aFile.read( (char*)&g, sizeof(float) );
|
||||
aFile.read( (char*)&b, sizeof(float) );
|
||||
aColor.SetColor( r, g, b );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::degenerate( glm::dvec3* pts )
|
||||
{
|
||||
double dx, dy, dz;
|
||||
|
||||
dx = pts[1].x - pts[0].x;
|
||||
dy = pts[1].y - pts[0].y;
|
||||
dz = pts[1].z - pts[0].z;
|
||||
|
||||
if( ( dx*dx + dy*dy + dz*dz ) < 1e-15 )
|
||||
return true;
|
||||
|
||||
dx = pts[2].x - pts[0].x;
|
||||
dy = pts[2].y - pts[0].y;
|
||||
dz = pts[2].z - pts[0].z;
|
||||
|
||||
if( ( dx*dx + dy*dy + dz*dz ) < 1e-15 )
|
||||
return true;
|
||||
|
||||
dx = pts[2].x - pts[1].x;
|
||||
dy = pts[2].y - pts[1].y;
|
||||
dz = pts[2].z - pts[1].z;
|
||||
|
||||
if( ( dx*dx + dy*dy + dz*dz ) < 1e-15 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void calcTriad( glm::dvec3* pts, glm::dvec3& tri )
|
||||
{
|
||||
if( S3D::degenerate( pts ) )
|
||||
{
|
||||
// degenerate points should contribute nothing to the result
|
||||
tri = glm::dvec3( 0.0, 0.0, 0.0 );
|
||||
return;
|
||||
}
|
||||
|
||||
// normal * 2 * area
|
||||
tri = glm::cross( pts[1] - pts[0], pts[2] - pts[0] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords,
|
||||
std::vector< int >& index, std::vector< SGVECTOR >& norms )
|
||||
{
|
||||
size_t vsize = coords.size();
|
||||
|
||||
if( vsize < 3 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid vertex set (fewer than 3 vertices)";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t isize = index.size();
|
||||
|
||||
if( 0 != isize % 3 || index.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid index set (not multiple of 3)";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !norms.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] normals set is not empty";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map< int, std::list< glm::dvec3 > >vmap;
|
||||
|
||||
int p1, p2, p3;
|
||||
|
||||
// create the map of indices to facet sets
|
||||
for( size_t i = 0; i < isize; )
|
||||
{
|
||||
p1 = index[i++];
|
||||
p2 = index[i++];
|
||||
p3 = index[i++];
|
||||
|
||||
if( p1 < 0 || p1 >= (int)vsize || p2 < 0 || p2 >= (int)vsize ||
|
||||
p3 < 0 || p3 >= (int)vsize )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid index set; index out of bounds";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
glm::dvec3 tri;
|
||||
glm::dvec3 trip[3];
|
||||
trip[0] = glm::dvec3( coords[p1].x, coords[p1].y, coords[p1].z );
|
||||
trip[1] = glm::dvec3( coords[p2].x, coords[p2].y, coords[p2].z );
|
||||
trip[2] = glm::dvec3( coords[p3].x, coords[p3].y, coords[p3].z );
|
||||
calcTriad( trip, tri );
|
||||
|
||||
std::map< int, std::list< glm::dvec3 > >::iterator ip = vmap.find( p1 );
|
||||
|
||||
if( ip != vmap.end() )
|
||||
{
|
||||
ip->second.push_back( tri );
|
||||
}
|
||||
else
|
||||
{
|
||||
vmap.insert( std::pair < int, std::list < glm::dvec3 > >
|
||||
( p1, std::list < glm::dvec3 >( 1, tri ) ) );
|
||||
}
|
||||
|
||||
ip = vmap.find( p2 );
|
||||
|
||||
if( ip != vmap.end() )
|
||||
{
|
||||
ip->second.push_back( tri );
|
||||
}
|
||||
else
|
||||
{
|
||||
vmap.insert( std::pair < int, std::list < glm::dvec3 > >
|
||||
( p2, std::list < glm::dvec3 >( 1, tri ) ) );
|
||||
}
|
||||
|
||||
ip = vmap.find( p3 );
|
||||
|
||||
if( ip != vmap.end() )
|
||||
{
|
||||
ip->second.push_back( tri );
|
||||
}
|
||||
else
|
||||
{
|
||||
vmap.insert( std::pair < int, std::list < glm::dvec3 > >
|
||||
( p3, std::list < glm::dvec3 >( 1, tri ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
std::map< int, std::list< glm::dvec3 > >::iterator sM = vmap.begin();
|
||||
std::map< int, std::list< glm::dvec3 > >::iterator eM = vmap.end();
|
||||
size_t idx = 0;
|
||||
|
||||
while( sM != eM )
|
||||
{
|
||||
size_t item = sM->first;
|
||||
|
||||
// assign any skipped coordinates a normal of (0,0,1)
|
||||
while( item > idx )
|
||||
{
|
||||
norms.push_back( SGVECTOR( 0, 0, 1 ) );
|
||||
++idx;
|
||||
}
|
||||
|
||||
std::list< glm::dvec3 >::iterator sT = sM->second.begin();
|
||||
std::list< glm::dvec3 >::iterator eT = sM->second.end();
|
||||
glm::dvec3 norm( 0.0, 0.0, 0.0 );
|
||||
|
||||
while( sT != eT )
|
||||
{
|
||||
norm += *sT;
|
||||
++sT;
|
||||
}
|
||||
|
||||
norms.push_back( SGVECTOR( norm.x, norm.y, norm.z ) );
|
||||
|
||||
++idx;
|
||||
++sM;
|
||||
}
|
||||
|
||||
if( norms.size() != coords.size() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] number of normals does not equal number of vertices";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_helpers.h
|
||||
* defines a number of macro functions to aid in repetitious code which
|
||||
* is probably best expressed as a preprocessor macro rather than as
|
||||
* a template. This header also declares a number of functions which are
|
||||
* only of use within the sg_* classes.
|
||||
*/
|
||||
|
||||
#ifndef SG_HELPERS_H
|
||||
#define SG_HELPERS_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "plugins/3dapi/sg_base.h"
|
||||
#include "plugins/3dapi/sg_types.h"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class SGNORMALS;
|
||||
class SGCOORDS;
|
||||
class SGCOORDINDEX;
|
||||
|
||||
// Function to drop references within an SGNODE
|
||||
// The node being destroyed must remove itself from the object reference's
|
||||
// backpointer list in order to avoid a segfault.
|
||||
#define DROP_REFS( aType, aList ) do { \
|
||||
std::vector< aType* >::iterator sL = aList.begin(); \
|
||||
std::vector< aType* >::iterator eL = aList.end(); \
|
||||
while( sL != eL ) { \
|
||||
((SGNODE*)*sL)->delNodeRef( this ); \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
} while( 0 )
|
||||
|
||||
|
||||
// Function to delete owned objects within an SGNODE
|
||||
// The owned object's parent is set to NULL before
|
||||
// deletion to avoid a redundant 'unlinkChildNode' call.
|
||||
#define DEL_OBJS( aType, aList ) do { \
|
||||
std::vector< aType* >::iterator sL = aList.begin(); \
|
||||
std::vector< aType* >::iterator eL = aList.end(); \
|
||||
while( sL != eL ) { \
|
||||
((SGNODE*)*sL)->SetParent( NULL, false ); \
|
||||
delete *sL; \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
} while( 0 )
|
||||
|
||||
|
||||
// Function to unlink a child or reference node when that child or
|
||||
// reference node is being destroyed.
|
||||
#define UNLINK_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) do { \
|
||||
if( aNodeID == aNode->GetNodeType() ) { \
|
||||
std::vector< aType* >* oSL; \
|
||||
std::vector< aType* >::iterator sL; \
|
||||
std::vector< aType* >::iterator eL; \
|
||||
if( isChild ) { \
|
||||
oSL = &aOwnedList; \
|
||||
sL = oSL->begin(); \
|
||||
eL = oSL->end(); \
|
||||
while( sL != eL ) { \
|
||||
if( (SGNODE*)*sL == aNode ) { \
|
||||
oSL->erase( sL ); \
|
||||
return; \
|
||||
} \
|
||||
++sL; \
|
||||
} \
|
||||
} else { \
|
||||
oSL = &aRefList; \
|
||||
sL = oSL->begin(); \
|
||||
eL = oSL->end(); \
|
||||
while( sL != eL ) { \
|
||||
if( (SGNODE*)*sL == aNode ) { \
|
||||
delNodeRef( this ); \
|
||||
oSL->erase( sL ); \
|
||||
return; \
|
||||
} \
|
||||
++sL; \
|
||||
} \
|
||||
} \
|
||||
return; \
|
||||
} } while( 0 )
|
||||
|
||||
|
||||
// Function to check a node type, check for an existing reference,
|
||||
// and add the node type to the reference list if applicable
|
||||
#define ADD_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) do { \
|
||||
if( aNodeID == aNode->GetNodeType() ) { \
|
||||
std::vector< aType* >::iterator sL; \
|
||||
sL = std::find( aOwnedList.begin(), aOwnedList.end(), aNode ); \
|
||||
if( sL != aOwnedList.end() ) return true; \
|
||||
sL = std::find( aRefList.begin(), aRefList.end(), aNode ); \
|
||||
if( sL != aRefList.end() ) return true; \
|
||||
if( isChild ) { \
|
||||
SGNODE* ppn = (SGNODE*)aNode->GetParent(); \
|
||||
if( NULL != ppn ) { \
|
||||
if( this != ppn ) { \
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
|
||||
std::cerr << " * [BUG] object '" << aNode->GetName(); \
|
||||
std::cerr << "' has multiple parents '" << ppn->GetName() << "', '"; \
|
||||
std::cerr << m_Name << "'\n"; \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
aOwnedList.push_back( (aType*)aNode ); \
|
||||
aNode->SetParent( this, false ); \
|
||||
} else { \
|
||||
/*if( NULL == aNode->GetParent() ) { \
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
|
||||
std::cerr << " * [BUG] object '" << aNode->GetName(); \
|
||||
std::cerr << "' has no parent\n"; \
|
||||
std::cerr << " * [INFO] possible copy assignment or copy constructor bug\n"; \
|
||||
return false; \
|
||||
} */ \
|
||||
aRefList.push_back( (aType*)aNode ); \
|
||||
aNode->addNodeRef( this ); \
|
||||
} \
|
||||
return true; \
|
||||
} } while( 0 )
|
||||
|
||||
|
||||
// Function to find a node object given a (non-unique) node name
|
||||
#define FIND_NODE( aType, aName, aNodeList, aCallingNode ) do { \
|
||||
std::vector< aType* >::iterator sLA = aNodeList.begin(); \
|
||||
std::vector< aType* >::iterator eLA = aNodeList.end(); \
|
||||
SGNODE* psg = NULL; \
|
||||
while( sLA != eLA ) { \
|
||||
if( (SGNODE*)*sLA != aCallingNode ) { \
|
||||
psg = (SGNODE*) (*sLA)->FindNode( aName, this ); \
|
||||
if( NULL != psg) \
|
||||
return psg; \
|
||||
} \
|
||||
++sLA; \
|
||||
} } while ( 0 )
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
bool degenerate( glm::dvec3* pts );
|
||||
|
||||
//
|
||||
// Normals calculations from triangles
|
||||
//
|
||||
|
||||
/*
|
||||
* Function CalcTriangleNormals
|
||||
* takes an array of 3D coordinates and its corresponding index set and calculates
|
||||
* the normals assuming that indices are given in CCW order. Care must be taken in
|
||||
* using this function to ensure that:
|
||||
* (a) all coordinates are indexed; unindexed coordinates are assigned normal(0,0,1);
|
||||
* when dealing with VRML models which may list and reuse one large coordinate set it
|
||||
* is necessary to gather all index sets and perform this operation only once.
|
||||
* (b) index sets must represent triangles (multiple of 3 indices) and must not be
|
||||
* degenerate - that is all indices and coordinates in a triad must be unique.
|
||||
*
|
||||
* @param coords is the array of 3D vertices
|
||||
* @param index is the array of 3x vertex indices (triads)
|
||||
* @param norms is an empty array which holds the normals corresponding to each vector
|
||||
* @return true on success; otherwise false.
|
||||
*/
|
||||
bool CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >& index,
|
||||
std::vector< SGVECTOR >& norms );
|
||||
|
||||
//
|
||||
// VRML related functions
|
||||
//
|
||||
|
||||
// formats a floating point number for text output to a VRML file
|
||||
void FormatFloat( std::string& result, double value );
|
||||
|
||||
// format orientation data for VRML output
|
||||
void FormatOrientation( std::string& result, const SGVECTOR& axis, double rotation );
|
||||
|
||||
// format point data for VRML output
|
||||
void FormatPoint( std::string& result, const SGPOINT& point );
|
||||
|
||||
// format vector data for VRML output
|
||||
void FormatVector( std::string& result, const SGVECTOR& aVector );
|
||||
|
||||
// format Color data for VRML output
|
||||
void FormatColor( std::string& result, const SGCOLOR& aColor );
|
||||
|
||||
//
|
||||
// Cache related WRITE functions
|
||||
//
|
||||
|
||||
// write out an XYZ vertex
|
||||
bool WritePoint( std::ostream& aFile, const SGPOINT& aPoint );
|
||||
|
||||
// write out a unit vector
|
||||
bool WriteVector( std::ostream& aFile, const SGVECTOR& aVector );
|
||||
|
||||
// write out an RGB color
|
||||
bool WriteColor( std::ostream& aFile, const SGCOLOR& aColor );
|
||||
|
||||
//
|
||||
// Cache related READ functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Function ReadTag
|
||||
* reads the text tag of a binary cache file which is the
|
||||
* NodeTag and unique ID number combined
|
||||
*
|
||||
* @param aFile is a binary file open for reading
|
||||
* @param aName will hold the tag name on successful return
|
||||
* @return will be the NodeType which the tag represents or
|
||||
* S3D::SGTYPES::SGTYPE_END on failure
|
||||
*/
|
||||
S3D::SGTYPES ReadTag( std::istream& aFile, std::string& aName );
|
||||
|
||||
// read an XYZ vertex
|
||||
bool ReadPoint( std::istream& aFile, SGPOINT& aPoint );
|
||||
|
||||
// read a unit vector
|
||||
bool ReadVector( std::istream& aFile, SGVECTOR& aVector );
|
||||
|
||||
// read an RGB color
|
||||
bool ReadColor( std::istream& aFile, SGCOLOR& aColor );
|
||||
}
|
||||
|
||||
#endif // SG_HELPERS_H
|
||||
@@ -1,398 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_index.h"
|
||||
|
||||
|
||||
SGINDEX::SGINDEX( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGINDEX (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGINDEX::~SGINDEX()
|
||||
{
|
||||
index.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGINDEX and derived types
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGINDEX::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::GetIndices( size_t& nIndices, int*& aIndexList )
|
||||
{
|
||||
if( index.empty() )
|
||||
{
|
||||
nIndices = 0;
|
||||
aIndexList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
nIndices = index.size();
|
||||
aIndexList = & index[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
{
|
||||
index.clear();
|
||||
|
||||
if( 0 == nIndices || NULL == aIndexList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < nIndices; ++i )
|
||||
index.push_back( aIndexList[i] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::AddIndex( int aIndex )
|
||||
{
|
||||
index.push_back( aIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( index.empty() )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_COORDINDEX == m_SGtype )
|
||||
return writeCoordIndex( aFile );
|
||||
|
||||
return writeColorIndex( aFile );
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::writeCoordIndex( std::ostream& aFile )
|
||||
{
|
||||
size_t n = index.size();
|
||||
|
||||
if( n % 3 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] coord index is not divisible by three (violates triangle constraint)";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << " coordIndex [\n ";
|
||||
|
||||
// indices to control formatting
|
||||
int nv0 = 0;
|
||||
int nv1 = 0;
|
||||
|
||||
for( size_t i = 0; i < n; )
|
||||
{
|
||||
aFile << index[i];
|
||||
++i;
|
||||
|
||||
if( ++nv0 == 3 )
|
||||
{
|
||||
aFile << ",-1";
|
||||
++nv1;
|
||||
nv0 = 0;
|
||||
}
|
||||
|
||||
if( i < n )
|
||||
{
|
||||
aFile << ",";
|
||||
|
||||
if( nv1 == 8 )
|
||||
{
|
||||
nv1 = 0;
|
||||
aFile << "\n ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aFile << "]\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::writeColorIndex( std::ostream& aFile )
|
||||
{
|
||||
aFile << " colorIndex [\n ";
|
||||
return writeIndexList( aFile );
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::writeIndexList( std::ostream& aFile )
|
||||
{
|
||||
// index to control formatting
|
||||
int nv = 0;
|
||||
size_t n = index.size();
|
||||
|
||||
for( size_t i = 0; i < n; )
|
||||
{
|
||||
aFile << index[i];
|
||||
++i;
|
||||
|
||||
if( i < n )
|
||||
{
|
||||
aFile << ",";
|
||||
|
||||
if( ++nv == 20 )
|
||||
{
|
||||
aFile << "\n ";
|
||||
nv = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aFile << "]\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
size_t npts = index.size();
|
||||
aFile.write( (char*)&npts, sizeof(size_t) );
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
aFile.write( (char*)&index[i], sizeof(int) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !index.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t npts;
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
int tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
{
|
||||
aFile.read( (char*)&tmp, sizeof(int) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
index.push_back( tmp );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_index.h
|
||||
* defines a generic Index interface for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_INDEX_H
|
||||
#define SG_INDEX_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGINDEX : public SGNODE
|
||||
{
|
||||
protected:
|
||||
bool writeCoordIndex( std::ostream& aFile );
|
||||
bool writeColorIndex( std::ostream& aFile );
|
||||
bool writeIndexList( std::ostream& aFile );
|
||||
|
||||
public:
|
||||
// for internal SG consumption only
|
||||
std::vector< int > index;
|
||||
void unlinkChildNode( const SGNODE* aCaller ) override;
|
||||
void unlinkRefNode( const SGNODE* aCaller ) override;
|
||||
|
||||
public:
|
||||
SGINDEX( SGNODE* aParent );
|
||||
virtual ~SGINDEX();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
/**
|
||||
* Function GetIndices
|
||||
* retrieves the number of indices and a pointer to
|
||||
* the list. Note: the returned pointer may be invalidated
|
||||
* by future operations on the SGNODE; the caller must make
|
||||
* immediate use of the data and must not rely on the pointer's
|
||||
* validity in the future.
|
||||
*
|
||||
* @param nIndices [out] will hold the number of indices in the list
|
||||
* @param aIndexList [out] will store a pointer to the data
|
||||
* @return true if there was available data (nIndices > 0) otherwise false
|
||||
*/
|
||||
bool GetIndices( size_t& nIndices, int*& aIndexList );
|
||||
|
||||
/**
|
||||
* Function SetIndices
|
||||
* sets the number of indices and creates a copy of the given index data.
|
||||
*
|
||||
* @param nIndices [in] the number of indices to be stored
|
||||
* @param aIndexList [in] the index data
|
||||
*/
|
||||
void SetIndices( size_t nIndices, int* aIndexList );
|
||||
|
||||
|
||||
/**
|
||||
* Function AddIndex
|
||||
* adds a single index to the list
|
||||
*
|
||||
* @param aIndex is the index to add
|
||||
*/
|
||||
void AddIndex( int aIndex );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
};
|
||||
|
||||
#endif // SG_INDEX_H
|
||||
@@ -1,442 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
|
||||
static const std::string node_names[S3D::SGTYPE_END + 1] = {
|
||||
"TXFM",
|
||||
"APP",
|
||||
"COL",
|
||||
"COLIDX",
|
||||
"FACE",
|
||||
"COORD",
|
||||
"COORDIDX",
|
||||
"NORM",
|
||||
"SHAPE",
|
||||
"INVALID"
|
||||
};
|
||||
|
||||
|
||||
static unsigned int node_counts[S3D::SGTYPE_END] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
|
||||
char const* S3D::GetNodeTypeName( S3D::SGTYPES aType )
|
||||
{
|
||||
return node_names[aType].c_str();
|
||||
}
|
||||
|
||||
|
||||
static void getNodeName( S3D::SGTYPES nodeType, std::string& aName )
|
||||
{
|
||||
if( nodeType < 0 || nodeType >= S3D::SGTYPE_END )
|
||||
{
|
||||
aName = node_names[S3D::SGTYPE_END];
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int seqNum = node_counts[nodeType];
|
||||
++node_counts[nodeType];
|
||||
|
||||
std::ostringstream ostr;
|
||||
ostr << node_names[nodeType] << "_" << seqNum;
|
||||
aName = ostr.str();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE::SGNODE( SGNODE* aParent )
|
||||
{
|
||||
m_Parent = aParent;
|
||||
m_Association = NULL;
|
||||
m_written = false;
|
||||
m_SGtype = S3D::SGTYPE_END;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE::~SGNODE()
|
||||
{
|
||||
if( m_Parent )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
if( m_Association )
|
||||
*m_Association = NULL;
|
||||
|
||||
std::list< SGNODE* >::iterator sBP = m_BackPointers.begin();
|
||||
std::list< SGNODE* >::iterator eBP = m_BackPointers.end();
|
||||
|
||||
while( sBP != eBP )
|
||||
{
|
||||
(*sBP)->unlinkRefNode( this );
|
||||
++sBP;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D::SGTYPES SGNODE::GetNodeType( void ) const
|
||||
{
|
||||
return m_SGtype;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGNODE::GetParent( void ) const
|
||||
{
|
||||
return m_Parent;
|
||||
}
|
||||
|
||||
|
||||
bool SGNODE::SwapParent( SGNODE* aNewParent )
|
||||
{
|
||||
if( aNewParent == m_Parent )
|
||||
return true;
|
||||
|
||||
if( NULL == aNewParent )
|
||||
return false;
|
||||
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
if( aNewParent->AddChildNode( this ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aNewParent->GetNodeType() != m_Parent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
SGNODE* oldParent = m_Parent;
|
||||
m_Parent->unlinkChildNode( this );
|
||||
m_Parent = NULL;
|
||||
aNewParent->unlinkRefNode( this );
|
||||
aNewParent->AddChildNode( this );
|
||||
oldParent->AddRefNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const char* SGNODE::GetName( void )
|
||||
{
|
||||
if( m_Name.empty() )
|
||||
getNodeName( m_SGtype, m_Name );
|
||||
|
||||
return m_Name.c_str();
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::SetName( const char *aName )
|
||||
{
|
||||
if( NULL == aName || 0 == aName[0] )
|
||||
getNodeName( m_SGtype, m_Name );
|
||||
else
|
||||
m_Name = aName;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const char * SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||
{
|
||||
return node_names[aNodeType].c_str();
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::addNodeRef( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
std::list< SGNODE* >::iterator np =
|
||||
std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
|
||||
|
||||
if( np != m_BackPointers.end() )
|
||||
return;
|
||||
|
||||
m_BackPointers.push_back( aNode );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::delNodeRef( const SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
std::list< SGNODE* >::iterator np =
|
||||
std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
|
||||
|
||||
if( np != m_BackPointers.end() )
|
||||
{
|
||||
m_BackPointers.erase( np );
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] delNodeRef() did not find its target\n";
|
||||
ostr << " * This Node Type: " << m_SGtype << ", Referenced node type: ";
|
||||
ostr << aNode->GetNodeType() << "\n";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::AssociateWrapper( SGNODE** aWrapperRef )
|
||||
{
|
||||
if( NULL == aWrapperRef )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL handle";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( *aWrapperRef != this )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] handle value does not match this object's pointer";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is an existing association then break it and emit a warning
|
||||
// just in case the behavior is undesired
|
||||
if( m_Association )
|
||||
{
|
||||
*m_Association = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [WARNING] association being broken with previous wrapper";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
|
||||
m_Association = aWrapperRef;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SGNODE::DisassociateWrapper( SGNODE** aWrapperRef )
|
||||
{
|
||||
if( !m_Association )
|
||||
return;
|
||||
|
||||
if( !aWrapperRef )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid handle value aWrapperRef";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( *aWrapperRef != *m_Association || aWrapperRef != m_Association )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] *aWrapperRef (" << *aWrapperRef;
|
||||
ostr << ") does not match *m_Association (" << *m_Association << ") in type ";
|
||||
ostr << node_names[ m_SGtype] << "\n";
|
||||
ostr << " * [INFO] OR aWrapperRef(" << aWrapperRef << ") != m_Association(";
|
||||
ostr << m_Association << ")\n";
|
||||
ostr << " * [INFO] node name: " << GetName();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_Association = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::ResetNodeIndex( void )
|
||||
{
|
||||
for( int i = 0; i < (int)S3D::SGTYPE_END; ++i )
|
||||
node_counts[i] = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex )
|
||||
{
|
||||
aIndex = 0;
|
||||
|
||||
if( NULL == aNode || S3D::SGTYPE_APPEARANCE != aNode->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
ostr.str( "" );
|
||||
|
||||
if( NULL == aNode )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, " * [BUG] aNode is NULL\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
ostr << " * [BUG] invalid node type (" << aNode->GetNodeType();
|
||||
ostr << "), expected " << S3D::SGTYPE_APPEARANCE;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGAPPEARANCE* node = (SGAPPEARANCE*)aNode;
|
||||
|
||||
std::map< SGAPPEARANCE const*, int >::iterator it = aList.matmap.find( node );
|
||||
|
||||
if( it != aList.matmap.end() )
|
||||
{
|
||||
aIndex = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
int idx = (int)aList.matorder.size();
|
||||
aList.matorder.push_back( node );
|
||||
aList.matmap.insert( std::pair< SGAPPEARANCE const*, int >( node, idx ) );
|
||||
aIndex = idx;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void S3D::INIT_SMATERIAL( SMATERIAL& aMaterial )
|
||||
{
|
||||
memset( &aMaterial, 0, sizeof( aMaterial ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::INIT_SMESH( SMESH& aMesh )
|
||||
{
|
||||
memset( &aMesh, 0, sizeof( aMesh ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::INIT_S3DMODEL( S3DMODEL& aModel )
|
||||
{
|
||||
memset( &aModel, 0, sizeof( aModel ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::FREE_SMESH( SMESH& aMesh)
|
||||
{
|
||||
if( NULL != aMesh.m_Positions )
|
||||
{
|
||||
delete [] aMesh.m_Positions;
|
||||
aMesh.m_Positions = NULL;
|
||||
}
|
||||
|
||||
if( NULL != aMesh.m_Normals )
|
||||
{
|
||||
delete [] aMesh.m_Normals;
|
||||
aMesh.m_Normals = NULL;
|
||||
}
|
||||
|
||||
if( NULL != aMesh.m_Texcoords )
|
||||
{
|
||||
delete [] aMesh.m_Texcoords;
|
||||
aMesh.m_Texcoords = NULL;
|
||||
}
|
||||
|
||||
if( NULL != aMesh.m_Color )
|
||||
{
|
||||
delete [] aMesh.m_Color;
|
||||
aMesh.m_Color = NULL;
|
||||
}
|
||||
|
||||
if( NULL != aMesh.m_FaceIdx )
|
||||
{
|
||||
delete [] aMesh.m_FaceIdx;
|
||||
aMesh.m_FaceIdx = NULL;
|
||||
}
|
||||
|
||||
aMesh.m_VertexSize = 0;
|
||||
aMesh.m_FaceIdxSize = 0;
|
||||
aMesh.m_MaterialIdx = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::FREE_S3DMODEL( S3DMODEL& aModel )
|
||||
{
|
||||
if( NULL != aModel.m_Materials )
|
||||
{
|
||||
delete [] aModel.m_Materials;
|
||||
aModel.m_Materials = NULL;
|
||||
}
|
||||
|
||||
aModel.m_MaterialsSize = 0;
|
||||
|
||||
if( NULL != aModel.m_Meshes )
|
||||
{
|
||||
for( unsigned int i = 0; i < aModel.m_MeshesSize; ++i )
|
||||
FREE_SMESH( aModel.m_Meshes[i] );
|
||||
|
||||
delete [] aModel.m_Meshes;
|
||||
aModel.m_Meshes = NULL;
|
||||
}
|
||||
|
||||
aModel.m_MeshesSize = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_node.h
|
||||
* defines the base class of the intermediate scene graph NODE
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SG_NODE_H
|
||||
#define SG_NODE_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
#include "plugins/3dapi/sg_base.h"
|
||||
#include "plugins/3dapi/sg_types.h"
|
||||
|
||||
class SGNODE;
|
||||
class SGAPPEARANCE;
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
/**
|
||||
* Function GetNodeTypeName
|
||||
* returns the name of the given type of node
|
||||
*/
|
||||
char const* GetNodeTypeName( S3D::SGTYPES aType );
|
||||
|
||||
struct MATLIST
|
||||
{
|
||||
std::vector< SGAPPEARANCE const* > matorder; // materials in order of addition
|
||||
std::map< SGAPPEARANCE const*, int > matmap; // mapping from material to index
|
||||
};
|
||||
|
||||
bool GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex );
|
||||
|
||||
void INIT_SMATERIAL( SMATERIAL& aMaterial );
|
||||
void INIT_SMESH( SMESH& aMesh );
|
||||
void INIT_S3DMODEL( S3DMODEL& aModel );
|
||||
|
||||
void FREE_SMESH( SMESH& aMesh);
|
||||
void FREE_S3DMODEL( S3DMODEL& aModel );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class SGNODE
|
||||
* represents the base class of all Scene Graph nodes
|
||||
*/
|
||||
class SGNODE
|
||||
{
|
||||
private:
|
||||
SGNODE** m_Association; // handle to the instance held by a wrapper
|
||||
|
||||
protected:
|
||||
std::list< SGNODE* > m_BackPointers; // nodes which hold a reference to this
|
||||
SGNODE* m_Parent; // pointer to parent node; may be NULL for top level transform
|
||||
S3D::SGTYPES m_SGtype; // type of SG node
|
||||
std::string m_Name; // name to use for referencing the entity by name
|
||||
bool m_written; // set true when the object has been written after a ReNameNodes()
|
||||
|
||||
public:
|
||||
/**
|
||||
* Function unlinkChild
|
||||
* removes references to an owned child; it is invoked by the child upon destruction
|
||||
* to ensure that the parent has no invalid references.
|
||||
*
|
||||
* @param aNode is the child which is being deleted
|
||||
*/
|
||||
virtual void unlinkChildNode( const SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Function unlinkRef
|
||||
* removes pointers to a referenced node; it is invoked by the referenced node
|
||||
* upon destruction to ensure that the referring node has no invalid references.
|
||||
*
|
||||
* @param aNode is the node which is being deleted
|
||||
*/
|
||||
virtual void unlinkRefNode( const SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Function addNodeRef
|
||||
* adds a pointer to a node which references, but does not own, this node.
|
||||
* Such back-pointers are required to ensure that invalidated references
|
||||
* are removed when a node is deleted
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object
|
||||
*/
|
||||
void addNodeRef( SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Function delNodeRef
|
||||
* removes a pointer to a node which references, but does not own, this node.
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object
|
||||
*/
|
||||
void delNodeRef( const SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Function IsWritten
|
||||
* returns true if the object had already been written to a
|
||||
* cache file or VRML file; for internal use only.
|
||||
*/
|
||||
bool isWritten( void )
|
||||
{
|
||||
return m_written;
|
||||
}
|
||||
|
||||
public:
|
||||
SGNODE( SGNODE* aParent );
|
||||
virtual ~SGNODE();
|
||||
|
||||
/**
|
||||
* Function GetNodeType
|
||||
* returns the type of this node instance
|
||||
*/
|
||||
S3D::SGTYPES GetNodeType( void ) const;
|
||||
|
||||
/**
|
||||
* Function GetParent
|
||||
* returns a pointer to the parent SGNODE of this object
|
||||
* or NULL if the object has no parent (ie. top level transform)
|
||||
*/
|
||||
SGNODE* GetParent( void ) const;
|
||||
|
||||
/**
|
||||
* Function SetParent
|
||||
* sets the parent SGNODE of this object.
|
||||
*
|
||||
* @param aParent [in] is the desired parent node
|
||||
* @return true if the operation succeeds; false if
|
||||
* the given node is not allowed to be a parent to
|
||||
* the derived object.
|
||||
*/
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) = 0;
|
||||
|
||||
/**
|
||||
* Function SwapParent
|
||||
* swaps the ownership with the given parent. This operation
|
||||
* may be required when reordering nodes for optimization.
|
||||
*
|
||||
* @param aNewParent [in] will become the new parent to the
|
||||
* object; it must be the same type as the parent of this
|
||||
* instance.
|
||||
*/
|
||||
bool SwapParent( SGNODE* aNewParent );
|
||||
|
||||
const char* GetName( void );
|
||||
void SetName(const char *aName);
|
||||
|
||||
const char * GetNodeTypeName( S3D::SGTYPES aNodeType ) const;
|
||||
|
||||
/**
|
||||
* Function FindNode searches the tree of linked nodes and returns a
|
||||
* reference to the first node found with the given name. The reference
|
||||
* is then typically added to another node via AddRefNode().
|
||||
*
|
||||
* @param aNodeName is the name of the node to search for
|
||||
* @param aCaller is a pointer to the node invoking this function
|
||||
* @return is a valid node pointer on success, otherwise NULL
|
||||
*/
|
||||
virtual SGNODE* FindNode( const char *aNodeName, const SGNODE *aCaller ) = 0;
|
||||
|
||||
virtual bool AddRefNode( SGNODE* aNode ) = 0;
|
||||
|
||||
virtual bool AddChildNode( SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Function AssociateWrapper
|
||||
* associates this object with a handle to itself; this handle
|
||||
* is typically held by an IFSG* wrapper and the pointer which
|
||||
* it refers to is set to NULL upon destruction of this object.
|
||||
* This mechanism provides a scheme by which a wrapper can be
|
||||
* notified of the destruction of the object which it wraps.
|
||||
*/
|
||||
void AssociateWrapper( SGNODE** aWrapperRef );
|
||||
|
||||
/**
|
||||
* Function DisassociateWrapper
|
||||
* removes the association between an IFSG* wrapper
|
||||
* object and this object.
|
||||
*/
|
||||
void DisassociateWrapper( SGNODE** aWrapperRef );
|
||||
|
||||
/**
|
||||
* Function ResetNodeIndex
|
||||
* resets the global SG* node indices in preparation for
|
||||
* Write() operations
|
||||
*/
|
||||
void ResetNodeIndex( void );
|
||||
|
||||
/**
|
||||
* Function ReNameNodes
|
||||
* renames a node and all its child nodes in preparation for
|
||||
* Write() operations
|
||||
*/
|
||||
virtual void ReNameNodes( void ) = 0;
|
||||
|
||||
/**
|
||||
* Function WriteVRML
|
||||
* writes this node's data to a VRML file; this includes
|
||||
* all data of child and referenced nodes.
|
||||
*/
|
||||
virtual bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) = 0;
|
||||
|
||||
/**
|
||||
* Function WriteCache
|
||||
* write's this node's data to a binary cache file; the data
|
||||
* includes all data of children and references to children.
|
||||
* If this function is invoked by the user, parentNode must be
|
||||
* set to NULL in order to ensure coherent data.
|
||||
*/
|
||||
virtual bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) = 0;
|
||||
|
||||
/**
|
||||
* Function ReadCache
|
||||
* Reads binary format data from a cache file. To read a cache file,
|
||||
* open the file for reading and invoke this function from a new
|
||||
* SCENEGRAPH node.
|
||||
*/
|
||||
virtual bool ReadCache( std::istream& aFile, SGNODE* parentNode ) = 0;
|
||||
};
|
||||
|
||||
#endif // SG_NODE_H
|
||||
@@ -1,366 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_normals.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
SGNORMALS::SGNORMALS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_NORMALS;
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGNORMALS (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNORMALS::~SGNORMALS()
|
||||
{
|
||||
norms.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGNORMALS
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGNORMALS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
|
||||
{
|
||||
if( norms.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aNormalList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
aListSize = norms.size();
|
||||
aNormalList = &norms[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
|
||||
{
|
||||
norms.clear();
|
||||
|
||||
if( 0 == aListSize || NULL == aNormalList )
|
||||
return;
|
||||
|
||||
for( int i = 0; i < (int)aListSize; ++i )
|
||||
norms.push_back( aNormalList[i] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::AddNormal( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
norms.push_back( SGVECTOR( aXValue, aYValue, aZValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::AddNormal( const SGVECTOR& aNormal )
|
||||
{
|
||||
norms.push_back( aNormal );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( norms.empty() )
|
||||
return false;
|
||||
|
||||
if( aReuseFlag )
|
||||
{
|
||||
if( !m_written )
|
||||
{
|
||||
aFile << " normal DEF " << GetName() << " Normal { vector [\n ";
|
||||
m_written = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " normal USE " << GetName() << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " normal Normal { vector [\n ";
|
||||
}
|
||||
|
||||
std::string tmp;
|
||||
size_t n = norms.size();
|
||||
bool nline = false;
|
||||
|
||||
for( size_t i = 0; i < n; )
|
||||
{
|
||||
S3D::FormatVector( tmp, norms[i] );
|
||||
aFile << tmp ;
|
||||
++i;
|
||||
|
||||
if( i < n )
|
||||
{
|
||||
aFile << ",";
|
||||
|
||||
if( nline )
|
||||
{
|
||||
aFile << "\n ";
|
||||
nline = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nline = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
aFile << "] }\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
size_t npts = norms.size();
|
||||
aFile.write( (char*)&npts, sizeof(size_t) );
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
S3D::WriteVector( aFile, norms[i] );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !norms.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t npts;
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
SGVECTOR tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
{
|
||||
if( !S3D::ReadVector( aFile, tmp ) || aFile.fail() )
|
||||
return false;
|
||||
|
||||
norms.push_back( tmp );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_normals.h
|
||||
* defines a set of vertex normals for a scene graph object
|
||||
*/
|
||||
|
||||
#ifndef SG_NORMALS_H
|
||||
#define SG_NORMALS_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGNORMALS : public SGNODE
|
||||
{
|
||||
public:
|
||||
std::vector< SGVECTOR > norms;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGNORMALS( SGNODE* aParent );
|
||||
virtual ~SGNORMALS();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList );
|
||||
void SetNormalList( size_t aListSize, const SGVECTOR* aNormalList );
|
||||
void AddNormal( double aXValue, double aYValue, double aZValue );
|
||||
void AddNormal( const SGVECTOR& aNormal );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
};
|
||||
|
||||
#endif // SG_NORMALS_H
|
||||
@@ -1,900 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_shape.h"
|
||||
#include "3d_cache/sg/sg_faceset.h"
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
#include "3d_cache/sg/sg_coords.h"
|
||||
#include "3d_cache/sg/sg_colors.h"
|
||||
#include "3d_cache/sg/sg_normals.h"
|
||||
|
||||
|
||||
SGSHAPE::SGSHAPE( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_SHAPE;
|
||||
m_Appearance = NULL;
|
||||
m_RAppearance = NULL;
|
||||
m_FaceSet = NULL;
|
||||
m_RFaceSet = NULL;
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGSHAPE (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGSHAPE::~SGSHAPE()
|
||||
{
|
||||
// drop references
|
||||
if( m_RAppearance )
|
||||
{
|
||||
m_RAppearance->delNodeRef( this );
|
||||
m_RAppearance = NULL;
|
||||
}
|
||||
|
||||
if( m_RFaceSet )
|
||||
{
|
||||
m_RFaceSet->delNodeRef( this );
|
||||
m_RFaceSet = NULL;
|
||||
}
|
||||
|
||||
// delete objects
|
||||
if( m_Appearance )
|
||||
{
|
||||
m_Appearance->SetParent( NULL, false );
|
||||
delete m_Appearance;
|
||||
m_Appearance = NULL;
|
||||
}
|
||||
|
||||
if( m_FaceSet )
|
||||
{
|
||||
m_FaceSet->SetParent( NULL, false );
|
||||
delete m_FaceSet;
|
||||
m_FaceSet = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGTRANSFORM may be parent to a SGSHAPE
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGSHAPE::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
SGNODE* tmp = NULL;
|
||||
|
||||
if( NULL != m_Appearance )
|
||||
{
|
||||
tmp = m_Appearance->FindNode( aNodeName, this );
|
||||
|
||||
if( tmp )
|
||||
{
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if( NULL != m_FaceSet )
|
||||
{
|
||||
tmp = m_FaceSet->FindNode( aNodeName, this );
|
||||
|
||||
if( tmp )
|
||||
{
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
|
||||
|
||||
void SGSHAPE::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
if( isChild )
|
||||
{
|
||||
if( aNode == m_Appearance )
|
||||
{
|
||||
m_Appearance = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_FaceSet )
|
||||
{
|
||||
m_FaceSet = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aNode == m_RAppearance )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RAppearance = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_RFaceSet )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RFaceSet = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unlinkNode() did not find its target";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGSHAPE::unlinkChildNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, true );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGSHAPE::unlinkRefNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, false );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_APPEARANCE == aNode->GetNodeType() )
|
||||
{
|
||||
if( m_Appearance || m_RAppearance )
|
||||
{
|
||||
if( aNode != m_Appearance && aNode != m_RAppearance )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Appearance nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( isChild )
|
||||
{
|
||||
m_Appearance = (SGAPPEARANCE*)aNode;
|
||||
m_Appearance->SetParent( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RAppearance = (SGAPPEARANCE*)aNode;
|
||||
m_RAppearance->addNodeRef( this );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_FACESET == aNode->GetNodeType() )
|
||||
{
|
||||
if( m_FaceSet || m_RFaceSet )
|
||||
{
|
||||
if( aNode != m_FaceSet && aNode != m_RFaceSet )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple FaceSet nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( isChild )
|
||||
{
|
||||
m_FaceSet = (SGFACESET*)aNode;
|
||||
m_FaceSet->SetParent( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RFaceSet = (SGFACESET*)aNode;
|
||||
m_RFaceSet->addNodeRef( this );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] object '" << aNode->GetName();
|
||||
ostr << "' is not a valid type for this object (" << aNode->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
return addNode( aNode, false );
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
return addNode( aNode, true );
|
||||
}
|
||||
|
||||
|
||||
void SGSHAPE::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
|
||||
// rename Appearance
|
||||
if( m_Appearance )
|
||||
m_Appearance->ReNameNodes();
|
||||
|
||||
// rename FaceSet
|
||||
if( m_FaceSet )
|
||||
m_FaceSet->ReNameNodes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( !m_Appearance && !m_RAppearance
|
||||
&& !m_FaceSet && !m_RFaceSet )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aReuseFlag )
|
||||
{
|
||||
if( !m_written )
|
||||
{
|
||||
aFile << "DEF " << GetName() << " Shape {\n";
|
||||
m_written = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " USE " << GetName() << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " Shape {\n";
|
||||
}
|
||||
|
||||
if( m_Appearance )
|
||||
m_Appearance->WriteVRML( aFile, aReuseFlag );
|
||||
|
||||
if( m_RAppearance )
|
||||
m_RAppearance->WriteVRML( aFile, aReuseFlag );
|
||||
|
||||
if( m_FaceSet )
|
||||
m_FaceSet->WriteVRML( aFile, aReuseFlag );
|
||||
|
||||
if( m_RFaceSet )
|
||||
m_RFaceSet->WriteVRML( aFile, aReuseFlag );
|
||||
|
||||
aFile << "}\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if any references are unwritten and swap parents if so
|
||||
if( NULL != m_RAppearance && !m_RAppearance->isWritten() )
|
||||
m_RAppearance->SwapParent(this);
|
||||
|
||||
if( NULL != m_RFaceSet && !m_RFaceSet->isWritten() )
|
||||
m_RFaceSet->SwapParent( this );
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
#define NITEMS 4
|
||||
bool items[NITEMS];
|
||||
int i;
|
||||
|
||||
for( i = 0; i < NITEMS; ++i )
|
||||
items[i] = 0;
|
||||
|
||||
i = 0;
|
||||
if( NULL != m_Appearance )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( NULL != m_RAppearance )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( NULL != m_FaceSet )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( NULL != m_RFaceSet )
|
||||
items[i] = true;
|
||||
|
||||
for( int jj = 0; jj < NITEMS; ++jj )
|
||||
aFile.write( (char*)&items[jj], sizeof(bool) );
|
||||
|
||||
if( items[0] )
|
||||
m_Appearance->WriteCache( aFile, this );
|
||||
|
||||
if( items[1] )
|
||||
aFile << "[" << m_RAppearance->GetName() << "]";
|
||||
|
||||
if( items[2] )
|
||||
m_FaceSet->WriteCache( aFile, this );
|
||||
|
||||
if( items[3] )
|
||||
aFile << "[" << m_RFaceSet->GetName() << "]";
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( m_Appearance || m_RAppearance || m_FaceSet || m_RFaceSet )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define NITEMS 4
|
||||
bool items[NITEMS];
|
||||
|
||||
for( int i = 0; i < NITEMS; ++i )
|
||||
aFile.read( (char*)&items[i], sizeof(bool) );
|
||||
|
||||
if( ( items[0] && items[1] ) || ( items[2] && items[3] ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; multiple item definitions at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
|
||||
if( items[0] )
|
||||
{
|
||||
if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child apperance tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Appearance = new SGAPPEARANCE( this );
|
||||
m_Appearance->SetName( name.c_str() );
|
||||
|
||||
if( !m_Appearance->ReadCache( aFile, this ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading appearance '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( items[1] )
|
||||
{
|
||||
if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref appearance tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = FindNode( name.c_str(), this );
|
||||
|
||||
if( !np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref appearance '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_APPEARANCE != np->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGAPPEARANCE '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_RAppearance = (SGAPPEARANCE*)np;
|
||||
m_RAppearance->addNodeRef( this );
|
||||
}
|
||||
|
||||
if( items[2] )
|
||||
{
|
||||
if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child face set tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_FaceSet = new SGFACESET( this );
|
||||
m_FaceSet->SetName( name.c_str() );
|
||||
|
||||
if( !m_FaceSet->ReadCache( aFile, this ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading face set '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( items[3] )
|
||||
{
|
||||
if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref face set tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = FindNode( name.c_str(), this );
|
||||
|
||||
if( !np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref face set '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_FACESET != np->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGFACESET '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_RFaceSet = (SGFACESET*)np;
|
||||
m_RFaceSet->addNodeRef( this );
|
||||
}
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes )
|
||||
{
|
||||
SMESH m;
|
||||
S3D::INIT_SMESH( m );
|
||||
|
||||
SGAPPEARANCE* pa = m_Appearance;
|
||||
SGFACESET* pf = m_FaceSet;
|
||||
|
||||
if( NULL == pa )
|
||||
pa = m_RAppearance;
|
||||
|
||||
if( NULL == pf )
|
||||
pf = m_RFaceSet;
|
||||
|
||||
// no face sets = nothing to render, which is valid though pointless
|
||||
if( NULL == pf )
|
||||
return true;
|
||||
|
||||
if( !pf->validate() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; inconsistent data";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
if( NULL == pa )
|
||||
{
|
||||
m.m_MaterialIdx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int idx;
|
||||
|
||||
if( !S3D::GetMatIndex( materials, pa, idx ) )
|
||||
{
|
||||
m.m_MaterialIdx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m.m_MaterialIdx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
SGCOLORS* pc = pf->m_Colors;
|
||||
SGCOORDS* pv = pf->m_Coords;
|
||||
SGCOORDINDEX* vidx = pf->m_CoordIndices;
|
||||
SGNORMALS* pn = pf->m_Normals;
|
||||
|
||||
if( NULL == pc )
|
||||
pc = pf->m_RColors;
|
||||
|
||||
if( NULL == pv )
|
||||
pv = pf->m_RCoords;
|
||||
|
||||
if( NULL == pn )
|
||||
pn = pf->m_RNormals;
|
||||
|
||||
// set the vertex points and indices
|
||||
size_t nCoords = 0;
|
||||
SGPOINT* pCoords = NULL;
|
||||
pv->GetCoordsList( nCoords, pCoords );
|
||||
|
||||
size_t nColors = 0;
|
||||
SGCOLOR* pColors = NULL;
|
||||
|
||||
if( pc )
|
||||
{
|
||||
// check the vertex colors
|
||||
pc->GetColorList( nColors, pColors );
|
||||
|
||||
if( nColors < nCoords )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; not enough colors per vertex (";
|
||||
ostr << nColors << " vs " << nCoords << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// set the vertex indices
|
||||
size_t nvidx = 0;
|
||||
int* lv = NULL;
|
||||
vidx->GetIndices( nvidx, lv );
|
||||
|
||||
// note: reduce the vertex set to include only the referenced vertices
|
||||
std::vector< int > vertices; // store the list of temp vertex indices
|
||||
std::map< int, unsigned int > indexmap; // map temp vertex to true vertex
|
||||
std::map< int, unsigned int >::iterator mit;
|
||||
|
||||
for( unsigned int i = 0; i < nvidx; ++i )
|
||||
{
|
||||
mit = indexmap.find( lv[i] );
|
||||
|
||||
if( mit == indexmap.end() )
|
||||
{
|
||||
indexmap.insert( std::pair< int, unsigned int >( lv[i], vertices.size() ) );
|
||||
vertices.push_back( lv[i] );
|
||||
}
|
||||
}
|
||||
|
||||
if( vertices.size() < 3 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; not enough vertices";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// construct the final vertex/color list
|
||||
SFVEC3F* lColors = NULL;
|
||||
SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ];
|
||||
int ti;
|
||||
|
||||
if( pc )
|
||||
{
|
||||
lColors = new SFVEC3F[vertices.size()];
|
||||
m.m_Color = lColors;
|
||||
}
|
||||
|
||||
|
||||
if( pc )
|
||||
{
|
||||
for( size_t i = 0; i < vertices.size(); ++i )
|
||||
{
|
||||
ti = vertices[i];
|
||||
glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
|
||||
pt = (*aTransform) * pt;
|
||||
pColors[ti].GetColor( lColors[i].x, lColors[i].y, lColors[i].z );
|
||||
lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( size_t i = 0; i < vertices.size(); ++i )
|
||||
{
|
||||
ti = vertices[i];
|
||||
glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
|
||||
pt = (*aTransform) * pt;
|
||||
lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
|
||||
}
|
||||
}
|
||||
|
||||
m.m_VertexSize = (unsigned int) vertices.size();
|
||||
m.m_Positions = lCoords;
|
||||
unsigned int* lvidx = new unsigned int[ nvidx ];
|
||||
|
||||
for( unsigned int i = 0; i < nvidx; ++i )
|
||||
{
|
||||
mit = indexmap.find( lv[i] );
|
||||
lvidx[i] = mit->second;
|
||||
}
|
||||
|
||||
m.m_FaceIdxSize = (unsigned int )nvidx;
|
||||
m.m_FaceIdx = lvidx;
|
||||
|
||||
// set the per-vertex normals
|
||||
size_t nNorms = 0;
|
||||
SGVECTOR* pNorms = NULL;
|
||||
double x, y, z;
|
||||
|
||||
pn->GetNormalList( nNorms, pNorms );
|
||||
SFVEC3F* lNorms = new SFVEC3F[ vertices.size() ];
|
||||
|
||||
for( size_t i = 0; i < vertices.size(); ++i )
|
||||
{
|
||||
ti = vertices[i];
|
||||
pNorms[ti].GetVector( x, y, z );
|
||||
glm::dvec4 pt( x, y, z, 0.0 );
|
||||
pt = (*aTransform) * pt;
|
||||
|
||||
lNorms[i] = SFVEC3F( pt.x, pt.y, pt.z );
|
||||
}
|
||||
|
||||
m.m_Normals = lNorms;
|
||||
meshes.push_back( m );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_shape.h
|
||||
* defines a complex 3D shape for a scenegraph object
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SG_SHAPE_H
|
||||
#define SG_SHAPE_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGAPPEARANCE;
|
||||
class SGFACESET;
|
||||
|
||||
class SGSHAPE : public SGNODE
|
||||
{
|
||||
private:
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
public:
|
||||
// owned node
|
||||
SGAPPEARANCE* m_Appearance;
|
||||
SGFACESET* m_FaceSet;
|
||||
|
||||
// referenced nodes
|
||||
SGAPPEARANCE* m_RAppearance;
|
||||
SGFACESET* m_RFaceSet;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGSHAPE( SGNODE* aParent );
|
||||
virtual ~SGSHAPE();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
bool Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes );
|
||||
};
|
||||
|
||||
/*
|
||||
p.107
|
||||
Shape {
|
||||
appearance NULL
|
||||
geometry NULL
|
||||
}
|
||||
*/
|
||||
|
||||
#endif // SG_SHAPE_H
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file str_rsort.h
|
||||
* provides a wxString sorting functino which works from the
|
||||
* end of the string towards the beginning
|
||||
*/
|
||||
|
||||
#ifndef STR_RSORT_H
|
||||
#define STR_RSORT_H
|
||||
|
||||
#include <wx/string.h>
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
|
||||
struct rsort_wxString
|
||||
{
|
||||
bool operator() (const wxString& strA, const wxString& strB ) const
|
||||
{
|
||||
// sort a wxString using the reverse character order; for 3d model
|
||||
// filenames this will typically be a much faster operation than
|
||||
// a normal alphabetic sort
|
||||
wxString::const_reverse_iterator sA = strA.rbegin();
|
||||
wxString::const_reverse_iterator eA = strA.rend();
|
||||
|
||||
wxString::const_reverse_iterator sB = strB.rbegin();
|
||||
wxString::const_reverse_iterator eB = strB.rend();
|
||||
|
||||
if( strA.empty() )
|
||||
{
|
||||
if( strB.empty() )
|
||||
return false;
|
||||
|
||||
// note: this rule implies that a null string is first in the sort order
|
||||
return true;
|
||||
}
|
||||
|
||||
if( strB.empty() )
|
||||
return false;
|
||||
|
||||
while( sA != eA && sB != eB )
|
||||
{
|
||||
if( (*sA) == (*sB) )
|
||||
{
|
||||
++sA;
|
||||
++sB;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( (*sA) < (*sB) )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if( sB == eB )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // end NAMESPACE
|
||||
|
||||
#endif // STR_RSORT_H
|
||||
@@ -0,0 +1,735 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_canvas.cpp
|
||||
*/
|
||||
#include <fctsys.h>
|
||||
#include <trigo.h>
|
||||
#include <project.h>
|
||||
#include <gestfich.h>
|
||||
|
||||
#include <wx/image.h>
|
||||
|
||||
#if !wxUSE_GLCANVAS
|
||||
#error Please set wxUSE_GLCANVAS to 1 in setup.h.
|
||||
#endif
|
||||
|
||||
#include <wx/dataobj.h>
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <GL/glew.h> // must be included before gl.h
|
||||
#endif
|
||||
|
||||
#include <3d_viewer.h>
|
||||
#include <3d_canvas.h>
|
||||
#include <info3d_visu.h>
|
||||
#include <trackball.h>
|
||||
#include <3d_viewer_id.h>
|
||||
|
||||
#include <textures/text_silk.h>
|
||||
#include <textures/text_pcb.h>
|
||||
|
||||
|
||||
static const double DELTA_MOVE_STEP = 0.7;
|
||||
|
||||
|
||||
/*
|
||||
* EDA_3D_CANVAS implementation
|
||||
*/
|
||||
|
||||
BEGIN_EVENT_TABLE( EDA_3D_CANVAS, wxGLCanvas )
|
||||
EVT_PAINT( EDA_3D_CANVAS::OnPaint )
|
||||
|
||||
// key event:
|
||||
EVT_CHAR( EDA_3D_CANVAS::OnChar )
|
||||
|
||||
// mouse events
|
||||
EVT_RIGHT_DOWN( EDA_3D_CANVAS::OnRightClick )
|
||||
EVT_MOUSEWHEEL( EDA_3D_CANVAS::OnMouseWheel )
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
EVT_MAGNIFY( EDA_3D_CANVAS::OnMagnify )
|
||||
#endif
|
||||
EVT_MOTION( EDA_3D_CANVAS::OnMouseMove )
|
||||
|
||||
// other events
|
||||
EVT_ERASE_BACKGROUND( EDA_3D_CANVAS::OnEraseBackground )
|
||||
EVT_MENU_RANGE( ID_POPUP_3D_VIEW_START, ID_POPUP_3D_VIEW_END, EDA_3D_CANVAS::OnPopUpMenu )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// Define an invalid value for some unsigned int indexes
|
||||
#define INVALID_INDEX GL_INVALID_VALUE
|
||||
|
||||
EDA_3D_CANVAS::EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList ) :
|
||||
wxGLCanvas( parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE )
|
||||
{
|
||||
m_init = false;
|
||||
m_reportWarnings = true;
|
||||
m_shadow_init = false;
|
||||
// set an invalid value to not yet initialized indexes managing
|
||||
// textures created to enhance 3D rendering
|
||||
m_text_pcb = m_text_silk = INVALID_INDEX;
|
||||
m_text_fake_shadow_front = INVALID_INDEX;
|
||||
m_text_fake_shadow_back = INVALID_INDEX;
|
||||
m_text_fake_shadow_board = INVALID_INDEX;
|
||||
|
||||
// position of the front and back layers
|
||||
// (will be initialized to a better value later)
|
||||
m_ZBottom = 0.0;
|
||||
m_ZTop = 0.0;
|
||||
|
||||
m_lightPos = S3D_VERTEX(0.0f, 0.0f, 30.0f);
|
||||
|
||||
// Clear all gl list identifiers:
|
||||
for( int ii = GL_ID_BEGIN; ii < GL_ID_END; ii++ )
|
||||
m_glLists[ii] = 0;
|
||||
|
||||
// Explicitly create a new rendering context instance for this canvas.
|
||||
m_glRC = new wxGLContext( this );
|
||||
|
||||
DisplayStatus();
|
||||
}
|
||||
|
||||
|
||||
EDA_3D_CANVAS::~EDA_3D_CANVAS()
|
||||
{
|
||||
ClearLists();
|
||||
m_init = false;
|
||||
delete m_glRC;
|
||||
|
||||
// Free the list of parsers list
|
||||
for( unsigned int i = 0; i < m_model_parsers_list.size(); i++ )
|
||||
delete m_model_parsers_list[i];
|
||||
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::ClearLists( int aGlList )
|
||||
{
|
||||
if( aGlList )
|
||||
{
|
||||
if( m_glLists[aGlList] > 0 )
|
||||
glDeleteLists( m_glLists[aGlList], 1 );
|
||||
|
||||
m_glLists[aGlList] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for( int ii = GL_ID_BEGIN; ii < GL_ID_END; ii++ )
|
||||
{
|
||||
if( m_glLists[ii] > 0 )
|
||||
glDeleteLists( m_glLists[ii], 1 );
|
||||
|
||||
m_glLists[ii] = 0;
|
||||
}
|
||||
|
||||
// When m_text_fake_shadow_??? is set to INVALID_INDEX, textures are not yet created.
|
||||
if( m_text_fake_shadow_front != INVALID_INDEX )
|
||||
glDeleteTextures( 1, &m_text_fake_shadow_front );
|
||||
|
||||
if( m_text_fake_shadow_back != INVALID_INDEX )
|
||||
glDeleteTextures( 1, &m_text_fake_shadow_back );
|
||||
|
||||
if( m_text_fake_shadow_board != INVALID_INDEX )
|
||||
glDeleteTextures( 1, &m_text_fake_shadow_board );
|
||||
|
||||
m_shadow_init = false;
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnChar( wxKeyEvent& event )
|
||||
{
|
||||
SetView3D( event.GetKeyCode() );
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::SetView3D( int keycode )
|
||||
{
|
||||
int ii;
|
||||
double delta_move = DELTA_MOVE_STEP * GetPrm3DVisu().m_Zoom;
|
||||
|
||||
switch( keycode )
|
||||
{
|
||||
case WXK_LEFT:
|
||||
m_draw3dOffset.x -= delta_move;
|
||||
break;
|
||||
|
||||
case WXK_RIGHT:
|
||||
m_draw3dOffset.x += delta_move;
|
||||
break;
|
||||
|
||||
case WXK_UP:
|
||||
m_draw3dOffset.y += delta_move;
|
||||
break;
|
||||
|
||||
case WXK_DOWN:
|
||||
m_draw3dOffset.y -= delta_move;
|
||||
break;
|
||||
|
||||
case WXK_HOME:
|
||||
GetPrm3DVisu().m_Zoom = 1.0;
|
||||
m_draw3dOffset.x = m_draw3dOffset.y = 0;
|
||||
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
break;
|
||||
|
||||
case WXK_END:
|
||||
break;
|
||||
|
||||
case WXK_F1:
|
||||
GetPrm3DVisu().m_Zoom /= 1.4;
|
||||
if( GetPrm3DVisu().m_Zoom <= 0.01 )
|
||||
GetPrm3DVisu().m_Zoom = 0.01;
|
||||
break;
|
||||
|
||||
case WXK_F2:
|
||||
GetPrm3DVisu().m_Zoom *= 1.4;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
break;
|
||||
|
||||
case '-':
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
case 'R':
|
||||
m_draw3dOffset.x = m_draw3dOffset.y = 0;
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
GetPrm3DVisu().m_ROTZ = -90;
|
||||
GetPrm3DVisu().m_ROTX = -90;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
GetPrm3DVisu().m_ROTZ = 90;
|
||||
GetPrm3DVisu().m_ROTX = -90;
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
GetPrm3DVisu().m_ROTX = -90;
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
GetPrm3DVisu().m_ROTX = -90;
|
||||
GetPrm3DVisu().m_ROTZ = -180;
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
GetPrm3DVisu().m_ROTX = -180;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayStatus();
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnMouseWheel( wxMouseEvent& event )
|
||||
{
|
||||
double delta = DELTA_MOVE_STEP * GetPrm3DVisu().m_Zoom;
|
||||
if ( GetPrm3DVisu().GetFlag( FL_MOUSEWHEEL_PANNING ) )
|
||||
delta *= 0.05 * event.GetWheelRotation();
|
||||
else
|
||||
if ( event.GetWheelRotation() < 0 )
|
||||
delta = -delta;
|
||||
|
||||
if( GetPrm3DVisu().GetFlag( FL_MOUSEWHEEL_PANNING ) )
|
||||
{
|
||||
if( event.GetWheelAxis() == wxMOUSE_WHEEL_HORIZONTAL )
|
||||
m_draw3dOffset.x -= delta;
|
||||
else
|
||||
m_draw3dOffset.y -= delta;
|
||||
}
|
||||
else if( event.ShiftDown() )
|
||||
{
|
||||
m_draw3dOffset.y -= delta;
|
||||
}
|
||||
else if( event.ControlDown() )
|
||||
{
|
||||
m_draw3dOffset.x += delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( event.GetWheelRotation() > 0 )
|
||||
{
|
||||
GetPrm3DVisu().m_Zoom /= 1.4;
|
||||
|
||||
if( GetPrm3DVisu().m_Zoom <= 0.01 )
|
||||
GetPrm3DVisu().m_Zoom = 0.01;
|
||||
}
|
||||
else
|
||||
GetPrm3DVisu().m_Zoom *= 1.4;
|
||||
|
||||
}
|
||||
|
||||
DisplayStatus();
|
||||
Refresh( false );
|
||||
GetPrm3DVisu().m_Beginx = event.GetX();
|
||||
GetPrm3DVisu().m_Beginy = event.GetY();
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void EDA_3D_CANVAS::OnMagnify( wxMouseEvent& event )
|
||||
{
|
||||
double magnification = ( event.GetMagnification() + 1.0f );
|
||||
|
||||
GetPrm3DVisu().m_Zoom /= magnification;
|
||||
|
||||
if( GetPrm3DVisu().m_Zoom <= 0.01 )
|
||||
{
|
||||
GetPrm3DVisu().m_Zoom = 0.01;
|
||||
}
|
||||
|
||||
DisplayStatus();
|
||||
Refresh( false );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnMouseMove( wxMouseEvent& event )
|
||||
{
|
||||
wxSize size( GetClientSize() );
|
||||
double spin_quat[4];
|
||||
|
||||
if( event.Dragging() )
|
||||
{
|
||||
if( event.LeftIsDown() )
|
||||
{
|
||||
/* drag in progress, simulate trackball */
|
||||
trackball( spin_quat,
|
||||
(2.0 * GetPrm3DVisu().m_Beginx - size.x) / size.x,
|
||||
(size.y - 2.0 * GetPrm3DVisu().m_Beginy) / size.y,
|
||||
( 2.0 * event.GetX() - size.x) / size.x,
|
||||
( size.y - 2.0 * event.GetY() ) / size.y );
|
||||
|
||||
add_quats( spin_quat, GetPrm3DVisu().m_Quat, GetPrm3DVisu().m_Quat );
|
||||
}
|
||||
else if( event.MiddleIsDown() )
|
||||
{
|
||||
/* middle button drag -> pan */
|
||||
|
||||
/* Current zoom and an additional factor are taken into account
|
||||
* for the amount of panning. */
|
||||
const double PAN_FACTOR = 8.0 * GetPrm3DVisu().m_Zoom;
|
||||
m_draw3dOffset.x -= PAN_FACTOR *
|
||||
( GetPrm3DVisu().m_Beginx - event.GetX() ) / size.x;
|
||||
m_draw3dOffset.y -= PAN_FACTOR *
|
||||
(event.GetY() - GetPrm3DVisu().m_Beginy) / size.y;
|
||||
}
|
||||
|
||||
/* orientation has changed, redraw mesh */
|
||||
DisplayStatus();
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
GetPrm3DVisu().m_Beginx = event.GetX();
|
||||
GetPrm3DVisu().m_Beginy = event.GetY();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnRightClick( wxMouseEvent& event )
|
||||
{
|
||||
wxPoint pos;
|
||||
wxMenu PopUpMenu;
|
||||
|
||||
pos.x = event.GetX();
|
||||
pos.y = event.GetY();
|
||||
|
||||
wxMenuItem* item = new wxMenuItem( &PopUpMenu, ID_POPUP_ZOOMIN, _( "Zoom +" ) );
|
||||
item->SetBitmap( KiBitmap( zoom_in_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_ZOOMOUT, _( "Zoom -" ) );
|
||||
item->SetBitmap( KiBitmap( zoom_out_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
PopUpMenu.AppendSeparator();
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_ZPOS, _( "Top View" ) );
|
||||
item->SetBitmap( KiBitmap( axis3d_top_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_ZNEG, _( "Bottom View" ) );
|
||||
item->SetBitmap( KiBitmap( axis3d_bottom_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
PopUpMenu.AppendSeparator();
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_XPOS, _( "Right View" ) );
|
||||
item->SetBitmap( KiBitmap( axis3d_right_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_XNEG, _( "Left View" ) );
|
||||
item->SetBitmap( KiBitmap( axis3d_left_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
PopUpMenu.AppendSeparator();
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_YPOS, _( "Front View" ) );
|
||||
item->SetBitmap( KiBitmap( axis3d_front_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_YNEG, _( "Back View" ) );
|
||||
item->SetBitmap( KiBitmap( axis3d_back_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
PopUpMenu.AppendSeparator();
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_LEFT, _( "Move left <-" ) );
|
||||
item->SetBitmap( KiBitmap( left_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_RIGHT, _( "Move right ->" ) );
|
||||
item->SetBitmap( KiBitmap( right_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_UP, _( "Move Up ^" ) );
|
||||
item->SetBitmap( KiBitmap( up_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_DOWN, _( "Move Down" ) );
|
||||
item->SetBitmap( KiBitmap( down_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
PopupMenu( &PopUpMenu, pos );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnPopUpMenu( wxCommandEvent& event )
|
||||
{
|
||||
int key = 0;
|
||||
|
||||
switch( event.GetId() )
|
||||
{
|
||||
case ID_POPUP_ZOOMIN:
|
||||
key = WXK_F1;
|
||||
break;
|
||||
|
||||
case ID_POPUP_ZOOMOUT:
|
||||
key = WXK_F2;
|
||||
break;
|
||||
|
||||
case ID_POPUP_VIEW_XPOS:
|
||||
key = 'x';
|
||||
break;
|
||||
|
||||
case ID_POPUP_VIEW_XNEG:
|
||||
key = 'X';
|
||||
break;
|
||||
|
||||
case ID_POPUP_VIEW_YPOS:
|
||||
key = 'y';
|
||||
break;
|
||||
|
||||
case ID_POPUP_VIEW_YNEG:
|
||||
key = 'Y';
|
||||
break;
|
||||
|
||||
case ID_POPUP_VIEW_ZPOS:
|
||||
key = 'z';
|
||||
break;
|
||||
|
||||
case ID_POPUP_VIEW_ZNEG:
|
||||
key = 'Z';
|
||||
break;
|
||||
|
||||
case ID_POPUP_MOVE3D_LEFT:
|
||||
key = WXK_LEFT;
|
||||
break;
|
||||
|
||||
case ID_POPUP_MOVE3D_RIGHT:
|
||||
key = WXK_RIGHT;
|
||||
break;
|
||||
|
||||
case ID_POPUP_MOVE3D_UP:
|
||||
key = WXK_UP;
|
||||
break;
|
||||
|
||||
case ID_POPUP_MOVE3D_DOWN:
|
||||
key = WXK_DOWN;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
SetView3D( key );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::DisplayStatus()
|
||||
{
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( wxT( "dx %3.2f" ), m_draw3dOffset.x );
|
||||
Parent()->SetStatusText( msg, 1 );
|
||||
|
||||
msg.Printf( wxT( "dy %3.2f" ), m_draw3dOffset.y );
|
||||
Parent()->SetStatusText( msg, 2 );
|
||||
|
||||
msg.Printf( _( "Zoom: %3.1f" ), 45 * GetPrm3DVisu().m_Zoom );
|
||||
Parent()->SetStatusText( msg, 3 );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnPaint( wxPaintEvent& event )
|
||||
{
|
||||
wxPaintDC dc( this );
|
||||
|
||||
Redraw();
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnEraseBackground( wxEraseEvent& event )
|
||||
{
|
||||
// Do nothing, to avoid flashing.
|
||||
}
|
||||
|
||||
typedef struct s_sImage
|
||||
{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
|
||||
unsigned char pixel_data[64 * 64 * 4 + 1];
|
||||
}tsImage;
|
||||
|
||||
|
||||
GLuint load_and_generate_texture( tsImage *image )
|
||||
{
|
||||
|
||||
GLuint texture;
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
glPixelStorei (GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
glGenTextures( 1, &texture );
|
||||
glBindTexture( GL_TEXTURE_2D, texture );
|
||||
gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, image->width, image->height,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image->pixel_data );
|
||||
|
||||
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::InitGL()
|
||||
{
|
||||
if( !m_init )
|
||||
{
|
||||
m_init = true;
|
||||
|
||||
|
||||
m_text_pcb = load_and_generate_texture( (tsImage *)&text_pcb );
|
||||
m_text_silk = load_and_generate_texture( (tsImage *)&text_silk );
|
||||
|
||||
GetPrm3DVisu().m_Zoom = 1.0;
|
||||
m_ZBottom = 1.0;
|
||||
m_ZTop = 10.0;
|
||||
|
||||
glDisable( GL_CULL_FACE ); // show back faces
|
||||
glEnable( GL_DEPTH_TEST ); // Enable z-buffering
|
||||
glEnable( GL_ALPHA_TEST );
|
||||
glEnable( GL_LINE_SMOOTH );
|
||||
// glEnable(GL_POLYGON_SMOOTH); // creates issues with some graphic cards
|
||||
glEnable( GL_NORMALIZE );
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
|
||||
// speedups
|
||||
//glEnable( GL_DITHER );
|
||||
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE );
|
||||
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
||||
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
// Initialize alpha blending function.
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::SetLights()
|
||||
{
|
||||
// activate light. the source is above the xy plane, at source_pos
|
||||
GLfloat source_pos[4] = { m_lightPos.x, m_lightPos.y, m_lightPos.z, 0.0f };
|
||||
GLfloat light_color[4]; // color of lights (RGBA values)
|
||||
light_color[3] = 1.0;
|
||||
|
||||
// Light above the xy plane
|
||||
light_color[0] = light_color[1] = light_color[2] = 0.0;
|
||||
glLightfv( GL_LIGHT0, GL_AMBIENT, light_color );
|
||||
|
||||
light_color[0] = light_color[1] = light_color[2] = 1.0;
|
||||
glLightfv( GL_LIGHT0, GL_DIFFUSE, light_color );
|
||||
|
||||
light_color[0] = light_color[1] = light_color[2] = 1.0;
|
||||
glLightfv( GL_LIGHT0, GL_SPECULAR, light_color );
|
||||
|
||||
glLightfv( GL_LIGHT0, GL_POSITION, source_pos );
|
||||
|
||||
light_color[0] = light_color[1] = light_color[2] = 0.2;
|
||||
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, light_color );
|
||||
|
||||
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
|
||||
|
||||
glEnable( GL_LIGHT0 ); // White spot on Z axis ( top )
|
||||
glEnable( GL_LIGHTING );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::TakeScreenshot( wxCommandEvent& event )
|
||||
{
|
||||
static wxFileName fn; // Remember path between saves during this session only.
|
||||
wxString FullFileName;
|
||||
wxString file_ext, mask;
|
||||
bool fmt_is_jpeg = false;
|
||||
|
||||
// First time path is set to the project path.
|
||||
if( !fn.IsOk() )
|
||||
fn = Parent()->Prj().GetProjectFullName();
|
||||
|
||||
if( event.GetId() == ID_MENU_SCREENCOPY_JPEG )
|
||||
fmt_is_jpeg = true;
|
||||
|
||||
if( event.GetId() != ID_TOOL_SCREENCOPY_TOCLIBBOARD )
|
||||
{
|
||||
file_ext = fmt_is_jpeg ? wxT( "jpg" ) : wxT( "png" );
|
||||
mask = wxT( "*." ) + file_ext;
|
||||
fn.SetExt( file_ext );
|
||||
|
||||
FullFileName = EDA_FILE_SELECTOR( _( "3D Image File Name:" ), fn.GetPath(),
|
||||
fn.GetFullName(), file_ext, mask, this,
|
||||
wxFD_SAVE | wxFD_OVERWRITE_PROMPT, true );
|
||||
|
||||
if( FullFileName.IsEmpty() )
|
||||
return;
|
||||
|
||||
fn = FullFileName;
|
||||
|
||||
// Be sure the screen area destroyed by the file dialog is redrawn before making
|
||||
// a screen copy.
|
||||
// Without this call, under Linux the screen refresh is made to late.
|
||||
wxYield();
|
||||
}
|
||||
|
||||
struct viewport_params
|
||||
{
|
||||
GLint originx;
|
||||
GLint originy;
|
||||
GLint x;
|
||||
GLint y;
|
||||
} viewport;
|
||||
|
||||
// Be sure we have the latest 3D view (remember 3D view is buffered)
|
||||
Refresh();
|
||||
wxYield();
|
||||
|
||||
// Build image from the 3D buffer
|
||||
wxWindowUpdateLocker noUpdates( this );
|
||||
glGetIntegerv( GL_VIEWPORT, (GLint*) &viewport );
|
||||
|
||||
unsigned char* pixelbuffer = (unsigned char*) malloc( viewport.x * viewport.y * 3 );
|
||||
unsigned char* alphabuffer = (unsigned char*) malloc( viewport.x * viewport.y );
|
||||
wxImage image( viewport.x, viewport.y );
|
||||
|
||||
glPixelStorei( GL_PACK_ALIGNMENT, 1 );
|
||||
glReadBuffer( GL_BACK_LEFT );
|
||||
glReadPixels( viewport.originx, viewport.originy,
|
||||
viewport.x, viewport.y,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, pixelbuffer );
|
||||
glReadPixels( viewport.originx, viewport.originy,
|
||||
viewport.x, viewport.y,
|
||||
GL_ALPHA, GL_UNSIGNED_BYTE, alphabuffer );
|
||||
|
||||
image.SetData( pixelbuffer );
|
||||
image.SetAlpha( alphabuffer );
|
||||
image = image.Mirror( false );
|
||||
wxBitmap bitmap( image );
|
||||
|
||||
if( event.GetId() == ID_TOOL_SCREENCOPY_TOCLIBBOARD )
|
||||
{
|
||||
if( wxTheClipboard->Open() )
|
||||
{
|
||||
wxBitmapDataObject* dobjBmp = new wxBitmapDataObject( bitmap );
|
||||
|
||||
if( !wxTheClipboard->SetData( dobjBmp ) )
|
||||
wxMessageBox( _( "Failed to copy image to clipboard" ) );
|
||||
|
||||
wxTheClipboard->Flush(); /* the data in clipboard will stay
|
||||
* available after the application exits */
|
||||
wxTheClipboard->Close();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxImage image = bitmap.ConvertToImage();
|
||||
|
||||
if( !image.SaveFile( FullFileName,
|
||||
fmt_is_jpeg ? wxBITMAP_TYPE_JPEG : wxBITMAP_TYPE_PNG ) )
|
||||
wxMessageBox( _( "Can't save file" ) );
|
||||
|
||||
image.Destroy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_viewer.h
|
||||
*/
|
||||
|
||||
#ifndef _3D_CANVAS_H_
|
||||
#define _3D_CANVAS_H_
|
||||
|
||||
#include <wx/glcanvas.h>
|
||||
|
||||
#ifdef __WXMAC__
|
||||
# ifdef __DARWIN__
|
||||
# include <OpenGL/glu.h>
|
||||
# else
|
||||
# include <glu.h>
|
||||
# endif
|
||||
#else
|
||||
# include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
#include <3d_struct.h>
|
||||
#include <modelparsers.h>
|
||||
#include <class_module.h>
|
||||
#include <CBBox.h>
|
||||
|
||||
class BOARD_DESIGN_SETTINGS;
|
||||
class EDA_3D_FRAME;
|
||||
class SHAPE_POLY_SET;
|
||||
class REPORTER;
|
||||
|
||||
class VIA;
|
||||
class D_PAD;
|
||||
|
||||
// We are using GL lists to store layers and other items
|
||||
// to draw or not
|
||||
// GL_LIST_ID are the GL lists indexes in m_glLists
|
||||
enum GL_LIST_ID
|
||||
{
|
||||
GL_ID_BEGIN = 0,
|
||||
GL_ID_AXIS = GL_ID_BEGIN, // list id for 3D axis
|
||||
GL_ID_GRID, // list id for 3D grid
|
||||
GL_ID_BOARD, // List id for copper layers
|
||||
GL_ID_TECH_LAYERS, // List id for non copper layers (masks...)
|
||||
GL_ID_AUX_LAYERS, // List id for user layers (draw, eco, comment)
|
||||
GL_ID_3DSHAPES_SOLID_FRONT, // List id for 3D shapes, non transparent entities
|
||||
GL_ID_3DSHAPES_TRANSP_FRONT,// List id for 3D shapes, transparent entities
|
||||
GL_ID_3DSHAPES_SOLID_BACK, // List id for 3D shapes, non transparent entities
|
||||
GL_ID_3DSHAPES_TRANSP_BACK, // List id for 3D shapes, transparent entities
|
||||
GL_ID_SHADOW_FRONT,
|
||||
GL_ID_SHADOW_BACK,
|
||||
GL_ID_SHADOW_BOARD,
|
||||
GL_ID_BODY, // Body only list
|
||||
GL_ID_END
|
||||
};
|
||||
|
||||
class EDA_3D_CANVAS : public wxGLCanvas
|
||||
{
|
||||
private:
|
||||
bool m_init;
|
||||
bool m_reportWarnings; ///< true to report all warnings when building the 3D scene
|
||||
///< false to report errors only
|
||||
GLuint m_glLists[GL_ID_END]; ///< GL lists
|
||||
wxGLContext* m_glRC;
|
||||
wxRealPoint m_draw3dOffset; ///< offset to draw the 3D mesh.
|
||||
double m_ZBottom; ///< position of the back layer
|
||||
double m_ZTop; ///< position of the front layer
|
||||
|
||||
GLuint m_text_pcb; ///< an index to the texture generated for pcb texts
|
||||
GLuint m_text_silk; ///< an index to the texture generated for silk layers
|
||||
|
||||
// Index to the textures generated for shadows
|
||||
bool m_shadow_init;
|
||||
GLuint m_text_fake_shadow_front;
|
||||
GLuint m_text_fake_shadow_back;
|
||||
GLuint m_text_fake_shadow_board;
|
||||
|
||||
CBBOX m_boardAABBox; ///< Axis Align Bounding Box of the board
|
||||
CBBOX m_fastAABBox; ///< Axis Align Bounding Box that contain the other bounding boxes
|
||||
CBBOX m_fastAABBox_Shadow; ///< A bit scalled version of the m_fastAABBox
|
||||
|
||||
S3D_VERTEX m_lightPos;
|
||||
|
||||
/// Stores the list of parsers for each new file name (dont repeat files already loaded)
|
||||
std::vector<S3D_MODEL_PARSER *> m_model_parsers_list;
|
||||
std::vector<wxString> m_model_filename_list;
|
||||
|
||||
void create_and_render_shadow_buffer( GLuint *aDst_gl_texture,
|
||||
GLuint aTexture_size, bool aDraw_body, int aBlurPasses );
|
||||
|
||||
void calcBBox();
|
||||
|
||||
public:
|
||||
EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList = 0 );
|
||||
~EDA_3D_CANVAS();
|
||||
|
||||
EDA_3D_FRAME* Parent() const { return static_cast<EDA_3D_FRAME*>( GetParent() ); }
|
||||
|
||||
BOARD* GetBoard() { return Parent()->GetBoard(); }
|
||||
|
||||
/**
|
||||
* Function ClearLists
|
||||
* Clear the display list.
|
||||
* @param aGlList = the list to clear.
|
||||
* if 0 (default) all lists are cleared
|
||||
*/
|
||||
void ClearLists( int aGlList = 0 );
|
||||
|
||||
// Event functions:
|
||||
void OnPaint( wxPaintEvent& event );
|
||||
void OnEraseBackground( wxEraseEvent& event );
|
||||
void OnChar( wxKeyEvent& event );
|
||||
void OnMouseWheel( wxMouseEvent& event );
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
#endif
|
||||
void OnMouseMove( wxMouseEvent& event );
|
||||
void OnRightClick( wxMouseEvent& event );
|
||||
void OnPopUpMenu( wxCommandEvent& event );
|
||||
|
||||
/**
|
||||
* Function TakeScreenshot
|
||||
*
|
||||
* creates a screenshot of the current 3D view and save to file as png or jpeg or image
|
||||
* is copied to the clipboard
|
||||
*/
|
||||
void TakeScreenshot( wxCommandEvent& event );
|
||||
void OnEnterWindow( wxMouseEvent& event );
|
||||
|
||||
// Display functions
|
||||
void SetView3D( int keycode );
|
||||
void DisplayStatus();
|
||||
void Redraw();
|
||||
void Render();
|
||||
|
||||
/**
|
||||
* Function CreateDrawGL_List
|
||||
* Prepares the parameters of the OpenGL draw list
|
||||
* creates the OpenGL draw list items (board, grid ...)
|
||||
* @param aErrorMessages = a REPORTER which will filled with error messages,
|
||||
* if any
|
||||
* @param aActivity = a REPORTER to display activity state
|
||||
*/
|
||||
void CreateDrawGL_List( REPORTER* aErrorMessages, REPORTER* aActivity );
|
||||
void InitGL();
|
||||
|
||||
void ReportWarnings( bool aReport ) { m_reportWarnings = aReport; }
|
||||
|
||||
void SetLights();
|
||||
|
||||
void SetOffset(double aPosX, double aPosY)
|
||||
{
|
||||
m_draw3dOffset.x = aPosX;
|
||||
m_draw3dOffset.y = aPosY;
|
||||
}
|
||||
|
||||
/** @return the INFO3D_VISU which contains the current parameters
|
||||
* to draw the 3D view og the board
|
||||
*/
|
||||
INFO3D_VISU& GetPrm3DVisu() const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* return true if we are in realistic mode render
|
||||
*/
|
||||
bool isRealisticMode() const;
|
||||
|
||||
/**
|
||||
* @return true if aItem should be displayed
|
||||
* @param aItem = an item of DISPLAY3D_FLG enum
|
||||
*/
|
||||
bool isEnabled( DISPLAY3D_FLG aItem ) const;
|
||||
|
||||
/** Helper function
|
||||
* @return true if aLayer should be displayed, false otherwise
|
||||
*/
|
||||
bool is3DLayerEnabled( LAYER_ID aLayer ) const;
|
||||
|
||||
/**
|
||||
* @return the size of the board in pcb units
|
||||
*/
|
||||
wxSize getBoardSize() const;
|
||||
|
||||
/**
|
||||
* @return the position of the board center in pcb units
|
||||
*/
|
||||
wxPoint getBoardCenter() const;
|
||||
|
||||
/**
|
||||
* Helper function setGLTechLayersColor
|
||||
* Initialize the color to draw the non copper layers
|
||||
* in realistic mode and normal mode.
|
||||
*/
|
||||
void setGLTechLayersColor( LAYER_NUM aLayer );
|
||||
|
||||
/**
|
||||
* Helper function setGLCopperColor
|
||||
* Initialize the copper color to draw the board
|
||||
* in realistic mode (a golden yellow color )
|
||||
*/
|
||||
void setGLCopperColor();
|
||||
|
||||
/**
|
||||
* Helper function setGLEpoxyColor
|
||||
* Initialize the color to draw the epoxy body board in realistic mode.
|
||||
*/
|
||||
void setGLEpoxyColor( float aTransparency = 1.0 );
|
||||
|
||||
/**
|
||||
* Helper function setGLSolderMaskColor
|
||||
* Initialize the color to draw the solder mask layers in realistic mode.
|
||||
*/
|
||||
void setGLSolderMaskColor( float aTransparency = 1.0 );
|
||||
|
||||
/**
|
||||
* Function buildBoard3DView
|
||||
* Called by CreateDrawGL_List()
|
||||
* Populates the OpenGL GL_ID_BOARD draw list with board items only on copper layers.
|
||||
* 3D footprint shapes, tech layers and aux layers are not on this list
|
||||
* Fills aErrorMessages with error messages created by some calculation function
|
||||
* display activity state
|
||||
* @param aBoardList =
|
||||
* @param aBodyOnlyList =
|
||||
* @param aErrorMessages = a REPORTER to add error and warning messages
|
||||
* created by the build process (can be NULL)
|
||||
* @param aActivity = a REPORTER to display activity state
|
||||
*/
|
||||
void buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
|
||||
REPORTER* aErrorMessages, REPORTER* aActivity );
|
||||
|
||||
/**
|
||||
* Function buildTechLayers3DView
|
||||
* Called by CreateDrawGL_List()
|
||||
* Populates the OpenGL GL_ID_TECH_LAYERS draw list with items on tech layers
|
||||
* @param aErrorMessages = a REPORTER to add error and warning messages
|
||||
* created by the build process (can be NULL)
|
||||
* @param aActivity = a REPORTER to display activity state
|
||||
*/
|
||||
void buildTechLayers3DView( REPORTER* aErrorMessages, REPORTER* aActivity );
|
||||
|
||||
/**
|
||||
* Function buildBoardThroughHolesPolygonList
|
||||
* Helper funtion to build the list of the board through holes polygons
|
||||
* @param allBoardHoles = the SHAPE_POLY_SET to populate
|
||||
* @param aSegCountPerCircle = the number of segments to approximate a circle
|
||||
* @param aOptimizeLargeCircles = true to use more than aSegCountPerCircle
|
||||
* for large circles (a large circle dimatere is > 1mm )
|
||||
*/
|
||||
void buildBoardThroughHolesPolygonList( SHAPE_POLY_SET& allBoardHoles,
|
||||
int aSegCountPerCircle, bool aOptimizeLargeCircles );
|
||||
|
||||
/**
|
||||
* Function buildShadowList
|
||||
* Called by CreateDrawGL_List()
|
||||
*/
|
||||
void buildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint aBoardList );
|
||||
|
||||
/**
|
||||
* Function buildFootprintShape3DList
|
||||
* Called by CreateDrawGL_List()
|
||||
* Fills the OpenGL GL_ID_3DSHAPES_SOLID and GL_ID_3DSHAPES_TRANSP
|
||||
* draw lists with 3D footprint shapes
|
||||
* @param aOpaqueList is the gl list for non transparent items
|
||||
* @param aTransparentList is the gl list for non transparent items,
|
||||
* @param aErrorMessages = a REPORTER to add error and warning messages
|
||||
* created by the build process (can be NULL)
|
||||
* @param aActivity = a REPORTER to display activity state
|
||||
* which need to be drawn after all other items
|
||||
*/
|
||||
void buildFootprintShape3DList( GLuint aOpaqueList,
|
||||
GLuint aTransparentList,
|
||||
REPORTER* aErrorMessages, REPORTER* aActivity );
|
||||
/**
|
||||
* Function buildBoard3DAuxLayers
|
||||
* Called by CreateDrawGL_List()
|
||||
* Fills the OpenGL GL_ID_AUX_LAYERS draw list
|
||||
* with items on aux layers only
|
||||
* @param aErrorMessages = a REPORTER to add error and warning messages
|
||||
* created by the build process (can be NULL)
|
||||
* @param aActivity = a REPORTER to display activity state
|
||||
* which need to be drawn after all other items
|
||||
*/
|
||||
void buildBoard3DAuxLayers( REPORTER* aErrorMessages, REPORTER* aActivity );
|
||||
|
||||
void draw3DGrid( double aGriSizeMM );
|
||||
void draw3DAxis();
|
||||
|
||||
/**
|
||||
* Helper function BuildPadShapeThickOutlineAsPolygon:
|
||||
* Build a pad outline as non filled polygon, to draw pads on silkscreen layer
|
||||
* with a line thickness = aWidth
|
||||
* Used only to draw pads outlines on silkscreen layers.
|
||||
*/
|
||||
void buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aWidth,
|
||||
int aCircleToSegmentsCount,
|
||||
double aCorrectionFactor );
|
||||
|
||||
|
||||
/**
|
||||
* Helper function draw3DViaHole:
|
||||
* Draw the via hole:
|
||||
* Build a vertical hole (a cylinder) between the first and the last via layers
|
||||
*/
|
||||
void draw3DViaHole( const VIA * aVia );
|
||||
|
||||
/**
|
||||
* Helper function draw3DPadHole:
|
||||
* Draw the pad hole:
|
||||
* Build a vertical hole (round or oblong) between the front and back layers
|
||||
*/
|
||||
void draw3DPadHole( const D_PAD * aPad );
|
||||
|
||||
/**
|
||||
* function render3DComponentShape
|
||||
* insert mesh in gl list
|
||||
* @param module
|
||||
* @param aIsRenderingJustNonTransparentObjects = true to load non transparent objects
|
||||
* @param aIsRenderingJustTransparentObjects = true to load non transparent objects
|
||||
* in openGL, transparent objects should be drawn *after* non transparent objects
|
||||
*/
|
||||
void render3DComponentShape( MODULE* module,
|
||||
bool aIsRenderingJustNonTransparentObjects,
|
||||
bool aIsRenderingJustTransparentObjects );
|
||||
|
||||
/**
|
||||
* function read3DComponentShape
|
||||
* read the 3D component shape(s) of the footprint (physical shape).
|
||||
* @param module
|
||||
* @return true if load was succeeded, false otherwise
|
||||
*/
|
||||
bool read3DComponentShape( MODULE* module );
|
||||
|
||||
/**
|
||||
* function generateFakeShadowsTextures
|
||||
* creates shadows of the board an footprints
|
||||
* for aesthetical purpose
|
||||
* @param aErrorMessages = a REPORTER to add error and warning messages
|
||||
* created by the build process (can be NULL)
|
||||
* @param aActivity = a REPORTER to display activity state
|
||||
*/
|
||||
void generateFakeShadowsTextures( REPORTER* aErrorMessages, REPORTER* aActivity );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
void CheckGLError(const char *aFileName, int aLineNumber);
|
||||
|
||||
#endif /* _3D_CANVAS_H_ */
|
||||
@@ -1,526 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cinfo3d_visu.cpp
|
||||
* @brief Handles data related with the board to be visualized
|
||||
*/
|
||||
|
||||
#include "../3d_rendering/ccamera.h"
|
||||
#include "cinfo3d_visu.h"
|
||||
#include <3d_rendering/3d_render_raytracing/shapes2D/cpolygon2d.h>
|
||||
#include <class_board.h>
|
||||
#include <3d_math.h>
|
||||
#include "3d_fastmath.h"
|
||||
#include <geometry/geometry_utils.h>
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_CINFO3D_VISU". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
const wxChar *CINFO3D_VISU::m_logTrace = wxT( "KI_TRACE_EDA_CINFO3D_VISU" );
|
||||
|
||||
|
||||
CINFO3D_VISU G_null_CINFO3D_VISU;
|
||||
|
||||
|
||||
CINFO3D_VISU::CINFO3D_VISU() :
|
||||
m_currentCamera( m_trackBallCamera ),
|
||||
m_trackBallCamera( RANGE_SCALE_3D )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::CINFO3D_VISU" ) );
|
||||
|
||||
m_board = NULL;
|
||||
m_3d_model_manager = NULL;
|
||||
m_3D_grid_type = GRID3D_NONE;
|
||||
m_drawFlags.resize( FL_LAST, false );
|
||||
|
||||
m_render_engine = RENDER_ENGINE_OPENGL_LEGACY;
|
||||
m_material_mode = MATERIAL_MODE_NORMAL;
|
||||
|
||||
m_boardPos = wxPoint();
|
||||
m_boardSize = wxSize();
|
||||
m_boardCenter = SFVEC3F( 0.0f );
|
||||
|
||||
m_boardBoudingBox.Reset();
|
||||
m_board2dBBox3DU.Reset();
|
||||
|
||||
m_layers_container2D.clear();
|
||||
m_layers_holes2D.clear();
|
||||
m_through_holes_inner.Clear();
|
||||
m_through_holes_outer.Clear();
|
||||
|
||||
m_copperLayersCount = -1;
|
||||
m_epoxyThickness3DU = 0.0f;
|
||||
m_copperThickness3DU = 0.0f;
|
||||
m_nonCopperLayerThickness3DU = 0.0f;
|
||||
m_biuTo3Dunits = 1.0;
|
||||
|
||||
m_stats_nr_tracks = 0;
|
||||
m_stats_nr_vias = 0;
|
||||
m_stats_via_med_hole_diameter = 0.0f;
|
||||
m_stats_nr_holes = 0;
|
||||
m_stats_hole_med_diameter = 0.0f;
|
||||
m_stats_track_med_width = 0.0f;
|
||||
|
||||
m_calc_seg_min_factor3DU = 0.0f;
|
||||
m_calc_seg_max_factor3DU = 0.0f;
|
||||
|
||||
|
||||
memset( m_layerZcoordTop, 0, sizeof( m_layerZcoordTop ) );
|
||||
memset( m_layerZcoordBottom, 0, sizeof( m_layerZcoordBottom ) );
|
||||
|
||||
SetFlag( FL_USE_REALISTIC_MODE, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_NORMAL, true );
|
||||
SetFlag( FL_SHOW_BOARD_BODY, true );
|
||||
SetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_NORMAL, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL, true );
|
||||
SetFlag( FL_ZONE, true );
|
||||
SetFlag( FL_SILKSCREEN, true );
|
||||
SetFlag( FL_SOLDERMASK, true );
|
||||
|
||||
m_BgColorBot = SFVEC3D( 0.4, 0.4, 0.5 );
|
||||
m_BgColorTop = SFVEC3D( 0.8, 0.8, 0.9 );
|
||||
m_BoardBodyColor = SFVEC3D( 0.4, 0.4, 0.5 );
|
||||
m_SolderMaskColor = SFVEC3D( 0.1, 0.2, 0.1 );
|
||||
m_SolderPasteColor = SFVEC3D( 0.4, 0.4, 0.4 );
|
||||
m_SilkScreenColor = SFVEC3D( 0.9, 0.9, 0.9 );
|
||||
m_CopperColor = SFVEC3D( 0.75, 0.61, 0.23 );
|
||||
}
|
||||
|
||||
|
||||
CINFO3D_VISU::~CINFO3D_VISU()
|
||||
{
|
||||
destroyLayers();
|
||||
}
|
||||
|
||||
|
||||
bool CINFO3D_VISU::Is3DLayerEnabled( PCB_LAYER_ID aLayer ) const
|
||||
{
|
||||
wxASSERT( aLayer < PCB_LAYER_ID_COUNT );
|
||||
|
||||
DISPLAY3D_FLG flg;
|
||||
|
||||
// see if layer needs to be shown
|
||||
// check the flags
|
||||
switch( aLayer )
|
||||
{
|
||||
case B_Adhes:
|
||||
case F_Adhes:
|
||||
flg = FL_ADHESIVE;
|
||||
break;
|
||||
|
||||
case B_Paste:
|
||||
case F_Paste:
|
||||
flg = FL_SOLDERPASTE;
|
||||
break;
|
||||
|
||||
case B_SilkS:
|
||||
case F_SilkS:
|
||||
flg = FL_SILKSCREEN;
|
||||
break;
|
||||
|
||||
case B_Mask:
|
||||
case F_Mask:
|
||||
flg = FL_SOLDERMASK;
|
||||
break;
|
||||
|
||||
case Dwgs_User:
|
||||
case Cmts_User:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
flg = FL_COMMENTS;
|
||||
break;
|
||||
|
||||
case Eco1_User:
|
||||
case Eco2_User:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
flg = FL_ECO;
|
||||
break;
|
||||
|
||||
case Edge_Cuts:
|
||||
if( GetFlag( FL_SHOW_BOARD_BODY ) || GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
||||
case Margin:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
||||
case B_Cu:
|
||||
case F_Cu:
|
||||
return m_board->GetDesignSettings().IsLayerVisible( aLayer ) ||
|
||||
GetFlag( FL_USE_REALISTIC_MODE );
|
||||
break;
|
||||
|
||||
default:
|
||||
// the layer is an internal copper layer, used the visibility
|
||||
if( GetFlag( FL_SHOW_BOARD_BODY ) &&
|
||||
(m_render_engine == RENDER_ENGINE_OPENGL_LEGACY) )
|
||||
{
|
||||
// Do not render internal layers if it is overlap with the board
|
||||
// (on OpenGL render)
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_board->GetDesignSettings().IsLayerVisible( aLayer );
|
||||
}
|
||||
|
||||
// The layer has a flag, return the flag
|
||||
return GetFlag( flg );
|
||||
}
|
||||
|
||||
|
||||
bool CINFO3D_VISU::GetFlag( DISPLAY3D_FLG aFlag ) const
|
||||
{
|
||||
wxASSERT( aFlag < FL_LAST );
|
||||
|
||||
return m_drawFlags[aFlag];
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::SetFlag( DISPLAY3D_FLG aFlag, bool aState )
|
||||
{
|
||||
wxASSERT( aFlag < FL_LAST );
|
||||
|
||||
m_drawFlags[aFlag] = aState;
|
||||
}
|
||||
|
||||
bool CINFO3D_VISU::ShouldModuleBeDisplayed( MODULE_ATTR_T aModuleAttributs ) const
|
||||
{
|
||||
if( ( ( aModuleAttributs == MOD_DEFAULT ) &&
|
||||
GetFlag( FL_MODULE_ATTRIBUTES_NORMAL ) ) ||
|
||||
( ( ( aModuleAttributs & MOD_CMS) == MOD_CMS ) &&
|
||||
GetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT ) ) ||
|
||||
( ( ( aModuleAttributs & MOD_VIRTUAL) == MOD_VIRTUAL ) &&
|
||||
GetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// !TODO: define the actual copper thickness by user
|
||||
#define COPPER_THICKNESS KiROUND( 0.035 * IU_PER_MM ) // for 35 um
|
||||
#define TECH_LAYER_THICKNESS KiROUND( 0.04 * IU_PER_MM )
|
||||
|
||||
int CINFO3D_VISU::GetCopperThicknessBIU() const
|
||||
{
|
||||
return COPPER_THICKNESS;
|
||||
}
|
||||
|
||||
unsigned int CINFO3D_VISU::GetNrSegmentsCircle( float aDiameter3DU ) const
|
||||
{
|
||||
wxASSERT( aDiameter3DU > 0.0f );
|
||||
|
||||
return GetNrSegmentsCircle( (int)( aDiameter3DU / m_biuTo3Dunits ) );
|
||||
}
|
||||
|
||||
|
||||
unsigned int CINFO3D_VISU::GetNrSegmentsCircle( int aDiameterBIU ) const
|
||||
{
|
||||
wxASSERT( aDiameterBIU > 0 );
|
||||
|
||||
return GetArcToSegmentCount( aDiameterBIU / 2, ARC_HIGH_DEF, 360.0 );
|
||||
}
|
||||
|
||||
|
||||
double CINFO3D_VISU::GetCircleCorrectionFactor( int aNrSides ) const
|
||||
{
|
||||
wxASSERT( aNrSides >= 3 );
|
||||
|
||||
return GetCircletoPolyCorrectionFactor( aNrSides );
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::InitSettings( REPORTER *aStatusTextReporter )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::InitSettings" ) );
|
||||
|
||||
// Calculates the board bounding box
|
||||
// First, use only the board outlines
|
||||
EDA_RECT bbbox = m_board->ComputeBoundingBox( true );
|
||||
|
||||
// If no outlines, use the board with items
|
||||
if( ( bbbox.GetWidth() == 0 ) && ( bbbox.GetHeight() == 0 ) )
|
||||
bbbox = m_board->ComputeBoundingBox( false );
|
||||
|
||||
// Gives a non null size to avoid issues in zoom / scale calculations
|
||||
if( ( bbbox.GetWidth() == 0 ) && ( bbbox.GetHeight() == 0 ) )
|
||||
bbbox.Inflate( Millimeter2iu( 10 ) );
|
||||
|
||||
m_boardSize = bbbox.GetSize();
|
||||
m_boardPos = bbbox.Centre();
|
||||
|
||||
wxASSERT( (m_boardSize.x > 0) && (m_boardSize.y > 0) );
|
||||
|
||||
m_boardPos.y = -m_boardPos.y; // The y coord is inverted in 3D viewer
|
||||
|
||||
m_copperLayersCount = m_board->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...
|
||||
if( m_copperLayersCount < 2 )
|
||||
m_copperLayersCount = 2;
|
||||
|
||||
// Calculate the convertion to apply to all positions.
|
||||
m_biuTo3Dunits = RANGE_SCALE_3D / std::max( m_boardSize.x, m_boardSize.y );
|
||||
|
||||
m_epoxyThickness3DU = m_board->GetDesignSettings().GetBoardThickness() *
|
||||
m_biuTo3Dunits;
|
||||
|
||||
// !TODO: use value defined by user (currently use default values by ctor
|
||||
m_copperThickness3DU = COPPER_THICKNESS * m_biuTo3Dunits;
|
||||
m_nonCopperLayerThickness3DU = TECH_LAYER_THICKNESS * m_biuTo3Dunits;
|
||||
|
||||
// Init Z position of each layer
|
||||
// calculate z position for each copper layer
|
||||
// Zstart = -m_epoxyThickness / 2.0 is the z position of the back (bottom layer) (layer id = 31)
|
||||
// Zstart = +m_epoxyThickness / 2.0 is the z position of the front (top layer) (layer id = 0)
|
||||
// all unused copper layer z position are set to 0
|
||||
|
||||
// ____==__________==________==______ <- Bottom = +m_epoxyThickness / 2.0,
|
||||
// | | Top = Bottom + m_copperThickness
|
||||
// |__________________________________|
|
||||
// == == == == <- Bottom = -m_epoxyThickness / 2.0,
|
||||
// Top = Bottom - m_copperThickness
|
||||
|
||||
unsigned int layer;
|
||||
|
||||
for( layer = 0; layer < m_copperLayersCount; ++layer )
|
||||
{
|
||||
m_layerZcoordBottom[layer] = m_epoxyThickness3DU / 2.0f -
|
||||
(m_epoxyThickness3DU * layer / (m_copperLayersCount - 1) );
|
||||
|
||||
if( layer < (m_copperLayersCount / 2) )
|
||||
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] + m_copperThickness3DU;
|
||||
else
|
||||
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] - m_copperThickness3DU;
|
||||
}
|
||||
|
||||
#define layerThicknessMargin 1.1
|
||||
const float zpos_offset = m_nonCopperLayerThickness3DU * layerThicknessMargin;
|
||||
|
||||
// Fill remaining unused copper layers and back layer zpos
|
||||
// with -m_epoxyThickness / 2.0
|
||||
for( ; layer < MAX_CU_LAYERS; layer++ )
|
||||
{
|
||||
m_layerZcoordBottom[layer] = -(m_epoxyThickness3DU / 2.0f);
|
||||
m_layerZcoordTop[layer] = -(m_epoxyThickness3DU / 2.0f) - m_copperThickness3DU;
|
||||
}
|
||||
|
||||
// This is the top of the copper layer thickness.
|
||||
const float zpos_copperTop_back = m_layerZcoordTop[B_Cu];
|
||||
const float zpos_copperTop_front = m_layerZcoordTop[F_Cu];
|
||||
|
||||
// calculate z position for each non copper layer
|
||||
// Solder mask and Solder paste have the same Z position
|
||||
for( int layer_id = MAX_CU_LAYERS; layer_id < PCB_LAYER_ID_COUNT; ++layer_id )
|
||||
{
|
||||
float zposTop;
|
||||
float zposBottom;
|
||||
|
||||
switch( layer_id )
|
||||
{
|
||||
case B_Adhes:
|
||||
zposBottom = zpos_copperTop_back - 2.0f * zpos_offset;
|
||||
zposTop = zposBottom - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_Adhes:
|
||||
zposBottom = zpos_copperTop_front + 2.0f * zpos_offset;
|
||||
zposTop = zposBottom + m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case B_Mask:
|
||||
case B_Paste:
|
||||
zposBottom = zpos_copperTop_back;
|
||||
zposTop = zpos_copperTop_back - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_Mask:
|
||||
case F_Paste:
|
||||
zposTop = zpos_copperTop_front + m_nonCopperLayerThickness3DU;
|
||||
zposBottom = zpos_copperTop_front;
|
||||
break;
|
||||
|
||||
case B_SilkS:
|
||||
zposBottom = zpos_copperTop_back - 1.0f * zpos_offset;
|
||||
zposTop = zposBottom - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_SilkS:
|
||||
zposBottom = zpos_copperTop_front + 1.0f * zpos_offset;
|
||||
zposTop = zposBottom + m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
// !TODO: review
|
||||
default:
|
||||
zposTop = zpos_copperTop_front + (layer_id - MAX_CU_LAYERS + 3.0f) * zpos_offset;
|
||||
zposBottom = zposTop - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
}
|
||||
|
||||
m_layerZcoordTop[layer_id] = zposTop;
|
||||
m_layerZcoordBottom[layer_id] = zposBottom;
|
||||
}
|
||||
|
||||
m_boardCenter = SFVEC3F( m_boardPos.x * m_biuTo3Dunits,
|
||||
m_boardPos.y * m_biuTo3Dunits,
|
||||
0.0f );
|
||||
|
||||
SFVEC3F boardSize = SFVEC3F( m_boardSize.x * m_biuTo3Dunits,
|
||||
m_boardSize.y * m_biuTo3Dunits,
|
||||
0.0f );
|
||||
boardSize /= 2.0f;
|
||||
|
||||
SFVEC3F boardMin = (m_boardCenter - boardSize);
|
||||
SFVEC3F boardMax = (m_boardCenter + boardSize);
|
||||
|
||||
boardMin.z = m_layerZcoordTop[B_Adhes];
|
||||
boardMax.z = m_layerZcoordTop[F_Adhes];
|
||||
|
||||
m_boardBoudingBox = CBBOX( boardMin, boardMax );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_startCreateBoardPolyTime = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Build board body" ) );
|
||||
|
||||
createBoardPolygon();
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_stopCreateBoardPolyTime = GetRunningMicroSecs();
|
||||
unsigned stats_startCreateLayersTime = stats_stopCreateBoardPolyTime;
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Create layers" ) );
|
||||
|
||||
createLayers( aStatusTextReporter );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_stopCreateLayersTime = GetRunningMicroSecs();
|
||||
|
||||
printf( "CINFO3D_VISU::InitSettings times\n" );
|
||||
printf( " CreateBoardPoly: %.3f ms\n",
|
||||
(float)( stats_stopCreateBoardPolyTime - stats_startCreateBoardPolyTime ) / 1e3 );
|
||||
printf( " CreateLayers and holes: %.3f ms\n",
|
||||
(float)( stats_stopCreateLayersTime - stats_startCreateLayersTime ) / 1e3 );
|
||||
printf( "\n" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::createBoardPolygon()
|
||||
{
|
||||
m_board_poly.RemoveAllContours();
|
||||
|
||||
wxString errmsg;
|
||||
|
||||
if( !m_board->GetBoardPolygonOutlines( m_board_poly, /*allLayerHoles,*/ &errmsg ) )
|
||||
{
|
||||
errmsg.append( wxT( "\n\n" ) );
|
||||
errmsg.append( _( "Cannot determine the board outline." ) );
|
||||
wxLogMessage( errmsg );
|
||||
}
|
||||
|
||||
// Be sure the polygon is strictly simple to avoid issues.
|
||||
m_board_poly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
Polygon_Calc_BBox_3DU( m_board_poly, m_board2dBBox3DU, m_biuTo3Dunits );
|
||||
}
|
||||
|
||||
|
||||
float CINFO3D_VISU::GetModulesZcoord3DIU( bool aIsFlipped ) const
|
||||
{
|
||||
if( aIsFlipped )
|
||||
{
|
||||
if( GetFlag( FL_SOLDERPASTE ) )
|
||||
return m_layerZcoordBottom[B_SilkS];
|
||||
else
|
||||
return m_layerZcoordBottom[B_Paste];
|
||||
}
|
||||
else
|
||||
{
|
||||
if( GetFlag( FL_SOLDERPASTE ) )
|
||||
return m_layerZcoordTop[F_SilkS];
|
||||
else
|
||||
return m_layerZcoordTop[F_Paste];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::CameraSetType( CAMERA_TYPE aCameraType )
|
||||
{
|
||||
switch( aCameraType )
|
||||
{
|
||||
case CAMERA_TRACKBALL:
|
||||
m_currentCamera = m_trackBallCamera;
|
||||
break;
|
||||
|
||||
default:
|
||||
wxLogMessage( wxT( "CINFO3D_VISU::CameraSetType() error: unknown camera type %d" ),
|
||||
(int)aCameraType );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetLayerColor( PCB_LAYER_ID aLayerId ) const
|
||||
{
|
||||
wxASSERT( aLayerId < PCB_LAYER_ID_COUNT );
|
||||
|
||||
const COLOR4D color = m_board->Colors().GetLayerColor( aLayerId );
|
||||
|
||||
return SFVEC3F( color.r, color.g, color.b );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetItemColor( int aItemId ) const
|
||||
{
|
||||
return GetColor( m_board->Colors().GetItemColor( aItemId ) );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetColor( COLOR4D aColor ) const
|
||||
{
|
||||
return SFVEC3F( aColor.r, aColor.g, aColor.b );
|
||||
}
|
||||
@@ -1,680 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cinfo3d_visu.h
|
||||
* @brief Handles data related with the board to be visualized
|
||||
*/
|
||||
|
||||
#ifndef CINFO3D_VISU_H
|
||||
#define CINFO3D_VISU_H
|
||||
|
||||
#include <vector>
|
||||
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes3D/cbbox.h"
|
||||
#include "../3d_rendering/ccamera.h"
|
||||
#include "../3d_rendering/ctrack_ball.h"
|
||||
#include "../3d_enums.h"
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
#include <class_pad.h>
|
||||
#include <class_track.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <pcb_base_frame.h>
|
||||
#include <class_pcb_text.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_dimension.h>
|
||||
#include <class_zone.h>
|
||||
#include <class_module.h>
|
||||
#include <reporter.h>
|
||||
|
||||
/// A type that stores a container of 2d objects for each layer id
|
||||
typedef std::map< PCB_LAYER_ID, CBVHCONTAINER2D *> MAP_CONTAINER_2D;
|
||||
|
||||
/// A type that stores polysets for each layer id
|
||||
typedef std::map< PCB_LAYER_ID, SHAPE_POLY_SET *> MAP_POLY;
|
||||
|
||||
/// This defines the range that all coord will have to be rendered.
|
||||
/// It will use this value to convert to a normalized value between
|
||||
/// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||
#define RANGE_SCALE_3D 8.0f
|
||||
|
||||
|
||||
/**
|
||||
* Class CINFO3D_VISU
|
||||
* Helper class to handle information needed to display 3D board
|
||||
*/
|
||||
class CINFO3D_VISU
|
||||
{
|
||||
public:
|
||||
|
||||
CINFO3D_VISU();
|
||||
|
||||
~CINFO3D_VISU();
|
||||
|
||||
/**
|
||||
* @brief Set3DCacheManager - Update the Cache manager pointer
|
||||
* @param aCachePointer: the pointer to the 3d cache manager
|
||||
*/
|
||||
void Set3DCacheManager( S3D_CACHE *aCachePointer ) { m_3d_model_manager = aCachePointer; }
|
||||
|
||||
/**
|
||||
* @brief Get3DCacheManager - Return the 3d cache manager pointer
|
||||
* @return
|
||||
*/
|
||||
S3D_CACHE *Get3DCacheManager( ) const { return m_3d_model_manager; }
|
||||
|
||||
/**
|
||||
* @brief GetFlag - get a configuration status of a flag
|
||||
* @param aFlag: the flag to get the status
|
||||
* @return true if flag is set, false if not
|
||||
*/
|
||||
bool GetFlag( DISPLAY3D_FLG aFlag ) const ;
|
||||
|
||||
/**
|
||||
* @brief SetFlag - set the status of a flag
|
||||
* @param aFlag: the flag to get the status
|
||||
* @param aState: status to set
|
||||
*/
|
||||
void SetFlag( DISPLAY3D_FLG aFlag, bool aState );
|
||||
|
||||
/**
|
||||
* @brief Is3DLayerEnabled - Check if a layer is enabled
|
||||
* @param aLayer: layer ID to get status
|
||||
* @return true if layer should be displayed, false if not
|
||||
*/
|
||||
bool Is3DLayerEnabled( PCB_LAYER_ID aLayer ) const;
|
||||
|
||||
/**
|
||||
* @brief ShouldModuleBeDisplayed - Test if module should be displayed in
|
||||
* relation to attributs and the flags
|
||||
* @return true if module should be displayed, false if not
|
||||
*/
|
||||
bool ShouldModuleBeDisplayed( MODULE_ATTR_T aModuleAttributs ) const;
|
||||
|
||||
/**
|
||||
* @brief SetBoard - Set current board to be rendered
|
||||
* @param aBoard: board to process
|
||||
*/
|
||||
void SetBoard( BOARD *aBoard ) { m_board = aBoard; }
|
||||
|
||||
/**
|
||||
* @brief GetBoard - Get current board to be rendered
|
||||
* @return BOARD pointer
|
||||
*/
|
||||
const BOARD *GetBoard() const { return m_board; }
|
||||
|
||||
/**
|
||||
* @brief InitSettings - Function to be called by the render when it need to
|
||||
* reload the settings for the board.
|
||||
* @param aStatusTextReporter: the pointer for the status reporter
|
||||
*/
|
||||
void InitSettings( REPORTER *aStatusTextReporter );
|
||||
|
||||
/**
|
||||
* @brief BiuTo3Dunits - Board integer units To 3D units
|
||||
* @return the conversion factor to transform a position from the board to 3d units
|
||||
*/
|
||||
double BiuTo3Dunits() const { return m_biuTo3Dunits; }
|
||||
|
||||
/**
|
||||
* @brief GetBBox3DU - Get the bbox of the pcb board
|
||||
* @return the board bbox in 3d units
|
||||
*/
|
||||
const CBBOX &GetBBox3DU() const { return m_boardBoudingBox; }
|
||||
|
||||
/**
|
||||
* @brief GetEpoxyThickness3DU - Get the current epoxy thickness
|
||||
* @return thickness in 3d unities
|
||||
*/
|
||||
float GetEpoxyThickness3DU() const { return m_epoxyThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetNonCopperLayerThickness3DU - Get the current non copper layers thickness
|
||||
* @return thickness in 3d unities of non copperlayers
|
||||
*/
|
||||
float GetNonCopperLayerThickness3DU() const { return m_nonCopperLayerThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetCopperThickness3DU - Get the current copper layer thickness
|
||||
* @return thickness in 3d unities of copperlayers
|
||||
*/
|
||||
float GetCopperThickness3DU() const { return m_copperThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetCopperThicknessBIU - Get the current copper layer thickness
|
||||
* @return thickness in board unities
|
||||
*/
|
||||
int GetCopperThicknessBIU() const;
|
||||
|
||||
/**
|
||||
* @brief GetBoardSizeBIU - Get the board size
|
||||
* @return size in BIU unities
|
||||
*/
|
||||
wxSize GetBoardSizeBIU() const { return m_boardSize; }
|
||||
|
||||
/**
|
||||
* @brief GetBoardPosBIU - Get the board size
|
||||
* @return size in BIU unities
|
||||
*/
|
||||
wxPoint GetBoardPosBIU() const { return m_boardPos; }
|
||||
|
||||
/**
|
||||
* @brief GetBoardCenter - the board center position in 3d units
|
||||
* @return board center vector position in 3d units
|
||||
*/
|
||||
const SFVEC3F &GetBoardCenter3DU() const { return m_boardCenter; }
|
||||
|
||||
/**
|
||||
* @brief GetModulesZcoord3DIU - Get the position of the module in 3d integer units
|
||||
* considering if it is flipped or not.
|
||||
* @param aIsFlipped: true for use in modules on Front (top) layer, false
|
||||
* if module is on back (bottom) layer
|
||||
* @return the Z position of 3D shapes, in 3D integer units
|
||||
*/
|
||||
float GetModulesZcoord3DIU( bool aIsFlipped ) const ;
|
||||
|
||||
/**
|
||||
* @brief CameraSetType - Set the camera type to use
|
||||
* @param aCameraType: camera type to use in this canvas
|
||||
*/
|
||||
void CameraSetType( CAMERA_TYPE aCameraType );
|
||||
|
||||
/**
|
||||
* @brief CameraGet - get current camera in use
|
||||
* @return a camera
|
||||
*/
|
||||
CCAMERA &CameraGet() const { return m_currentCamera; }
|
||||
|
||||
/**
|
||||
* @brief GridGet - get the current grid
|
||||
* @return space type of the grid
|
||||
*/
|
||||
GRID3D_TYPE GridGet() const { return m_3D_grid_type; }
|
||||
|
||||
/**
|
||||
* @brief GridSet - set the current grid
|
||||
* @param aGridType = the type space of the grid
|
||||
*/
|
||||
void GridSet( GRID3D_TYPE aGridType ) { m_3D_grid_type = aGridType; }
|
||||
|
||||
/**
|
||||
* @brief RenderEngineSet
|
||||
* @param aRenderEngine = the render engine mode selected
|
||||
*/
|
||||
void RenderEngineSet( RENDER_ENGINE aRenderEngine ) { m_render_engine = aRenderEngine; }
|
||||
|
||||
/**
|
||||
* @brief RenderEngineGet
|
||||
* @return render engine on use
|
||||
*/
|
||||
RENDER_ENGINE RenderEngineGet() const { return m_render_engine; }
|
||||
|
||||
/**
|
||||
* @brief MaterialModeSet
|
||||
* @param aMaterialMode = the render material mode
|
||||
*/
|
||||
void MaterialModeSet( MATERIAL_MODE aMaterialMode ) { m_material_mode = aMaterialMode; }
|
||||
|
||||
/**
|
||||
* @brief MaterialModeGet
|
||||
* @return material rendering mode
|
||||
*/
|
||||
MATERIAL_MODE MaterialModeGet() const { return m_material_mode; }
|
||||
|
||||
/**
|
||||
* @brief GetBoardPoly - Get the current polygon of the epoxy board
|
||||
* @return the shape polygon
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetBoardPoly() const { return m_board_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetLayerColor - get the technical color of a layer
|
||||
* @param aLayerId: the layer to get the color information
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetLayerColor( PCB_LAYER_ID aLayerId ) const;
|
||||
|
||||
/**
|
||||
* @brief GetItemColor - get the technical color of a layer
|
||||
* @param aItemId: the item id to get the color information
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetItemColor( int aItemId ) const;
|
||||
|
||||
/**
|
||||
* @brief GetColor
|
||||
* @param aColor: the color mapped
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetColor( COLOR4D aColor ) const;
|
||||
|
||||
/**
|
||||
* @brief GetLayerTopZpos3DU - Get the top z position
|
||||
* @param aLayerId: layer id
|
||||
* @return position in 3D unities
|
||||
*/
|
||||
float GetLayerTopZpos3DU( PCB_LAYER_ID aLayerId ) const { return m_layerZcoordTop[aLayerId]; }
|
||||
|
||||
/**
|
||||
* @brief GetLayerBottomZpos3DU - Get the bottom z position
|
||||
* @param aLayerId: layer id
|
||||
* @return position in 3D unities
|
||||
*/
|
||||
float GetLayerBottomZpos3DU( PCB_LAYER_ID aLayerId ) const { return m_layerZcoordBottom[aLayerId]; }
|
||||
|
||||
/**
|
||||
* @brief GetMapLayers - Get the map of container that have the objects per layer
|
||||
* @return the map containers of this board
|
||||
*/
|
||||
const MAP_CONTAINER_2D &GetMapLayers() const { return m_layers_container2D; }
|
||||
|
||||
/**
|
||||
* @brief GetMapLayersHoles -Get the map of container that have the holes per layer
|
||||
* @return the map containers of holes from this board
|
||||
*/
|
||||
const MAP_CONTAINER_2D &GetMapLayersHoles() const { return m_layers_holes2D; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Outer - Get the inflated ThroughHole container
|
||||
* @return a container with holes
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Outer() const { return m_through_holes_outer; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Outer_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Outer_poly() const { return m_through_outer_holes_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Outer_poly_NPTH -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Outer_poly_NPTH() const {
|
||||
return m_through_outer_holes_poly_NPTH; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Outer -
|
||||
* @return a container with via THT holes only
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Vias_Outer() const { return m_through_holes_vias_outer; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Inner -
|
||||
* @return a container with via THT holes only
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Vias_Inner() const { return m_through_holes_vias_inner; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Outer_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Vias_Outer_poly() const {
|
||||
return m_through_outer_holes_vias_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Inner_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Vias_Inner_poly() const {
|
||||
return m_through_inner_holes_vias_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Inner - Get the ThroughHole container
|
||||
* @return a container with holes
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Inner() const { return m_through_holes_inner; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Inner_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Inner_poly() const { return m_through_inner_holes_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Nr_Vias - Get statistics of the nr of vias
|
||||
* @return number of vias
|
||||
*/
|
||||
unsigned int GetStats_Nr_Vias() const { return m_stats_nr_vias; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Nr_Holes - Get statistics of the nr of holes
|
||||
* @return number of holes
|
||||
*/
|
||||
unsigned int GetStats_Nr_Holes() const { return m_stats_nr_holes; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Med_Via_Hole_Diameter3DU - Average diameter of the via holes
|
||||
* @return dimension in 3D units
|
||||
*/
|
||||
float GetStats_Med_Via_Hole_Diameter3DU() const { return m_stats_via_med_hole_diameter; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Med_Hole_Diameter3DU - Average diameter of holes
|
||||
* @return dimension in 3D units
|
||||
*/
|
||||
float GetStats_Med_Hole_Diameter3DU() const { return m_stats_hole_med_diameter; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Med_Track_Width - Average width of the tracks
|
||||
* @return dimensions in 3D units
|
||||
*/
|
||||
float GetStats_Med_Track_Width() const { return m_stats_track_med_width; }
|
||||
|
||||
/**
|
||||
* @brief GetNrSegmentsCircle
|
||||
* @param aDiameter3DU: diameter in 3DU
|
||||
* @return number of sides that should be used in that circle
|
||||
*/
|
||||
unsigned int GetNrSegmentsCircle( float aDiameter3DU ) const;
|
||||
|
||||
/**
|
||||
* @brief GetNrSegmentsCircle
|
||||
* @param aDiameterBIU: diameter in board internal units
|
||||
* @return number of sides that should be used in that circle
|
||||
*/
|
||||
unsigned int GetNrSegmentsCircle( int aDiameterBIU ) const;
|
||||
|
||||
/**
|
||||
* @brief GetCircleCorrectionFactor - computes a angle correction
|
||||
* factor used when creating circles
|
||||
* @param aNrSides: the number of segments sides of the circle
|
||||
* @return a factor to apply to contour creation
|
||||
*/
|
||||
double GetCircleCorrectionFactor( int aNrSides ) const;
|
||||
|
||||
/**
|
||||
* @brief GetPolyMap - Get maps of polygons's layers
|
||||
* @return the map with polygons's layers
|
||||
*/
|
||||
const MAP_POLY &GetPolyMap() const { return m_layers_poly; }
|
||||
|
||||
const MAP_POLY &GetPolyMapHoles_Inner() const { return m_layers_inner_holes_poly; }
|
||||
|
||||
const MAP_POLY &GetPolyMapHoles_Outer() const { return m_layers_outer_holes_poly; }
|
||||
|
||||
private:
|
||||
void createBoardPolygon();
|
||||
void createLayers( REPORTER *aStatusTextReporter );
|
||||
void destroyLayers();
|
||||
|
||||
// Helper functions to create the board
|
||||
COBJECT2D *createNewTrack( const TRACK* aTrack , int aClearanceValue ) const;
|
||||
|
||||
void createNewPad( const D_PAD* aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
wxSize aInflateValue ) const;
|
||||
|
||||
void createNewPadWithClearance( const D_PAD *aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
wxSize aClearanceValue ) const;
|
||||
|
||||
COBJECT2D *createNewPadDrill( const D_PAD* aPad, int aInflateValue );
|
||||
|
||||
void AddPadsShapesWithClearanceToContainer( const MODULE *aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper );
|
||||
|
||||
void AddGraphicsShapesWithClearanceToContainer( const MODULE *aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aInflateValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const TEXTE_PCB *aTextPCB,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const DRAWSEGMENT *aDrawSegment,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const DIMENSION *aDimension,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddSolidAreasShapesToContainer( const ZONE_CONTAINER *aZoneContainer,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId );
|
||||
|
||||
void TransformArcToSegments( const wxPoint &aCentre,
|
||||
const wxPoint &aStart,
|
||||
double aArcAngle,
|
||||
int aCircleToSegmentsCount,
|
||||
int aWidth,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
const BOARD_ITEM &aBoardItem );
|
||||
|
||||
void buildPadShapeThickOutlineAsSegments( const D_PAD *aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
int aWidth );
|
||||
|
||||
// Helper functions to create poly contours
|
||||
void buildPadShapeThickOutlineAsPolygon( const D_PAD *aPad,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
int aWidth) const;
|
||||
|
||||
void transformPadsShapesWithClearanceToPolygon( const DLIST<D_PAD> &aPads,
|
||||
PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper) const;
|
||||
|
||||
void transformGraphicModuleEdgeToPolygonSet( const MODULE *aModule,
|
||||
PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer ) const;
|
||||
|
||||
void buildPadShapePolygon( const D_PAD *aPad,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
wxSize aInflateValue,
|
||||
int aSegmentsPerCircle,
|
||||
double aCorrectionFactor ) const;
|
||||
|
||||
|
||||
public:
|
||||
SFVEC3D m_BgColorBot; ///< background bottom color
|
||||
SFVEC3D m_BgColorTop; ///< background top color
|
||||
SFVEC3D m_BoardBodyColor; ///< in realistic mode: FR4 board color
|
||||
SFVEC3D m_SolderMaskColor; ///< in realistic mode: solder mask color
|
||||
SFVEC3D m_SolderPasteColor; ///< in realistic mode: solder paste color
|
||||
SFVEC3D m_SilkScreenColor; ///< in realistic mode: SilkScreen color
|
||||
SFVEC3D m_CopperColor; ///< in realistic mode: copper color
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/// Current board
|
||||
BOARD *m_board;
|
||||
|
||||
/// pointer to the 3d model manager
|
||||
S3D_CACHE *m_3d_model_manager;
|
||||
|
||||
|
||||
// Render options
|
||||
|
||||
/// options flags to render the board
|
||||
std::vector< bool > m_drawFlags;
|
||||
|
||||
/// Stores the current grid type
|
||||
GRID3D_TYPE m_3D_grid_type;
|
||||
|
||||
/// render engine currently on use
|
||||
RENDER_ENGINE m_render_engine;
|
||||
|
||||
/// mode to render the 3d shape models material
|
||||
MATERIAL_MODE m_material_mode;
|
||||
|
||||
|
||||
// Pcb board position
|
||||
|
||||
/// center board actual position in board units
|
||||
wxPoint m_boardPos;
|
||||
|
||||
/// board actual size in board units
|
||||
wxSize m_boardSize;
|
||||
|
||||
/// 3d center position of the pcb board in 3d units
|
||||
SFVEC3F m_boardCenter;
|
||||
|
||||
|
||||
// Pcb board bounding boxes
|
||||
|
||||
/// 3d bouding box of the pcb board in 3d units
|
||||
CBBOX m_boardBoudingBox;
|
||||
|
||||
/// 2d bouding box of the pcb board in 3d units
|
||||
CBBOX2D m_board2dBBox3DU;
|
||||
|
||||
/// It contains polygon contours for each layer
|
||||
MAP_POLY m_layers_poly;
|
||||
|
||||
/// It contains polygon contours for holes of each layer (outer holes)
|
||||
MAP_POLY m_layers_outer_holes_poly;
|
||||
|
||||
/// It contains polygon contours for holes of each layer (inner holes)
|
||||
MAP_POLY m_layers_inner_holes_poly;
|
||||
|
||||
/// It contains polygon contours for (just) non plated through holes (outer cylinder)
|
||||
SHAPE_POLY_SET m_through_outer_holes_poly_NPTH;
|
||||
|
||||
/// It contains polygon contours for through holes (outer cylinder)
|
||||
SHAPE_POLY_SET m_through_outer_holes_poly;
|
||||
|
||||
/// It contains polygon contours for through holes (inner cylinder)
|
||||
SHAPE_POLY_SET m_through_inner_holes_poly;
|
||||
|
||||
/// It contains polygon contours for through holes vias (outer cylinder)
|
||||
SHAPE_POLY_SET m_through_outer_holes_vias_poly;
|
||||
|
||||
/// It contains polygon contours for through holes vias (inner cylinder)
|
||||
SHAPE_POLY_SET m_through_inner_holes_vias_poly;
|
||||
|
||||
/// PCB board outline polygon
|
||||
SHAPE_POLY_SET m_board_poly;
|
||||
|
||||
|
||||
// 2D element containers
|
||||
|
||||
/// It contains the 2d elements of each layer
|
||||
MAP_CONTAINER_2D m_layers_container2D;
|
||||
|
||||
/// It contains the holes per each layer
|
||||
MAP_CONTAINER_2D m_layers_holes2D;
|
||||
|
||||
/// It contains the list of throughHoles of the board,
|
||||
/// the radius of the hole is inflated with the copper tickness
|
||||
CBVHCONTAINER2D m_through_holes_outer;
|
||||
|
||||
/// It contains the list of throughHoles of the board,
|
||||
/// the radius is the inner hole
|
||||
CBVHCONTAINER2D m_through_holes_inner;
|
||||
|
||||
/// It contains the list of throughHoles vias of the board,
|
||||
/// the radius of the hole is inflated with the copper tickness
|
||||
CBVHCONTAINER2D m_through_holes_vias_outer;
|
||||
|
||||
/// It contains the list of throughHoles vias of the board,
|
||||
/// the radius of the hole
|
||||
CBVHCONTAINER2D m_through_holes_vias_inner;
|
||||
|
||||
|
||||
// Layers information
|
||||
|
||||
/// Number of copper layers actually used by the board
|
||||
unsigned int m_copperLayersCount;
|
||||
|
||||
/// Normalization scale to convert board internal units to 3D units to
|
||||
/// normalize 3D units between -1.0 and +1.0
|
||||
double m_biuTo3Dunits;
|
||||
|
||||
/// Top (End) Z position of each layer (normalized)
|
||||
float m_layerZcoordTop[PCB_LAYER_ID_COUNT];
|
||||
|
||||
/// Bottom (Start) Z position of each layer (normalized)
|
||||
float m_layerZcoordBottom[PCB_LAYER_ID_COUNT];
|
||||
|
||||
/// Copper thickness (normalized)
|
||||
float m_copperThickness3DU;
|
||||
|
||||
/// Epoxy thickness (normalized)
|
||||
float m_epoxyThickness3DU;
|
||||
|
||||
/// Non copper layers thickness
|
||||
float m_nonCopperLayerThickness3DU;
|
||||
|
||||
|
||||
// Cameras
|
||||
|
||||
/// Holds a pointer to current camera in use.
|
||||
CCAMERA &m_currentCamera;
|
||||
CTRACK_BALL m_trackBallCamera;
|
||||
|
||||
/// min factor used for cicle segment approximation calculation
|
||||
float m_calc_seg_min_factor3DU;
|
||||
|
||||
/// max factor used for cicle segment approximation calculation
|
||||
float m_calc_seg_max_factor3DU;
|
||||
|
||||
|
||||
// Statistics
|
||||
|
||||
/// Number of tracks in the board
|
||||
unsigned int m_stats_nr_tracks;
|
||||
|
||||
/// Track average width
|
||||
float m_stats_track_med_width;
|
||||
|
||||
/// Nr of vias
|
||||
unsigned int m_stats_nr_vias;
|
||||
|
||||
/// Computed medium diameter of the via holes in 3D units
|
||||
float m_stats_via_med_hole_diameter;
|
||||
|
||||
/// number of holes in the board
|
||||
unsigned int m_stats_nr_holes;
|
||||
|
||||
/// Computed medium diameter of the holes in 3D units
|
||||
float m_stats_hole_med_diameter;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_CINFO3D_VISU". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar *m_logTrace;
|
||||
|
||||
};
|
||||
|
||||
/// This is a dummy visualization configuration
|
||||
extern CINFO3D_VISU G_null_CINFO3D_VISU;
|
||||
|
||||
#endif // CINFO3D_VISU_H
|
||||
@@ -1,987 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file create_graphic_brd_items.cpp
|
||||
* @brief This file implements the creation of 2D graphic primitives of pcb items:
|
||||
* pads, tracks, drawsegments, texts....
|
||||
* It is based on the function found in the files:
|
||||
* board_items_to_polygon_shape_transform.cpp
|
||||
*/
|
||||
|
||||
#include "cinfo3d_visu.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes2D/cring2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes2D/cfilledcircle2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes2D/croundsegment2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes2D/cpolygon4pts2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes2D/cpolygon2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes3D/ccylinder.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes3D/clayeritem.h"
|
||||
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <class_pad.h>
|
||||
#include <class_pcb_text.h>
|
||||
#include <class_edge_mod.h>
|
||||
#include <class_zone.h>
|
||||
#include <class_text_mod.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <trigo.h>
|
||||
#include <draw_graphic_text.h>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
||||
// These variables are parameters used in addTextSegmToContainer.
|
||||
// But addTextSegmToContainer is a call-back function,
|
||||
// so we cannot send them as arguments.
|
||||
static int s_textWidth;
|
||||
static CGENERICCONTAINER2D *s_dstcontainer = NULL;
|
||||
static float s_biuTo3Dunits;
|
||||
static const CBBOX2D *s_boardBBox3DU = NULL;
|
||||
static const BOARD_ITEM *s_boardItem = NULL;
|
||||
|
||||
// This is a call back function, used by DrawGraphicText to draw the 3D text shape:
|
||||
void addTextSegmToContainer( int x0, int y0, int xf, int yf, void* aData )
|
||||
{
|
||||
wxASSERT( s_boardBBox3DU != NULL );
|
||||
wxASSERT( s_dstcontainer != NULL );
|
||||
|
||||
const SFVEC2F start3DU( x0 * s_biuTo3Dunits, -y0 * s_biuTo3Dunits );
|
||||
const SFVEC2F end3DU ( xf * s_biuTo3Dunits, -yf * s_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
s_dstcontainer->Add( new CFILLEDCIRCLE2D( start3DU,
|
||||
s_textWidth * s_biuTo3Dunits,
|
||||
*s_boardItem) );
|
||||
else
|
||||
s_dstcontainer->Add( new CROUNDSEGMENT2D( start3DU,
|
||||
end3DU,
|
||||
s_textWidth * s_biuTo3Dunits,
|
||||
*s_boardItem ) );
|
||||
}
|
||||
|
||||
|
||||
// Based on
|
||||
// void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet
|
||||
// board_items_to_polygon_shape_transform.cpp
|
||||
void CINFO3D_VISU::AddShapeWithClearanceToContainer( const TEXTE_PCB* aTextPCB,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue )
|
||||
{
|
||||
wxSize size = aTextPCB->GetTextSize();
|
||||
|
||||
if( aTextPCB->IsMirrored() )
|
||||
size.x = -size.x;
|
||||
|
||||
s_boardItem = (const BOARD_ITEM *)&aTextPCB;
|
||||
s_dstcontainer = aDstContainer;
|
||||
s_textWidth = aTextPCB->GetThickness() + ( 2 * aClearanceValue );
|
||||
s_biuTo3Dunits = m_biuTo3Dunits;
|
||||
s_boardBBox3DU = &m_board2dBBox3DU;
|
||||
|
||||
// not actually used, but needed by DrawGraphicText
|
||||
const COLOR4D dummy_color = COLOR4D::BLACK;
|
||||
|
||||
if( aTextPCB->IsMultilineAllowed() )
|
||||
{
|
||||
wxArrayString strings_list;
|
||||
wxStringSplit( aTextPCB->GetShownText(), strings_list, '\n' );
|
||||
std::vector<wxPoint> positions;
|
||||
positions.reserve( strings_list.Count() );
|
||||
aTextPCB->GetPositionsOfLinesOfMultilineText( positions,
|
||||
strings_list.Count() );
|
||||
|
||||
for( unsigned ii = 0; ii < strings_list.Count(); ++ii )
|
||||
{
|
||||
wxString txt = strings_list.Item( ii );
|
||||
|
||||
DrawGraphicText( NULL, NULL, positions[ii], dummy_color,
|
||||
txt, aTextPCB->GetTextAngle(), size,
|
||||
aTextPCB->GetHorizJustify(), aTextPCB->GetVertJustify(),
|
||||
aTextPCB->GetThickness(), aTextPCB->IsItalic(),
|
||||
true, addTextSegmToContainer );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawGraphicText( NULL, NULL, aTextPCB->GetTextPos(), dummy_color,
|
||||
aTextPCB->GetShownText(), aTextPCB->GetTextAngle(), size,
|
||||
aTextPCB->GetHorizJustify(), aTextPCB->GetVertJustify(),
|
||||
aTextPCB->GetThickness(), aTextPCB->IsItalic(),
|
||||
true, addTextSegmToContainer );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::AddShapeWithClearanceToContainer( const DIMENSION* aDimension,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue )
|
||||
{
|
||||
AddShapeWithClearanceToContainer(&aDimension->Text(), aDstContainer, aLayerId, aClearanceValue);
|
||||
|
||||
const int linewidth = aDimension->GetWidth() + (2 * aClearanceValue);
|
||||
|
||||
std::pair<wxPoint const *, wxPoint const *> segs[] = {
|
||||
{&aDimension->m_crossBarO, &aDimension->m_crossBarF},
|
||||
{&aDimension->m_featureLineGO, &aDimension->m_featureLineGF},
|
||||
{&aDimension->m_featureLineDO, &aDimension->m_featureLineDF},
|
||||
{&aDimension->m_crossBarF, &aDimension->m_arrowD1F},
|
||||
{&aDimension->m_crossBarF, &aDimension->m_arrowD2F},
|
||||
{&aDimension->m_crossBarO, &aDimension->m_arrowG1F},
|
||||
{&aDimension->m_crossBarO, &aDimension->m_arrowG2F}};
|
||||
|
||||
for( auto const & ii : segs )
|
||||
{
|
||||
const SFVEC2F start3DU( ii.first->x * m_biuTo3Dunits,
|
||||
-ii.first->y * m_biuTo3Dunits );
|
||||
|
||||
const SFVEC2F end3DU ( ii.second->x * m_biuTo3Dunits,
|
||||
-ii.second->y * m_biuTo3Dunits );
|
||||
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
|
||||
end3DU,
|
||||
linewidth * m_biuTo3Dunits,
|
||||
*aDimension ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Based on
|
||||
// void MODULE::TransformGraphicShapesWithClearanceToPolygonSet
|
||||
// board_items_to_polygon_shape_transform.cpp#L204
|
||||
void CINFO3D_VISU::AddGraphicsShapesWithClearanceToContainer( const MODULE* aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aInflateValue )
|
||||
{
|
||||
std::vector<TEXTE_MODULE *> texts; // List of TEXTE_MODULE to convert
|
||||
EDGE_MODULE* outline;
|
||||
|
||||
for( EDA_ITEM* item = aModule->GraphicalItemsList();
|
||||
item != NULL;
|
||||
item = item->Next() )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_MODULE_TEXT_T:
|
||||
{
|
||||
TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( item );
|
||||
|
||||
if( text->GetLayer() == aLayerId && text->IsVisible() )
|
||||
texts.push_back( text );
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case PCB_MODULE_EDGE_T:
|
||||
{
|
||||
outline = (EDGE_MODULE*) item;
|
||||
|
||||
if( outline->GetLayer() != aLayerId )
|
||||
break;
|
||||
|
||||
AddShapeWithClearanceToContainer( (const DRAWSEGMENT *)outline,
|
||||
aDstContainer,
|
||||
aLayerId, 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert texts sur modules
|
||||
if( aModule->Reference().GetLayer() == aLayerId && aModule->Reference().IsVisible() )
|
||||
texts.push_back( &aModule->Reference() );
|
||||
|
||||
if( aModule->Value().GetLayer() == aLayerId && aModule->Value().IsVisible() )
|
||||
texts.push_back( &aModule->Value() );
|
||||
|
||||
s_boardItem = (const BOARD_ITEM *)&aModule->Value();
|
||||
s_dstcontainer = aDstContainer;
|
||||
s_biuTo3Dunits = m_biuTo3Dunits;
|
||||
s_boardBBox3DU = &m_board2dBBox3DU;
|
||||
|
||||
for( unsigned ii = 0; ii < texts.size(); ++ii )
|
||||
{
|
||||
TEXTE_MODULE *textmod = texts[ii];
|
||||
s_textWidth = textmod->GetThickness() + ( 2 * aInflateValue );
|
||||
wxSize size = textmod->GetTextSize();
|
||||
|
||||
if( textmod->IsMirrored() )
|
||||
size.x = -size.x;
|
||||
|
||||
DrawGraphicText( NULL, NULL, textmod->GetTextPos(), BLACK,
|
||||
textmod->GetShownText(), textmod->GetDrawRotation(), size,
|
||||
textmod->GetHorizJustify(), textmod->GetVertJustify(),
|
||||
textmod->GetThickness(), textmod->IsItalic(),
|
||||
true, addTextSegmToContainer );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
COBJECT2D *CINFO3D_VISU::createNewTrack( const TRACK* aTrack,
|
||||
int aClearanceValue ) const
|
||||
{
|
||||
SFVEC2F start3DU( aTrack->GetStart().x * m_biuTo3Dunits,
|
||||
-aTrack->GetStart().y * m_biuTo3Dunits ); // y coord is inverted
|
||||
|
||||
switch( aTrack->Type() )
|
||||
{
|
||||
case PCB_VIA_T:
|
||||
{
|
||||
const float radius = ( ( aTrack->GetWidth() / 2 ) + aClearanceValue ) * m_biuTo3Dunits;
|
||||
|
||||
return new CFILLEDCIRCLE2D( start3DU, radius, *aTrack );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
wxASSERT( aTrack->Type() == PCB_TRACE_T );
|
||||
|
||||
SFVEC2F end3DU ( aTrack->GetEnd().x * m_biuTo3Dunits,
|
||||
-aTrack->GetEnd().y * m_biuTo3Dunits );
|
||||
|
||||
// Cannot add segments that have the same start and end point
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
const float radius = ((aTrack->GetWidth() / 2) + aClearanceValue) * m_biuTo3Dunits;
|
||||
|
||||
return new CFILLEDCIRCLE2D( start3DU, radius, *aTrack );
|
||||
}
|
||||
else
|
||||
{
|
||||
const float width = (aTrack->GetWidth() + 2 * aClearanceValue ) * m_biuTo3Dunits;
|
||||
|
||||
return new CROUNDSEGMENT2D( start3DU, end3DU, width, *aTrack );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// Based on:
|
||||
// void D_PAD:: TransformShapeWithClearanceToPolygon(
|
||||
// board_items_to_polygon_shape_transform.cpp
|
||||
void CINFO3D_VISU::createNewPadWithClearance( const D_PAD* aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
wxSize aClearanceValue ) const
|
||||
{
|
||||
// note: for most of shapes, aClearanceValue.x = aClearanceValue.y
|
||||
// only rectangular and oval shapes can have different values
|
||||
// when drawn on the solder paste layer, because we can have a margin that is a
|
||||
// percent of pad size
|
||||
const int dx = (aPad->GetSize().x / 2) + aClearanceValue.x;
|
||||
const int dy = (aPad->GetSize().y / 2) + aClearanceValue.y;
|
||||
|
||||
if( !dx || !dy )
|
||||
{
|
||||
wxLogTrace( m_logTrace,
|
||||
wxT( "CINFO3D_VISU::createNewPadWithClearance - found an invalid pad" ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
wxPoint PadShapePos = aPad->ShapePos(); // Note: for pad having a shape offset,
|
||||
// the pad position is NOT the shape position
|
||||
|
||||
switch( aPad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
{
|
||||
const float radius = dx * m_biuTo3Dunits;
|
||||
|
||||
const SFVEC2F center( PadShapePos.x * m_biuTo3Dunits,
|
||||
-PadShapePos.y * m_biuTo3Dunits );
|
||||
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( center, radius, *aPad ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_OVAL:
|
||||
{
|
||||
if( dx == dy )
|
||||
{
|
||||
// The segment object cannot store start and end the same position,
|
||||
// so add a circle instead
|
||||
const float radius = dx * m_biuTo3Dunits;
|
||||
|
||||
const SFVEC2F center( PadShapePos.x * m_biuTo3Dunits,
|
||||
-PadShapePos.y * m_biuTo3Dunits );
|
||||
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( center, radius, *aPad ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// An oval pad has the same shape as a segment with rounded ends
|
||||
|
||||
int iwidth;
|
||||
wxPoint shape_offset = wxPoint( 0, 0 );
|
||||
|
||||
if( dy > dx ) // Oval pad X/Y ratio for choosing translation axis
|
||||
{
|
||||
shape_offset.y = dy - dx;
|
||||
iwidth = dx * 2;
|
||||
}
|
||||
else //if( dy < dx )
|
||||
{
|
||||
shape_offset.x = dy - dx;
|
||||
iwidth = dy * 2;
|
||||
}
|
||||
|
||||
RotatePoint( &shape_offset, aPad->GetOrientation() );
|
||||
|
||||
const wxPoint start = PadShapePos - shape_offset;
|
||||
const wxPoint end = PadShapePos + shape_offset;
|
||||
|
||||
const SFVEC2F start3DU( start.x * m_biuTo3Dunits, -start.y * m_biuTo3Dunits );
|
||||
const SFVEC2F end3DU ( end.x * m_biuTo3Dunits, -end.y * m_biuTo3Dunits );
|
||||
|
||||
// Cannot add segments that have the same start and end point
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
|
||||
(iwidth / 2) * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU,
|
||||
iwidth * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_TRAPEZOID:
|
||||
case PAD_SHAPE_RECT:
|
||||
{
|
||||
// see pcbnew/board_items_to_polygon_shape_transform.cpp
|
||||
|
||||
wxPoint corners[4];
|
||||
aPad->BuildPadPolygon( corners, wxSize( 0, 0), aPad->GetOrientation() );
|
||||
|
||||
SFVEC2F corners3DU[4];
|
||||
|
||||
// Note: for pad having a shape offset,
|
||||
// the pad position is NOT the shape position
|
||||
for( unsigned int ii = 0; ii < 4; ++ii )
|
||||
{
|
||||
corners[ii] += aPad->ShapePos(); // Shift origin to position
|
||||
|
||||
corners3DU[ii] = SFVEC2F( corners[ii].x * m_biuTo3Dunits,
|
||||
-corners[ii].y * m_biuTo3Dunits );
|
||||
}
|
||||
|
||||
|
||||
// Learn more at:
|
||||
// https://lists.launchpad.net/kicad-developers/msg18729.html
|
||||
|
||||
// Add the PAD polygon
|
||||
aDstContainer->Add( new CPOLYGON4PTS2D( corners3DU[0],
|
||||
corners3DU[1],
|
||||
corners3DU[2],
|
||||
corners3DU[3],
|
||||
*aPad ) );
|
||||
|
||||
// Add the PAD contours
|
||||
// Round segments cannot have 0-length elements, so we approximate them
|
||||
// as a small circle
|
||||
for( int i = 1; i <= 4; i++ )
|
||||
{
|
||||
if( Is_segment_a_circle( corners3DU[i - 1], corners3DU[i & 3] ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( corners3DU[i - 1],
|
||||
aClearanceValue.x * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[i - 1],
|
||||
corners3DU[i & 3],
|
||||
aClearanceValue.x * 2.0f * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_ROUNDRECT:
|
||||
{
|
||||
wxSize shapesize( aPad->GetSize() );
|
||||
shapesize.x += aClearanceValue.x * 2;
|
||||
shapesize.y += aClearanceValue.y * 2;
|
||||
|
||||
int rounding_radius = aPad->GetRoundRectCornerRadius( shapesize );
|
||||
|
||||
wxPoint corners[4];
|
||||
|
||||
GetRoundRectCornerCenters( corners,
|
||||
rounding_radius,
|
||||
PadShapePos,
|
||||
shapesize,
|
||||
aPad->GetOrientation() );
|
||||
|
||||
SFVEC2F corners3DU[4];
|
||||
|
||||
for( unsigned int ii = 0; ii < 4; ++ii )
|
||||
corners3DU[ii] = SFVEC2F( corners[ii].x * m_biuTo3Dunits,
|
||||
-corners[ii].y * m_biuTo3Dunits );
|
||||
|
||||
// Add the PAD polygon (For some reason the corners need
|
||||
// to be inverted to display with the correctly orientation)
|
||||
aDstContainer->Add( new CPOLYGON4PTS2D( corners3DU[0],
|
||||
corners3DU[3],
|
||||
corners3DU[2],
|
||||
corners3DU[1],
|
||||
*aPad ) );
|
||||
|
||||
// Add the PAD contours
|
||||
// Round segments cannot have 0-length elements, so we approximate them
|
||||
// as a small circle
|
||||
for( int i = 1; i <= 4; i++ )
|
||||
{
|
||||
if( Is_segment_a_circle( corners3DU[i - 1], corners3DU[i & 3] ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( corners3DU[i - 1],
|
||||
rounding_radius * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[i - 1],
|
||||
corners3DU[i & 3],
|
||||
rounding_radius * 2.0f * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_CUSTOM:
|
||||
{
|
||||
SHAPE_POLY_SET polyList; // Will contain the pad outlines in board coordinates
|
||||
polyList.Append( aPad->GetCustomShapeAsPolygon() );
|
||||
aPad->CustomShapeAsPolygonToBoardPosition( &polyList, aPad->ShapePos(), aPad->GetOrientation() );
|
||||
|
||||
if( aClearanceValue.x )
|
||||
polyList.Inflate( aClearanceValue.x, 32 );
|
||||
|
||||
// Add the PAD polygon
|
||||
Convert_shape_line_polygon_to_triangles( polyList, *aDstContainer, m_biuTo3Dunits, *aPad );
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Based on:
|
||||
// BuildPadDrillShapePolygon
|
||||
// board_items_to_polygon_shape_transform.cpp
|
||||
COBJECT2D *CINFO3D_VISU::createNewPadDrill( const D_PAD* aPad, int aInflateValue )
|
||||
{
|
||||
wxSize drillSize = aPad->GetDrillSize();
|
||||
|
||||
if( !drillSize.x || !drillSize.y )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::createNewPadDrill - found an invalid pad" ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( drillSize.x == drillSize.y ) // usual round hole
|
||||
{
|
||||
const int radius = (drillSize.x / 2) + aInflateValue;
|
||||
|
||||
const SFVEC2F center( aPad->GetPosition().x * m_biuTo3Dunits,
|
||||
-aPad->GetPosition().y * m_biuTo3Dunits );
|
||||
|
||||
return new CFILLEDCIRCLE2D( center, radius * m_biuTo3Dunits, *aPad );
|
||||
|
||||
}
|
||||
else // Oblong hole
|
||||
{
|
||||
wxPoint start, end;
|
||||
int width;
|
||||
|
||||
aPad->GetOblongDrillGeometry( start, end, width );
|
||||
|
||||
width += aInflateValue * 2;
|
||||
start += aPad->GetPosition();
|
||||
end += aPad->GetPosition();
|
||||
|
||||
SFVEC2F start3DU( start.x * m_biuTo3Dunits,
|
||||
-start.y * m_biuTo3Dunits );
|
||||
|
||||
SFVEC2F end3DU ( end.x * m_biuTo3Dunits,
|
||||
-end.y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
return new CFILLEDCIRCLE2D( start3DU, (width / 2) * m_biuTo3Dunits, *aPad );
|
||||
}
|
||||
else
|
||||
{
|
||||
return new CROUNDSEGMENT2D( start3DU, end3DU, width * m_biuTo3Dunits, *aPad );
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// This function pretends to be like the
|
||||
// void D_PAD::BuildPadShapePolygon(
|
||||
// board_items_to_polygon_shape_transform.cpp
|
||||
void CINFO3D_VISU::createNewPad( const D_PAD* aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
wxSize aInflateValue ) const
|
||||
{
|
||||
switch( aPad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
case PAD_SHAPE_OVAL:
|
||||
case PAD_SHAPE_ROUNDRECT:
|
||||
case PAD_SHAPE_CUSTOM:
|
||||
createNewPadWithClearance( aPad, aDstContainer, aInflateValue );
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_TRAPEZOID:
|
||||
case PAD_SHAPE_RECT:
|
||||
wxPoint corners[4];
|
||||
aPad->BuildPadPolygon( corners, aInflateValue, aPad->GetOrientation() );
|
||||
|
||||
// Note: for pad having a shape offset,
|
||||
// the pad position is NOT the shape position
|
||||
for( unsigned int ii = 0; ii < 4; ++ii )
|
||||
corners[ii] += aPad->ShapePos(); // Shift origin to position
|
||||
|
||||
aDstContainer->Add( new CPOLYGON4PTS2D(
|
||||
SFVEC2F( corners[0].x * m_biuTo3Dunits,
|
||||
-corners[0].y * m_biuTo3Dunits ),
|
||||
SFVEC2F( corners[1].x * m_biuTo3Dunits,
|
||||
-corners[1].y * m_biuTo3Dunits ),
|
||||
SFVEC2F( corners[2].x * m_biuTo3Dunits,
|
||||
-corners[2].y * m_biuTo3Dunits ),
|
||||
SFVEC2F( corners[3].x * m_biuTo3Dunits,
|
||||
-corners[3].y * m_biuTo3Dunits ),
|
||||
*aPad ) );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::AddPadsShapesWithClearanceToContainer( const MODULE* aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper )
|
||||
{
|
||||
const D_PAD* pad = aModule->PadsList();
|
||||
|
||||
wxSize margin;
|
||||
|
||||
for( ; pad != NULL; pad = pad->Next() )
|
||||
{
|
||||
if( !pad->IsOnLayer( aLayerId ) )
|
||||
continue;
|
||||
|
||||
// NPTH pads are not drawn on layers if the
|
||||
// shape size and pos is the same as their hole:
|
||||
if( aSkipNPTHPadsWihNoCopper && (pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED) )
|
||||
{
|
||||
if( (pad->GetDrillSize() == pad->GetSize()) &&
|
||||
(pad->GetOffset() == wxPoint( 0, 0 )) )
|
||||
{
|
||||
switch( pad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_OVAL:
|
||||
if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( aLayerId )
|
||||
{
|
||||
case F_Mask:
|
||||
case B_Mask:
|
||||
margin.x = margin.y = pad->GetSolderMaskMargin() + aInflateValue;
|
||||
break;
|
||||
|
||||
case F_Paste:
|
||||
case B_Paste:
|
||||
margin = pad->GetSolderPasteMargin();
|
||||
margin.x += aInflateValue;
|
||||
margin.y += aInflateValue;
|
||||
break;
|
||||
|
||||
default:
|
||||
margin.x = margin.y = aInflateValue;
|
||||
break;
|
||||
}
|
||||
|
||||
createNewPad( pad, aDstContainer, margin );
|
||||
}
|
||||
}
|
||||
|
||||
// based on TransformArcToPolygon function from
|
||||
// common/convert_basic_shapes_to_polygon.cpp
|
||||
void CINFO3D_VISU::TransformArcToSegments( const wxPoint &aCentre,
|
||||
const wxPoint &aStart,
|
||||
double aArcAngle,
|
||||
int aCircleToSegmentsCount,
|
||||
int aWidth,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
const BOARD_ITEM &aBoardItem )
|
||||
{
|
||||
wxPoint arc_start, arc_end;
|
||||
int delta = 3600 / aCircleToSegmentsCount; // rotate angle in 0.1 degree
|
||||
|
||||
arc_end = arc_start = aStart;
|
||||
|
||||
if( aArcAngle != 3600 )
|
||||
{
|
||||
RotatePoint( &arc_end, aCentre, -aArcAngle );
|
||||
}
|
||||
|
||||
if( aArcAngle < 0 )
|
||||
{
|
||||
std::swap( arc_start, arc_end );
|
||||
aArcAngle = -aArcAngle;
|
||||
}
|
||||
|
||||
// Compute the ends of segments and creates poly
|
||||
wxPoint curr_end = arc_start;
|
||||
wxPoint curr_start = arc_start;
|
||||
|
||||
for( int ii = delta; ii < aArcAngle; ii += delta )
|
||||
{
|
||||
curr_end = arc_start;
|
||||
RotatePoint( &curr_end, aCentre, -ii );
|
||||
|
||||
const SFVEC2F start3DU( curr_start.x * m_biuTo3Dunits, -curr_start.y * m_biuTo3Dunits );
|
||||
const SFVEC2F end3DU ( curr_end.x * m_biuTo3Dunits, -curr_end.y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
|
||||
( aWidth / 2 ) * m_biuTo3Dunits,
|
||||
aBoardItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
|
||||
end3DU,
|
||||
aWidth * m_biuTo3Dunits,
|
||||
aBoardItem ) );
|
||||
}
|
||||
|
||||
curr_start = curr_end;
|
||||
}
|
||||
|
||||
if( curr_end != arc_end )
|
||||
{
|
||||
const SFVEC2F start3DU( curr_end.x * m_biuTo3Dunits, -curr_end.y * m_biuTo3Dunits );
|
||||
const SFVEC2F end3DU ( arc_end.x * m_biuTo3Dunits, -arc_end.y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
|
||||
( aWidth / 2 ) * m_biuTo3Dunits,
|
||||
aBoardItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
|
||||
end3DU,
|
||||
aWidth * m_biuTo3Dunits,
|
||||
aBoardItem ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Based on
|
||||
// TransformShapeWithClearanceToPolygon
|
||||
// board_items_to_polygon_shape_transform.cpp#L431
|
||||
void CINFO3D_VISU::AddShapeWithClearanceToContainer( const DRAWSEGMENT* aDrawSegment,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue )
|
||||
{
|
||||
// The full width of the lines to create
|
||||
// The extra 1 protects the inner/outer radius values from degeneracy
|
||||
const int linewidth = aDrawSegment->GetWidth() + (2 * aClearanceValue) + 1;
|
||||
|
||||
switch( aDrawSegment->GetShape() )
|
||||
{
|
||||
case S_CIRCLE:
|
||||
{
|
||||
const SFVEC2F center3DU( aDrawSegment->GetCenter().x * m_biuTo3Dunits,
|
||||
-aDrawSegment->GetCenter().y * m_biuTo3Dunits );
|
||||
|
||||
const float inner_radius = (aDrawSegment->GetRadius() - linewidth / 2) * m_biuTo3Dunits;
|
||||
const float outter_radius = (aDrawSegment->GetRadius() + linewidth / 2) * m_biuTo3Dunits;
|
||||
|
||||
aDstContainer->Add( new CRING2D( center3DU,
|
||||
inner_radius,
|
||||
outter_radius,
|
||||
*aDrawSegment ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case S_ARC:
|
||||
{
|
||||
const unsigned int nr_segments =
|
||||
GetNrSegmentsCircle( aDrawSegment->GetBoundingBox().GetSizeMax() );
|
||||
|
||||
TransformArcToSegments( aDrawSegment->GetCenter(),
|
||||
aDrawSegment->GetArcStart(),
|
||||
aDrawSegment->GetAngle(),
|
||||
nr_segments,
|
||||
aDrawSegment->GetWidth(),
|
||||
aDstContainer,
|
||||
*aDrawSegment );
|
||||
}
|
||||
break;
|
||||
|
||||
case S_SEGMENT:
|
||||
{
|
||||
const SFVEC2F start3DU( aDrawSegment->GetStart().x * m_biuTo3Dunits,
|
||||
-aDrawSegment->GetStart().y * m_biuTo3Dunits );
|
||||
|
||||
const SFVEC2F end3DU ( aDrawSegment->GetEnd().x * m_biuTo3Dunits,
|
||||
-aDrawSegment->GetEnd().y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
|
||||
( linewidth / 2 ) * m_biuTo3Dunits,
|
||||
*aDrawSegment ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
|
||||
end3DU,
|
||||
linewidth * m_biuTo3Dunits,
|
||||
*aDrawSegment ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case S_POLYGON:
|
||||
{
|
||||
const int segcountforcircle = 16;
|
||||
const double correctionFactor = GetCircleCorrectionFactor( segcountforcircle );
|
||||
SHAPE_POLY_SET polyList;
|
||||
|
||||
aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aClearanceValue,
|
||||
segcountforcircle, correctionFactor );
|
||||
|
||||
polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
if( polyList.IsEmpty() ) // Just for caution
|
||||
break;
|
||||
|
||||
Convert_shape_line_polygon_to_triangles( polyList, *aDstContainer,
|
||||
m_biuTo3Dunits, *aDrawSegment );
|
||||
}
|
||||
break;
|
||||
|
||||
case S_CURVE: // Bezier curve (not yet in use in KiCad)
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Based on
|
||||
// TransformSolidAreasShapesToPolygonSet
|
||||
// board_items_to_polygon_shape_transform.cpp
|
||||
void CINFO3D_VISU::AddSolidAreasShapesToContainer( const ZONE_CONTAINER* aZoneContainer,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId )
|
||||
{
|
||||
// Copy the polys list because we have to simplify it
|
||||
SHAPE_POLY_SET polyList = SHAPE_POLY_SET( aZoneContainer->GetFilledPolysList(), true );
|
||||
|
||||
// This convert the poly in outline and holes
|
||||
Convert_shape_line_polygon_to_triangles( polyList,
|
||||
*aDstContainer,
|
||||
m_biuTo3Dunits,
|
||||
*aZoneContainer );
|
||||
|
||||
// add filled areas outlines, which are drawn with thick lines segments
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
for( int i = 0; i < polyList.OutlineCount(); ++i )
|
||||
{
|
||||
// Add outline
|
||||
const SHAPE_LINE_CHAIN& pathOutline = polyList.COutline( i );
|
||||
|
||||
for( int j = 0; j < pathOutline.PointCount(); ++j )
|
||||
{
|
||||
const VECTOR2I& a = pathOutline.CPoint( j );
|
||||
const VECTOR2I& b = pathOutline.CPoint( j + 1 );
|
||||
|
||||
SFVEC2F start3DU( a.x * m_biuTo3Dunits, -a.y * m_biuTo3Dunits );
|
||||
SFVEC2F end3DU ( b.x * m_biuTo3Dunits, -b.y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
float radius = (aZoneContainer->GetMinThickness() / 2) * m_biuTo3Dunits;
|
||||
|
||||
if( radius > 0.0 ) // degenerated circles crash 3D viewer
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU, radius ,
|
||||
*aZoneContainer ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU,
|
||||
aZoneContainer->GetMinThickness() *
|
||||
m_biuTo3Dunits,
|
||||
*aZoneContainer ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Add holes (of the poly, ie: the open parts) for this outline
|
||||
for( int h = 0; h < polyList.HoleCount( i ); ++h )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN& pathHole = polyList.CHole( i, h );
|
||||
|
||||
for( int j = 0; j < pathHole.PointCount(); j++ )
|
||||
{
|
||||
const VECTOR2I& a = pathHole.CPoint( j );
|
||||
const VECTOR2I& b = pathHole.CPoint( j + 1 );
|
||||
|
||||
SFVEC2F start3DU( a.x * m_biuTo3Dunits, -a.y * m_biuTo3Dunits );
|
||||
SFVEC2F end3DU ( b.x * m_biuTo3Dunits, -b.y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
float radius = (aZoneContainer->GetMinThickness() / 2) * m_biuTo3Dunits;
|
||||
|
||||
if( radius > 0.0 ) // degenerated circles crash 3D viewer
|
||||
aDstContainer->Add(
|
||||
new CFILLEDCIRCLE2D( start3DU, radius,
|
||||
*aZoneContainer ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add(
|
||||
new CROUNDSEGMENT2D( start3DU, end3DU,
|
||||
aZoneContainer->GetMinThickness() *
|
||||
m_biuTo3Dunits,
|
||||
*aZoneContainer ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CINFO3D_VISU::buildPadShapeThickOutlineAsSegments( const D_PAD* aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
int aWidth )
|
||||
{
|
||||
if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring
|
||||
{
|
||||
const SFVEC2F center3DU( aPad->ShapePos().x * m_biuTo3Dunits,
|
||||
-aPad->ShapePos().y * m_biuTo3Dunits );
|
||||
|
||||
const int radius = aPad->GetSize().x / 2;
|
||||
const float inner_radius = (radius - aWidth / 2) * m_biuTo3Dunits;
|
||||
const float outter_radius = (radius + aWidth / 2) * m_biuTo3Dunits;
|
||||
|
||||
aDstContainer->Add( new CRING2D( center3DU,
|
||||
inner_radius,
|
||||
outter_radius,
|
||||
*aPad ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// For other shapes, draw polygon outlines
|
||||
SHAPE_POLY_SET corners;
|
||||
|
||||
const int segcountforcircle = GetNrSegmentsCircle( glm::min( aPad->GetSize().x,
|
||||
aPad->GetSize().y) );
|
||||
|
||||
const double correctionFactor = GetCircleCorrectionFactor( segcountforcircle );
|
||||
|
||||
aPad->BuildPadShapePolygon( corners, wxSize( 0, 0 ),
|
||||
// This two factors are only expected to be used if render an oval
|
||||
segcountforcircle, correctionFactor );
|
||||
|
||||
|
||||
// Add outlines as thick segments in polygon buffer
|
||||
|
||||
const SHAPE_LINE_CHAIN& path = corners.COutline( 0 );
|
||||
|
||||
for( int j = 0; j < path.PointCount(); j++ )
|
||||
{
|
||||
const VECTOR2I& a = path.CPoint( j );
|
||||
const VECTOR2I& b = path.CPoint( j + 1 );
|
||||
|
||||
SFVEC2F start3DU( a.x * m_biuTo3Dunits, -a.y * m_biuTo3Dunits );
|
||||
SFVEC2F end3DU ( b.x * m_biuTo3Dunits, -b.y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
|
||||
(aWidth / 2) * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU,
|
||||
aWidth * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file create_layer_poly.cpp
|
||||
* @brief This file implements the creation of the pcb board items in the poly
|
||||
* contours format. It is based on the function found in the files:
|
||||
* board_items_to_polygon_shape_transform.cpp
|
||||
* board_items_to_polygon_shape_transform.cpp
|
||||
*/
|
||||
|
||||
#include "cinfo3d_visu.h"
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <class_edge_mod.h>
|
||||
#include <class_module.h>
|
||||
|
||||
|
||||
// This is the same function as in board_items_to_polygon_shape_transform.cpp
|
||||
// but it adds the rect/trapezoid shapes with a different winding
|
||||
void CINFO3D_VISU::buildPadShapePolygon( const D_PAD* aPad,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
wxSize aInflateValue,
|
||||
int aSegmentsPerCircle,
|
||||
double aCorrectionFactor ) const
|
||||
{
|
||||
wxPoint corners[4];
|
||||
wxPoint PadShapePos = aPad->ShapePos(); /* Note: for pad having a shape offset,
|
||||
* the pad position is NOT the shape position */
|
||||
switch( aPad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
case PAD_SHAPE_OVAL:
|
||||
case PAD_SHAPE_ROUNDRECT:
|
||||
{
|
||||
// We are using TransformShapeWithClearanceToPolygon to build the shape.
|
||||
// Currently, this method uses only the same inflate value for X and Y dirs.
|
||||
// so because here this is not the case, we use a inflated dummy pad to build
|
||||
// the polygonal shape
|
||||
// TODO: remove this dummy pad when TransformShapeWithClearanceToPolygon will use
|
||||
// a wxSize to inflate the pad size
|
||||
D_PAD dummy( *aPad );
|
||||
wxSize new_size = aPad->GetSize() + aInflateValue + aInflateValue;
|
||||
dummy.SetSize( new_size );
|
||||
dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, 0,
|
||||
aSegmentsPerCircle, aCorrectionFactor );
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_TRAPEZOID:
|
||||
case PAD_SHAPE_RECT:
|
||||
{
|
||||
SHAPE_LINE_CHAIN aLineChain;
|
||||
|
||||
aPad->BuildPadPolygon( corners, aInflateValue, aPad->GetOrientation() );
|
||||
|
||||
for( int ii = 0; ii < 4; ++ii )
|
||||
{
|
||||
corners[3-ii] += PadShapePos; // Shift origin to position
|
||||
aLineChain.Append( corners[3-ii].x, corners[3-ii].y );
|
||||
}
|
||||
|
||||
aLineChain.SetClosed( true );
|
||||
|
||||
aCornerBuffer.AddOutline( aLineChain );
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_CUSTOM:
|
||||
{
|
||||
SHAPE_POLY_SET polyList; // Will contain the pad outlines in board coordinates
|
||||
polyList.Append( aPad->GetCustomShapeAsPolygon() );
|
||||
aPad->CustomShapeAsPolygonToBoardPosition( &polyList, aPad->ShapePos(), aPad->GetOrientation() );
|
||||
aCornerBuffer.Append( polyList );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aWidth ) const
|
||||
{
|
||||
if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring
|
||||
{
|
||||
unsigned int nr_sides_per_circle = GetNrSegmentsCircle( ( aPad->GetSize().x / 2 +
|
||||
aWidth / 2 ) * 2 );
|
||||
|
||||
TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(),
|
||||
aPad->GetSize().x / 2, nr_sides_per_circle, aWidth );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// For other shapes, draw polygon outlines
|
||||
SHAPE_POLY_SET corners;
|
||||
|
||||
unsigned int nr_sides_per_circle = GetNrSegmentsCircle( glm::min( aPad->GetSize().x,
|
||||
aPad->GetSize().y) );
|
||||
buildPadShapePolygon( aPad, corners, wxSize( 0, 0 ),
|
||||
nr_sides_per_circle,
|
||||
GetCircleCorrectionFactor( nr_sides_per_circle ) );
|
||||
|
||||
// Add outlines as thick segments in polygon buffer
|
||||
|
||||
const SHAPE_LINE_CHAIN& path = corners.COutline( 0 );
|
||||
|
||||
for( int ii = 0; ii < path.PointCount(); ++ii )
|
||||
{
|
||||
const VECTOR2I& a = path.CPoint( ii );
|
||||
const VECTOR2I& b = path.CPoint( ii + 1 );
|
||||
|
||||
TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
|
||||
wxPoint( a.x, a.y ),
|
||||
wxPoint( b.x, b.y ),
|
||||
nr_sides_per_circle,
|
||||
aWidth );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Based on the same function name in board_items_to_polyshape_transform.cpp
|
||||
// It was implemented here to allow dynamic segments count per pad shape
|
||||
void CINFO3D_VISU::transformPadsShapesWithClearanceToPolygon( const DLIST<D_PAD>& aPads, PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper ) const
|
||||
{
|
||||
const D_PAD* pad = aPads;
|
||||
|
||||
wxSize margin;
|
||||
for( ; pad != NULL; pad = pad->Next() )
|
||||
{
|
||||
if( !pad->IsOnLayer(aLayer) )
|
||||
continue;
|
||||
|
||||
// NPTH pads are not drawn on layers if the shape size and pos is the same
|
||||
// as their hole:
|
||||
if( aSkipNPTHPadsWihNoCopper && (pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED) )
|
||||
{
|
||||
if( (pad->GetDrillSize() == pad->GetSize()) &&
|
||||
(pad->GetOffset() == wxPoint( 0, 0 )) )
|
||||
{
|
||||
switch( pad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_OVAL:
|
||||
if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( aLayer )
|
||||
{
|
||||
case F_Mask:
|
||||
case B_Mask:
|
||||
margin.x = margin.y = pad->GetSolderMaskMargin() + aInflateValue;
|
||||
break;
|
||||
|
||||
case F_Paste:
|
||||
case B_Paste:
|
||||
margin = pad->GetSolderPasteMargin();
|
||||
margin.x += aInflateValue;
|
||||
margin.y += aInflateValue;
|
||||
break;
|
||||
|
||||
default:
|
||||
margin.x = margin.y = aInflateValue;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int aCircleToSegmentsCount = GetNrSegmentsCircle( pad->GetSize().x );
|
||||
double aCorrectionFactor = GetCircleCorrectionFactor( aCircleToSegmentsCount );
|
||||
|
||||
buildPadShapePolygon( pad, aCornerBuffer, margin,
|
||||
aCircleToSegmentsCount, aCorrectionFactor );
|
||||
}
|
||||
}
|
||||
|
||||
void CINFO3D_VISU::transformGraphicModuleEdgeToPolygonSet( const MODULE *aModule,
|
||||
PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer ) const
|
||||
{
|
||||
for( const EDA_ITEM* item = aModule->GraphicalItemsList();
|
||||
item != NULL;
|
||||
item = item->Next() )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_MODULE_EDGE_T:
|
||||
{
|
||||
EDGE_MODULE*outline = (EDGE_MODULE*) item;
|
||||
|
||||
if( outline->GetLayer() != aLayer )
|
||||
break;
|
||||
|
||||
unsigned int aCircleToSegmentsCount =
|
||||
GetNrSegmentsCircle( outline->GetBoundingBox().GetSizeMax() );
|
||||
|
||||
double aCorrectionFactor = GetCircleCorrectionFactor( aCircleToSegmentsCount );
|
||||
|
||||
outline->TransformShapeWithClearanceToPolygon( aCornerBuffer,
|
||||
0,
|
||||
aCircleToSegmentsCount,
|
||||
aCorrectionFactor );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,283 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eda_3d_canvas.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef EDA_3D_CANVAS_H
|
||||
#define EDA_3D_CANVAS_H
|
||||
|
||||
|
||||
#include "cinfo3d_visu.h"
|
||||
#include "3d_rendering/c3d_render_base.h"
|
||||
#include "3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h"
|
||||
#include "3d_rendering/3d_render_raytracing/c3d_render_raytracing.h"
|
||||
#include "3d_cache/3d_cache.h"
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/dataobj.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/statusbr.h>
|
||||
#include <pcb_base_frame.h>
|
||||
|
||||
|
||||
/**
|
||||
* Class EDA_3D_CANVAS
|
||||
* Implement a canvas based on a wxGLCanvas
|
||||
*/
|
||||
class EDA_3D_CANVAS : public HIDPI_GL_CANVAS
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* @brief EDA_3D_CANVAS - Creates a new 3D Canvas with a attribute list
|
||||
* @param aParent: the parent creator of this canvas
|
||||
* @param aAttribList: a list of openGL options created by GetOpenGL_AttributesList
|
||||
* @param aBoard: The board
|
||||
* @param aSettings: the settings options to be used by this canvas
|
||||
*/
|
||||
EDA_3D_CANVAS( wxWindow *aParent,
|
||||
const int *aAttribList = 0,
|
||||
BOARD *aBoard = NULL,
|
||||
CINFO3D_VISU &aSettings = G_null_CINFO3D_VISU,
|
||||
S3D_CACHE *a3DCachePointer = NULL );
|
||||
|
||||
~EDA_3D_CANVAS();
|
||||
|
||||
void SetStatusBar( wxStatusBar *aStatusBar ) { m_parentStatusBar = aStatusBar; }
|
||||
|
||||
void ReloadRequest( BOARD *aBoard = NULL, S3D_CACHE *aCachePointer = NULL );
|
||||
|
||||
/**
|
||||
* @brief IsReloadRequestPending - Query if there is a pending reload request
|
||||
* @return true if it wants to reload, false if there is no reload pending
|
||||
*/
|
||||
bool IsReloadRequestPending() const
|
||||
{
|
||||
if( m_3d_render )
|
||||
return m_3d_render->IsReloadRequestPending();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RenderRaytracingRequest - Request to render the current view in Raytracing mode
|
||||
*/
|
||||
void RenderRaytracingRequest();
|
||||
|
||||
/**
|
||||
* Request a screenshot and output it to the aDstImage
|
||||
* @param aDstImage - Screenshot destination image
|
||||
*/
|
||||
void GetScreenshot( wxImage &aDstImage );
|
||||
|
||||
/**
|
||||
* @brief SetView3D - Helper function to call view commands
|
||||
* @param aKeycode: ascii key commands
|
||||
* @return true if the key code was handled,
|
||||
* false if no command found for this code.
|
||||
*/
|
||||
bool SetView3D( int aKeycode );
|
||||
|
||||
/**
|
||||
* @brief RenderEngineChanged - Notify that the render engine was changed
|
||||
*/
|
||||
void RenderEngineChanged();
|
||||
|
||||
/**
|
||||
* @brief DisplayStatus - Update the status bar with the position information
|
||||
*/
|
||||
void DisplayStatus();
|
||||
|
||||
/**
|
||||
* @brief Request_refresh - Schedule a refresh update of the canvas
|
||||
* @param aRedrawImmediately - true will request a redraw, false will
|
||||
* schedule a redraw, after a short timeout.
|
||||
*/
|
||||
void Request_refresh( bool aRedrawImmediately = true );
|
||||
|
||||
void OnKeyEvent( wxKeyEvent& event );
|
||||
|
||||
private:
|
||||
|
||||
void OnPaint( wxPaintEvent &event );
|
||||
|
||||
void OnEraseBackground( wxEraseEvent &event );
|
||||
|
||||
void OnMouseWheel( wxMouseEvent &event );
|
||||
|
||||
#if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
#endif
|
||||
|
||||
void OnMouseMove( wxMouseEvent &event );
|
||||
|
||||
void OnLeftDown( wxMouseEvent &event );
|
||||
|
||||
void OnLeftUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleDown( wxMouseEvent &event );
|
||||
|
||||
void OnRightClick( wxMouseEvent &event );
|
||||
|
||||
void OnPopUpMenu( wxCommandEvent &event );
|
||||
|
||||
void OnCharHook( wxKeyEvent& event );
|
||||
|
||||
void OnTimerTimeout_Editing( wxTimerEvent& event );
|
||||
|
||||
/**
|
||||
* @brief OnCloseWindow - called when the frame is closed
|
||||
* @param event
|
||||
*/
|
||||
void OnCloseWindow( wxCloseEvent &event );
|
||||
|
||||
void OnResize( wxSizeEvent &event );
|
||||
|
||||
void OnTimerTimeout_Redraw( wxTimerEvent& event );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief stop_editingTimeOut_Timer - stop the editing time, so it will not timeout
|
||||
*/
|
||||
void stop_editingTimeOut_Timer();
|
||||
|
||||
|
||||
/**
|
||||
* @brief restart_editingTimeOut_Timer - reset the editing timer
|
||||
*/
|
||||
void restart_editingTimeOut_Timer();
|
||||
|
||||
|
||||
/**
|
||||
* @brief request_start_moving_camera - start a camera movement
|
||||
* @param aMovingSpeed: the time speed
|
||||
* @param aRenderPivot: if it should display pivot cursor while move
|
||||
*/
|
||||
void request_start_moving_camera( float aMovingSpeed = 2.0f,
|
||||
bool aRenderPivot = true );
|
||||
|
||||
|
||||
/**
|
||||
* @brief move_pivot_based_on_cur_mouse_position -
|
||||
* This function hits a ray to the board and start a moviment
|
||||
*/
|
||||
void move_pivot_based_on_cur_mouse_position();
|
||||
|
||||
|
||||
/**
|
||||
* @brief render_pivot - render the pivot cursor
|
||||
* @param t: time between 0.0 and 1.0
|
||||
* @param aScale: scale to apply on the cursor
|
||||
*/
|
||||
void render_pivot( float t, float aScale );
|
||||
|
||||
/**
|
||||
* @brief initializeOpenGL
|
||||
* @return if OpenGL initialization succeed
|
||||
*/
|
||||
bool initializeOpenGL();
|
||||
|
||||
/**
|
||||
* @brief releaseOpenGL - free created targets and openGL context
|
||||
*/
|
||||
void releaseOpenGL();
|
||||
|
||||
private:
|
||||
|
||||
/// current OpenGL context
|
||||
wxGLContext *m_glRC;
|
||||
|
||||
/// Parent statusbar to report progress
|
||||
wxStatusBar *m_parentStatusBar;
|
||||
|
||||
/// Time timeout will expires after some time sinalizing that the mouse /
|
||||
/// keyboard movements are over.
|
||||
wxTimer m_editing_timeout_timer;
|
||||
|
||||
/// This timer will be used to schedule a redraw event
|
||||
wxTimer m_redraw_trigger_timer;
|
||||
|
||||
/// true if mouse activity is on progress
|
||||
bool m_mouse_is_moving;
|
||||
|
||||
/// true if there was some type of activity, it will be used to render in
|
||||
/// preview mode
|
||||
bool m_mouse_was_moved;
|
||||
|
||||
/// true if camera animation is ongoing
|
||||
bool m_camera_is_moving;
|
||||
|
||||
/// activated the render of pivot while camera moving
|
||||
bool m_render_pivot;
|
||||
|
||||
/// 1.0f will be 1:1
|
||||
float m_camera_moving_speed;
|
||||
|
||||
/// Stores the ticktime when the camera star its movement
|
||||
unsigned m_strtime_camera_movement;
|
||||
|
||||
/// Stores all pre-computed 3D information and visualization settings to render the board
|
||||
CINFO3D_VISU &m_settings;
|
||||
|
||||
/// The current render in used for this canvas
|
||||
C3D_RENDER_BASE *m_3d_render;
|
||||
|
||||
/// Raytracing render class
|
||||
C3D_RENDER_RAYTRACING *m_3d_render_raytracing;
|
||||
|
||||
/// OpenGL legacy render class
|
||||
C3D_RENDER_OGL_LEGACY *m_3d_render_ogl_legacy;
|
||||
|
||||
/// Flag to store if opengl was initialized already
|
||||
bool m_is_opengl_initialized;
|
||||
|
||||
/// Step factor to used with cursor on relation to the current zoom
|
||||
static const float m_delta_move_step_factor;
|
||||
|
||||
/// Flags that the user requested the current view to be render with raytracing
|
||||
bool m_render_raytracing_was_requested;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_3D_CANVAS". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar *m_logTrace;
|
||||
};
|
||||
|
||||
|
||||
#endif // EDA_3D_CANVAS_H
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eda_3d_canvas_pivot.cpp
|
||||
* @brief Implementation of a 3d cursor
|
||||
*/
|
||||
|
||||
#include "../common_ogl/openGL_includes.h"
|
||||
#include "../common_ogl/ogl_utils.h"
|
||||
#include "eda_3d_canvas.h"
|
||||
|
||||
|
||||
static void pivot_render_triangles( float t )
|
||||
{
|
||||
wxASSERT( t >= 0.0f );
|
||||
|
||||
SFVEC3F vertexPointer[12];
|
||||
|
||||
const float u = 1.0f / 6.0f;
|
||||
|
||||
vertexPointer[0] = SFVEC3F( (-3.0f + t) * u, -2.0f * u, 0.0f );
|
||||
vertexPointer[1] = SFVEC3F( (-3.0f + t) * u, 2.0f * u, 0.0f );
|
||||
vertexPointer[2] = SFVEC3F( (-1.0f + t) * u, 0.0f * u, 0.0f );
|
||||
|
||||
vertexPointer[3] = SFVEC3F( -2.0f * u, (-3.0f + t) * u, 0.0f );
|
||||
vertexPointer[4] = SFVEC3F( 2.0f * u, (-3.0f + t) * u, 0.0f );
|
||||
vertexPointer[5] = SFVEC3F( 0.0f * u, (-1.0f + t) * u, 0.0f );
|
||||
|
||||
vertexPointer[6] = SFVEC3F( (3.0f - t) * u, -2.0f * u, 0.0f );
|
||||
vertexPointer[7] = SFVEC3F( (3.0f - t) * u, 2.0f * u, 0.0f );
|
||||
vertexPointer[8] = SFVEC3F( (1.0f - t) * u, 0.0f * u, 0.0f );
|
||||
|
||||
vertexPointer[9] = SFVEC3F( 2.0f * u, (3.0f - t) * u, 0.0f );
|
||||
vertexPointer[10] = SFVEC3F( -2.0f * u, (3.0f - t) * u, 0.0f );
|
||||
vertexPointer[11] = SFVEC3F( 0.0f * u, (1.0f - t) * u, 0.0f );
|
||||
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glDisableClientState( GL_NORMAL_ARRAY );
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glVertexPointer( 3, GL_FLOAT, 0, vertexPointer );
|
||||
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
glDrawArrays( GL_TRIANGLES, 0, 4 * 3 );
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::render_pivot( float t , float aScale )
|
||||
{
|
||||
wxASSERT( aScale >= 0.0f );
|
||||
wxASSERT( t >= 0.0f );
|
||||
|
||||
if( t > 1.0f )
|
||||
t = 1.0f;
|
||||
|
||||
const SFVEC3F &lookAtPos = m_settings.CameraGet().GetLookAtPos_T1();
|
||||
|
||||
glDisable( GL_LIGHTING );
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_CULL_FACE );
|
||||
|
||||
// Set projection and modelview matrixes
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadMatrixf( glm::value_ptr( m_settings.CameraGet().GetProjectionMatrix() ) );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
glLoadMatrixf( glm::value_ptr( m_settings.CameraGet().GetViewMatrix() ) );
|
||||
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColor4f( 0.0f, 1.0f, 0.0f, 0.75f - t * 0.75f );
|
||||
|
||||
// Translate to the look at position
|
||||
glTranslatef( lookAtPos.x, lookAtPos.y, lookAtPos.z );
|
||||
|
||||
glScalef( aScale, aScale, aScale );
|
||||
|
||||
pivot_render_triangles( t * 0.5f );
|
||||
|
||||
t = t * 0.80f;
|
||||
glScalef( 1.0f - t, 1.0f - t, 1.0f - t );
|
||||
glColor4f( 0.0f, 1.0f, 0.0f, 0.8f - t );
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef( t * 90.0f, 0.0f, 0.0f, 1.0f );
|
||||
pivot_render_triangles( t * 0.5f );
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef( -t * 90.0f, 0.0f, 0.0f, 1.0f );
|
||||
pivot_render_triangles( t * 0.5f );
|
||||
glPopMatrix();
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file status_text_reporter.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef STATUS_TEXT_REPORTER_H_
|
||||
#define STATUS_TEXT_REPORTER_H_
|
||||
|
||||
#include <reporter.h>
|
||||
|
||||
/**
|
||||
* Class STATUS_TEXT_REPORTER
|
||||
* is a wrapper for reporting to a wxString in a wxFrame status text.
|
||||
*/
|
||||
class STATUS_TEXT_REPORTER : public REPORTER
|
||||
{
|
||||
private:
|
||||
wxStatusBar *m_parentStatusBar;
|
||||
int m_position;
|
||||
bool m_hasMessage;
|
||||
|
||||
public:
|
||||
STATUS_TEXT_REPORTER( wxStatusBar* aParentStatusBar, int aPosition = 0 ) :
|
||||
REPORTER(),
|
||||
m_parentStatusBar( aParentStatusBar ), m_position( aPosition )
|
||||
{
|
||||
m_hasMessage = false;
|
||||
}
|
||||
|
||||
REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_UNDEFINED ) override
|
||||
{
|
||||
if( !aText.IsEmpty() )
|
||||
m_hasMessage = true;
|
||||
|
||||
if( m_parentStatusBar )
|
||||
m_parentStatusBar->SetStatusText( aText, m_position );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HasMessage() const override { return m_hasMessage; }
|
||||
};
|
||||
|
||||
|
||||
#endif // STATUS_TEXT_REPORTER_H_
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_class.cpp
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
|
||||
#include "3d_viewer.h"
|
||||
#include "3d_struct.h"
|
||||
#include "modelparsers.h"
|
||||
|
||||
|
||||
void S3D_MASTER::Insert( S3D_MATERIAL* aMaterial )
|
||||
{
|
||||
aMaterial->SetNext( m_Materials );
|
||||
m_Materials = aMaterial;
|
||||
}
|
||||
|
||||
|
||||
void S3D_MASTER::Copy( S3D_MASTER* pattern )
|
||||
{
|
||||
SetShape3DName( pattern->GetShape3DName() );
|
||||
m_MatScale = pattern->m_MatScale;
|
||||
m_MatRotation = pattern->m_MatRotation;
|
||||
m_MatPosition = pattern->m_MatPosition;
|
||||
m_3D_Drawings = NULL;
|
||||
m_Materials = NULL;
|
||||
}
|
||||
|
||||
|
||||
S3D_MASTER::S3D_MASTER( EDA_ITEM* aParent ) :
|
||||
EDA_ITEM( aParent, NOT_USED )
|
||||
{
|
||||
m_MatScale.x = m_MatScale.y = m_MatScale.z = 1.0;
|
||||
|
||||
m_3D_Drawings = NULL;
|
||||
m_Materials = NULL;
|
||||
m_parser = NULL;
|
||||
m_ShapeType = FILE3D_NONE;
|
||||
|
||||
m_use_modelfile_diffuseColor = true;
|
||||
m_use_modelfile_emissiveColor = true;
|
||||
m_use_modelfile_specularColor = true;
|
||||
m_use_modelfile_ambientIntensity = true;
|
||||
m_use_modelfile_transparency = true;
|
||||
m_use_modelfile_shininess = true;
|
||||
}
|
||||
|
||||
|
||||
S3D_MASTER:: ~S3D_MASTER()
|
||||
{
|
||||
STRUCT_3D_SHAPE* next;
|
||||
S3D_MATERIAL* nextmat;
|
||||
|
||||
for( ; m_3D_Drawings != NULL; m_3D_Drawings = next )
|
||||
{
|
||||
next = m_3D_Drawings->Next();
|
||||
delete m_3D_Drawings;
|
||||
m_3D_Drawings = 0;
|
||||
}
|
||||
|
||||
for( ; m_Materials != NULL; m_Materials = nextmat )
|
||||
{
|
||||
nextmat = m_Materials->Next();
|
||||
delete m_Materials;
|
||||
m_Materials = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool S3D_MASTER::Is3DType( enum FILE3D_TYPE aShapeType )
|
||||
{
|
||||
// type 'none' is not valid and will always return false
|
||||
if( aShapeType == FILE3D_NONE )
|
||||
return false;
|
||||
|
||||
// no one is interested if we have no file
|
||||
if( m_Shape3DName.empty() )
|
||||
return false;
|
||||
|
||||
if( aShapeType == m_ShapeType )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void S3D_MASTER::SetShape3DName( const wxString& aShapeName )
|
||||
{
|
||||
m_ShapeType = FILE3D_NONE;
|
||||
m_Shape3DName = aShapeName;
|
||||
|
||||
if( m_Shape3DName.empty() )
|
||||
return;
|
||||
|
||||
wxFileName fn = m_Shape3DName;
|
||||
m_Shape3DNameExtension = fn.GetExt();
|
||||
|
||||
if( m_Shape3DNameExtension == wxT( "wrl" ) ||
|
||||
m_Shape3DNameExtension == wxT( "x3d" ) )
|
||||
m_ShapeType = FILE3D_VRML;
|
||||
else if( m_Shape3DNameExtension == wxT( "idf" ) )
|
||||
m_ShapeType = FILE3D_IDF;
|
||||
else
|
||||
m_ShapeType = FILE3D_UNKNOWN;
|
||||
|
||||
// Expand any environment variables embedded in footprint's m_Shape3DName field.
|
||||
// To ensure compatibility with most of footprint's m_Shape3DName field,
|
||||
// if the m_Shape3DName is not an absolute path the default path
|
||||
// given by the environment variable KISYS3DMOD will be used
|
||||
|
||||
if( m_Shape3DName.StartsWith( wxT("${") ) )
|
||||
m_Shape3DFullFilename = wxExpandEnvVars( m_Shape3DName );
|
||||
else
|
||||
m_Shape3DFullFilename = m_Shape3DName;
|
||||
|
||||
wxFileName fnFull( m_Shape3DFullFilename );
|
||||
|
||||
if( !( fnFull.IsAbsolute() || m_Shape3DFullFilename.StartsWith( wxT(".") ) ) )
|
||||
{
|
||||
wxString default_path;
|
||||
wxGetEnv( KISYS3DMOD, &default_path );
|
||||
|
||||
if( !( default_path.IsEmpty() ) )
|
||||
{
|
||||
|
||||
if( !default_path.EndsWith( wxT("/") ) && !default_path.EndsWith( wxT("\\") ) )
|
||||
default_path += wxT("/");
|
||||
|
||||
m_Shape3DFullFilename = default_path + m_Shape3DFullFilename;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const wxString S3D_MASTER::GetShape3DFullFilename()
|
||||
{
|
||||
return m_Shape3DFullFilename;
|
||||
}
|
||||
|
||||
|
||||
const wxString S3D_MASTER::GetShape3DExtension()
|
||||
{
|
||||
return m_Shape3DNameExtension;
|
||||
}
|
||||
|
||||
|
||||
STRUCT_3D_SHAPE::STRUCT_3D_SHAPE( EDA_ITEM* aParent ) :
|
||||
EDA_ITEM( aParent, NOT_USED )
|
||||
{
|
||||
m_3D_Coord = NULL;
|
||||
m_3D_CoordIndex = NULL;
|
||||
m_3D_Points = 0;
|
||||
}
|
||||
|
||||
|
||||
STRUCT_3D_SHAPE:: ~STRUCT_3D_SHAPE()
|
||||
{
|
||||
delete m_3D_Coord;
|
||||
delete m_3D_CoordIndex;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_draw_basic_functions.cpp
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <trigo.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
|
||||
#include <3d_viewer.h>
|
||||
#include <info3d_visu.h>
|
||||
#include <3d_draw_basic_functions.h>
|
||||
#include <modelparsers.h>
|
||||
|
||||
// Number of segments to approximate a circle by segments
|
||||
#define SEGM_PER_CIRCLE 24
|
||||
|
||||
#ifndef CALLBACK
|
||||
#define CALLBACK
|
||||
#endif
|
||||
|
||||
// Variables used to pass a value to call back openGL functions
|
||||
static float s_textureScale;
|
||||
static double s_currentZpos;
|
||||
static double s_biuTo3Dunits;
|
||||
bool s_useTextures;
|
||||
|
||||
// CALLBACK functions for GLU_TESS
|
||||
static void CALLBACK tessBeginCB( GLenum which );
|
||||
static void CALLBACK tessEndCB();
|
||||
static void CALLBACK tessErrorCB( GLenum errorCode );
|
||||
static void CALLBACK tessCPolyPt2Vertex( const GLvoid* data );
|
||||
|
||||
void TransfertToGLlist( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUnits );
|
||||
|
||||
/* Draw3D_VerticalPolygonalCylinder is a helper function.
|
||||
*
|
||||
* draws a "vertical cylinder" having a polygon shape
|
||||
* from Z position = aZpos to aZpos + aHeight
|
||||
* Used to create the vertical sides of 3D horizontal shapes with thickness.
|
||||
*/
|
||||
static void Draw3D_VerticalPolygonalCylinder( const SHAPE_POLY_SET& aPolysList,
|
||||
int aHeight, int aZpos,
|
||||
bool aInside, double aBiuTo3DUnits )
|
||||
{
|
||||
if( aHeight == 0 )
|
||||
return;
|
||||
|
||||
std::vector<S3D_VERTEX> coords;
|
||||
coords.resize( 4 );
|
||||
|
||||
// Init Z position of the 4 points of a GL_QUAD
|
||||
if( aInside )
|
||||
{
|
||||
coords[0].z = aZpos;
|
||||
coords[1].z = aZpos + aHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
coords[0].z = aZpos + aHeight;
|
||||
coords[1].z = aZpos;
|
||||
}
|
||||
coords[2].z = coords[1].z;
|
||||
coords[3].z = coords[0].z;
|
||||
|
||||
// Draw the vertical polygonal side
|
||||
for( int idx = 0; idx < aPolysList.OutlineCount(); idx++ )
|
||||
{
|
||||
// Each polygon in aPolysList is a polygon with holes
|
||||
const SHAPE_POLY_SET::POLYGON& curr_polywithholes = aPolysList.CPolygon( idx );
|
||||
|
||||
// Draw the outline of each simple polygon inside the polygon with holes:
|
||||
for( unsigned ipoly = 0; ipoly < curr_polywithholes.size(); ipoly++ )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN& path = curr_polywithholes[ipoly]; // a simple polygon
|
||||
|
||||
for( int jj = 0; jj < path.PointCount(); jj++ )
|
||||
{
|
||||
const VECTOR2I& a = path.CPoint( jj );
|
||||
const VECTOR2I& b = path.CPoint( jj + 1 );
|
||||
|
||||
// Build the 4 vertices of each GL_QUAD
|
||||
coords[0].x = a.x;
|
||||
coords[0].y = -a.y;
|
||||
coords[1].x = coords[0].x;
|
||||
coords[1].y = coords[0].y; // only z change
|
||||
coords[2].x = b.x;
|
||||
coords[2].y = -b.y;
|
||||
coords[3].x = coords[2].x;
|
||||
coords[3].y = coords[2].y; // only z change
|
||||
|
||||
// Creates the GL_QUAD
|
||||
TransfertToGLlist( coords, aBiuTo3DUnits );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetGLColor( EDA_COLOR_T color, double alpha )
|
||||
{
|
||||
const StructColors &colordata = g_ColorRefs[ColorGetBase( color )];
|
||||
|
||||
float red = colordata.m_Red / 255.0;
|
||||
float blue = colordata.m_Blue / 255.0;
|
||||
float green = colordata.m_Green / 255.0;
|
||||
glColor4f( red, green, blue, (float)alpha );
|
||||
}
|
||||
|
||||
|
||||
void SetGLColor( S3D_COLOR& aColor, float aTransparency )
|
||||
{
|
||||
glColor4f( aColor.m_Red, aColor.m_Green, aColor.m_Blue, aTransparency );
|
||||
}
|
||||
|
||||
|
||||
void SetGLTexture( GLuint text_id, float scale )
|
||||
{
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
glBindTexture( GL_TEXTURE_2D, text_id );
|
||||
s_textureScale = scale; // for Tess callback functions
|
||||
}
|
||||
|
||||
|
||||
/* draw all solid polygons found in aPolysList
|
||||
* aZpos = z position in board internal units
|
||||
* aThickness = thickness in board internal units
|
||||
* If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
|
||||
* If aThickness > 0, a solid object is drawn.
|
||||
* The top side is located at aZpos + aThickness / 2
|
||||
* The bottom side is located at aZpos - aThickness / 2
|
||||
*/
|
||||
void Draw3D_SolidHorizontalPolyPolygons( const SHAPE_POLY_SET& aPolysList,
|
||||
int aZpos, int aThickness, double aBiuTo3DUnits,
|
||||
bool aUseTextures,
|
||||
float aNormal_Z_Orientation )
|
||||
{
|
||||
// for Tess callback functions:
|
||||
s_biuTo3Dunits = aBiuTo3DUnits;
|
||||
s_useTextures = aUseTextures;
|
||||
|
||||
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 );
|
||||
|
||||
GLdouble v_data[3];
|
||||
double zpos = ( aZpos + (aThickness / 2.0) ) * aBiuTo3DUnits;
|
||||
s_currentZpos = zpos; // for Tess callback functions
|
||||
v_data[2] = zpos;
|
||||
|
||||
// Set normal toward positive Z axis, for a solid object on the top side
|
||||
|
||||
//gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE );
|
||||
gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD );
|
||||
|
||||
glNormal3f( 0.0, 0.0, aNormal_Z_Orientation );
|
||||
|
||||
// Draw solid areas contained in this list
|
||||
SHAPE_POLY_SET polylist = aPolysList; // temporary copy for gluTessVertex
|
||||
|
||||
for( int side = 0; side < 2; side++ )
|
||||
{
|
||||
|
||||
for ( int idx = 0; idx < polylist.OutlineCount(); ++idx )
|
||||
{
|
||||
gluTessBeginPolygon( tess, NULL );
|
||||
|
||||
SHAPE_POLY_SET::POLYGON& curr_polywithholes = polylist.Polygon( idx ); // a polygon with holes
|
||||
|
||||
for( unsigned ipoly = 0; ipoly < curr_polywithholes.size(); ipoly++ )
|
||||
{
|
||||
SHAPE_LINE_CHAIN& curr_poly = curr_polywithholes[ipoly]; // a simple polygon
|
||||
|
||||
gluTessBeginContour( tess );
|
||||
|
||||
for( int ipt = 0; ipt < curr_poly.PointCount(); ipt++ )
|
||||
{
|
||||
v_data[0] = curr_poly.Point( ipt ).x * aBiuTo3DUnits;
|
||||
v_data[1] = -curr_poly.Point( ipt ).y * aBiuTo3DUnits;
|
||||
// gluTessVertex store pointers on data, not data, so do not store
|
||||
// different corners values in a temporary variable
|
||||
// but send pointer on each CPolyPt value in polylist
|
||||
// before calling gluDeleteTess
|
||||
gluTessVertex( tess, v_data, &curr_poly.Point( ipt ) );
|
||||
}
|
||||
|
||||
gluTessEndContour( tess );
|
||||
}
|
||||
|
||||
gluTessEndPolygon( tess );
|
||||
}
|
||||
|
||||
|
||||
if( aThickness == 0 )
|
||||
break;
|
||||
|
||||
// Prepare the bottom side of solid areas
|
||||
zpos = ( aZpos - (aThickness / 2.0) ) * aBiuTo3DUnits;
|
||||
s_currentZpos = zpos; // for Tess callback functions
|
||||
v_data[2] = zpos;
|
||||
|
||||
glNormal3f( 0.0, 0.0, -aNormal_Z_Orientation );
|
||||
}
|
||||
|
||||
gluDeleteTess( tess );
|
||||
|
||||
if( aThickness == 0 )
|
||||
return;
|
||||
|
||||
// Build the 3D data : vertical side
|
||||
Draw3D_VerticalPolygonalCylinder( polylist, aThickness, aZpos - (aThickness / 2.0),
|
||||
true, aBiuTo3DUnits );
|
||||
}
|
||||
|
||||
|
||||
/* draw a cylinder (a tube) using 3D primitives.
|
||||
* the cylinder axis is parallel to the Z axis
|
||||
* If aHeight = height of the cylinder is 0, only one ring will be drawn
|
||||
* If aThickness = 0, only one cylinder will be drawn
|
||||
*/
|
||||
void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius,
|
||||
int aHeight, int aThickness,
|
||||
int aZpos, double aBiuTo3DUnits )
|
||||
{
|
||||
const int slice = SEGM_PER_CIRCLE;
|
||||
SHAPE_POLY_SET outer_cornerBuffer;
|
||||
|
||||
TransformCircleToPolygon( outer_cornerBuffer, aCenterPos,
|
||||
aRadius + (aThickness / 2), slice );
|
||||
|
||||
std::vector<S3D_VERTEX> coords;
|
||||
coords.resize( 4 );
|
||||
|
||||
SHAPE_POLY_SET inner_cornerBuffer;
|
||||
|
||||
if( aThickness ) // build the the vertical inner polygon (hole)
|
||||
TransformCircleToPolygon( inner_cornerBuffer, aCenterPos,
|
||||
aRadius - (aThickness / 2), slice );
|
||||
|
||||
if( aHeight )
|
||||
{
|
||||
|
||||
// Draw the vertical outer side
|
||||
Draw3D_VerticalPolygonalCylinder( outer_cornerBuffer,
|
||||
aHeight, aZpos, false, aBiuTo3DUnits );
|
||||
|
||||
if( aThickness )
|
||||
// Draws the vertical inner side (hole)
|
||||
Draw3D_VerticalPolygonalCylinder( inner_cornerBuffer,
|
||||
aHeight, aZpos, true, aBiuTo3DUnits );
|
||||
}
|
||||
|
||||
if( aThickness )
|
||||
{
|
||||
// draw top (front) and bottom (back) horizontal sides (rings)
|
||||
outer_cornerBuffer.AddHole( inner_cornerBuffer.COutline( 0 ) );
|
||||
|
||||
// draw top (front) horizontal ring
|
||||
Draw3D_SolidHorizontalPolyPolygons( outer_cornerBuffer, aZpos + aHeight,
|
||||
0, aBiuTo3DUnits, false, 1.0f );
|
||||
|
||||
if( aHeight )
|
||||
{
|
||||
// draw bottom (back) horizontal ring
|
||||
Draw3D_SolidHorizontalPolyPolygons( outer_cornerBuffer, aZpos,
|
||||
0, aBiuTo3DUnits, false, -1.0f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function Draw3D_ZaxisOblongCylinder:
|
||||
* draw a segment with an oblong hole.
|
||||
* Used to draw oblong holes
|
||||
* If aHeight = height of the cylinder is 0, only one ring will be drawn
|
||||
* If aThickness = 0, only one cylinder will be drawn
|
||||
*/
|
||||
void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos,
|
||||
int aRadius, int aHeight, int aThickness,
|
||||
int aZpos, double aBiuTo3DUnits )
|
||||
{
|
||||
const int slice = SEGM_PER_CIRCLE;
|
||||
|
||||
// Build the points to approximate oblong cylinder by segments
|
||||
SHAPE_POLY_SET cornerBuffer;
|
||||
|
||||
int segm_width = (aRadius * 2) + aThickness;
|
||||
TransformRoundedEndsSegmentToPolygon( cornerBuffer, aAxis1Pos,
|
||||
aAxis2Pos, slice, segm_width );
|
||||
|
||||
// Draw the oblong outer cylinder
|
||||
if( aHeight )
|
||||
Draw3D_VerticalPolygonalCylinder( cornerBuffer, aHeight, aZpos,
|
||||
false, aBiuTo3DUnits );
|
||||
|
||||
if( aThickness )
|
||||
{
|
||||
SHAPE_POLY_SET inner_cornerBuffer;
|
||||
segm_width = aRadius * 2;
|
||||
TransformRoundedEndsSegmentToPolygon( inner_cornerBuffer, aAxis1Pos,
|
||||
aAxis2Pos, slice, segm_width );
|
||||
|
||||
// Draw the oblong inner cylinder
|
||||
if( aHeight )
|
||||
Draw3D_VerticalPolygonalCylinder( inner_cornerBuffer, aHeight,
|
||||
aZpos, true, aBiuTo3DUnits );
|
||||
|
||||
// Build the horizontal full polygon shape
|
||||
// (outer polygon shape - inner polygon shape)
|
||||
cornerBuffer.AddHole( inner_cornerBuffer.COutline( 0 ) );
|
||||
|
||||
// draw top (front) horizontal side (ring)
|
||||
Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos + aHeight, 0, aBiuTo3DUnits, false,
|
||||
1.0f );
|
||||
|
||||
if( aHeight )
|
||||
{
|
||||
// draw bottom (back) horizontal side (ring)
|
||||
Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, 0, aBiuTo3DUnits, false,
|
||||
-1.0f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* draw a thick segment using 3D primitives, in a XY plane
|
||||
* wxPoint aStart, wxPoint aEnd = YX position of end in board units
|
||||
* aWidth = width of segment in board units
|
||||
* aThickness = thickness of segment in board units
|
||||
* aZpos = z position of segment in board units
|
||||
*/
|
||||
void Draw3D_SolidSegment( const wxPoint& aStart, const wxPoint& aEnd,
|
||||
int aWidth, int aThickness, int aZpos, double aBiuTo3DUnits )
|
||||
{
|
||||
SHAPE_POLY_SET cornerBuffer;
|
||||
const int slice = SEGM_PER_CIRCLE;
|
||||
|
||||
TransformRoundedEndsSegmentToPolygon( cornerBuffer, aStart, aEnd, slice, aWidth );
|
||||
|
||||
Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false, 1.0f );
|
||||
}
|
||||
|
||||
|
||||
void Draw3D_ArcSegment( const wxPoint& aCenterPos, const wxPoint& aStartPoint,
|
||||
double aArcAngle, int aWidth, int aThickness,
|
||||
int aZpos, double aBiuTo3DUnits )
|
||||
{
|
||||
const int slice = SEGM_PER_CIRCLE;
|
||||
|
||||
SHAPE_POLY_SET cornerBuffer;
|
||||
TransformArcToPolygon( cornerBuffer, aCenterPos, aStartPoint, aArcAngle,
|
||||
slice, aWidth );
|
||||
|
||||
Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false, 1.0f );
|
||||
}
|
||||
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// GLU_TESS CALLBACKS
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CALLBACK tessBeginCB( GLenum which )
|
||||
{
|
||||
glBegin( which );
|
||||
}
|
||||
|
||||
|
||||
void CALLBACK tessEndCB()
|
||||
{
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
void CALLBACK tessCPolyPt2Vertex( const GLvoid* data )
|
||||
{
|
||||
// cast back to double type
|
||||
const VECTOR2I* ptr = (const VECTOR2I*) data;
|
||||
|
||||
if( s_useTextures )
|
||||
{
|
||||
glTexCoord2f( ptr->x * s_biuTo3Dunits * s_textureScale,
|
||||
-ptr->y * s_biuTo3Dunits * s_textureScale);
|
||||
}
|
||||
|
||||
glVertex3d( ptr->x * s_biuTo3Dunits, -ptr->y * s_biuTo3Dunits, s_currentZpos );
|
||||
}
|
||||
|
||||
|
||||
void CALLBACK tessErrorCB( GLenum errorCode )
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
const GLubyte* errorStr;
|
||||
|
||||
errorStr = gluErrorString( errorCode );
|
||||
|
||||
// DEBUG //
|
||||
DBG( printf( "Tess ERROR: %s\n", errorStr ); )
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_draw_basic_functions.h
|
||||
*/
|
||||
#ifndef _3D_DRAW_BASIC_FUNCTIONS_H_
|
||||
#define _3D_DRAW_BASIC_FUNCTIONS_H_
|
||||
|
||||
// angle increment to draw a circle, approximated by segments
|
||||
#define ANGLE_INC( x ) ( 3600 / (x) )
|
||||
|
||||
/** draw all solid polygons found in aPolysList
|
||||
* @param aPolysList = the poligon list to draw
|
||||
* @param aZpos = z position in board internal units
|
||||
* @param aThickness = thickness in board internal units
|
||||
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
|
||||
* @param aUseTextures = true to use textxures for the polygons
|
||||
* @param aNormal_Z_Orientation = the normal Z orientation to apply
|
||||
* If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
|
||||
* If aThickness > 0, a solid object is drawn.
|
||||
* The top side is located at aZpos + aThickness / 2
|
||||
* The bottom side is located at aZpos - aThickness / 2
|
||||
*/
|
||||
void Draw3D_SolidHorizontalPolyPolygons( const SHAPE_POLY_SET& aPolysList,
|
||||
int aZpos, int aThickness, double aBiuTo3DUnits,
|
||||
bool aUseTextures,
|
||||
float aNormal_Z_Orientation );
|
||||
|
||||
/** draw a thick segment using 3D primitives, in a XY plane
|
||||
* @param aStart = YX position of start point in board units
|
||||
* @param aEnd = YX position of end point in board units
|
||||
* @param aWidth = width of segment in board units
|
||||
* @param aThickness = thickness of segment in board units
|
||||
* @param aZpos = z position of segment in board units
|
||||
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
|
||||
* If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
|
||||
* If aThickness > 0, a solid object is drawn.
|
||||
* The top side is located at aZpos + aThickness / 2
|
||||
* The bottom side is located at aZpos - aThickness / 2
|
||||
*/
|
||||
void Draw3D_SolidSegment( const wxPoint& aStart, const wxPoint& aEnd,
|
||||
int aWidth, int aThickness, int aZpos,
|
||||
double aBiuTo3DUnits );
|
||||
|
||||
/** draw an arc using 3D primitives, in a XY plane
|
||||
* @param aCenterPos = XY position of the center in board units
|
||||
* @param aStartPoint = start point coordinate of arc in board units
|
||||
* @param aWidth = width of the circle in board units
|
||||
* @param aArcAngle = arc angle in 1/10 degrees
|
||||
* @param aWidth = thickness of arc
|
||||
* @param aThickness = thickness of segment in board units
|
||||
* @param aZpos = z position of segment in board units
|
||||
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
|
||||
*/
|
||||
void Draw3D_ArcSegment( const wxPoint& aCenterPos, const wxPoint& aStartPoint,
|
||||
double aArcAngle, int aWidth, int aThickness,
|
||||
int aZpos, double aBiuTo3DUnits );
|
||||
|
||||
|
||||
/** draw a thick cylinder (a tube) using 3D primitives.
|
||||
* the cylinder axis is parallel to the Z axis
|
||||
* @param aCenterPos = XY position of the axis cylinder ( board internal units)
|
||||
* @param aRadius = radius of the cylinder ( board internal units)
|
||||
* @param aHeight = height of the cylinder ( boardinternal units)
|
||||
* @param aThickness = tichkness of tube ( boardinternal units)
|
||||
* @param aZpos = Z position of the bottom side of the cylinder ( board internal units)
|
||||
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
|
||||
*
|
||||
* If aHeight = height of the cylinder is 0, only one ring will be drawn
|
||||
* If aThickness = 0, only one cylinder (not a tube) will be drawn
|
||||
*/
|
||||
void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius,
|
||||
int aHeight, int aThickness,
|
||||
int aZpos, double aBiuTo3DUnits );
|
||||
|
||||
/** draw an oblong cylinder (oblong tube) using 3D primitives.
|
||||
* the cylinder axis are parallel to the Z axis
|
||||
* @param aAxis1Pos = position of the first axis cylinder
|
||||
* @param aAxis2Pos = position of the second axis cylinder
|
||||
* @param aRadius = radius of the cylinder ( board internal units )
|
||||
* @param aHeight = height of the cylinder ( board internal units )
|
||||
* @param aThickness = tichkness of tube ( board internal units )
|
||||
* @param aZpos = Z position of the bottom side of the cylinder ( board internal units )
|
||||
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
|
||||
*/
|
||||
void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos,
|
||||
int aRadius, int aHeight, int aThickness,
|
||||
int aZpos, double aBiuTo3DUnits );
|
||||
/**
|
||||
* Set the current 3D color from a Kicad color, with optional transparency
|
||||
* @param aColor = a EDA_COLOR_T kicad color index
|
||||
* @param aTransparency = the color transparency (default = 1.0 = no transparency)
|
||||
*/
|
||||
void SetGLColor( EDA_COLOR_T aColor, double aTransparency = 1.0 );
|
||||
|
||||
/**
|
||||
* Set the current 3D color from a S3D_COLOR color, with optional transparency
|
||||
* @param aColor = a S3D_COLOR RGB color index
|
||||
* @param aTransparency = the color transparency (default = 1.0 = no transparency)
|
||||
*/
|
||||
void SetGLColor( S3D_COLOR& aColor, float aTransparency );
|
||||
|
||||
|
||||
/**
|
||||
* Set a texture id and a scale to apply when rendering the polygons
|
||||
* @param text_id = texture ID created by glGenTextures
|
||||
* @param scale = scale to apply to texture coords
|
||||
*/
|
||||
void SetGLTexture( GLuint text_id, float scale );
|
||||
|
||||
|
||||
#endif // _3D_DRAW_BASIC_FUNCTIONS_H_
|
||||
@@ -0,0 +1,640 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014-2015 Mario Luzeiro <mrluzeiro@gmail.com>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_draw_board_body.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <common.h>
|
||||
#include <trigo.h>
|
||||
#include <pcbstruct.h>
|
||||
#include <drawtxt.h>
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
|
||||
#include <wxBasePcbFrame.h>
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <class_track.h>
|
||||
#include <class_edge_mod.h>
|
||||
#include <class_zone.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_pcb_text.h>
|
||||
#include <colors_selection.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
|
||||
#include <gal/opengl/opengl_compositor.h>
|
||||
#ifdef __WINDOWS__
|
||||
#include <GL/glew.h> // must be included before gl.h
|
||||
#endif
|
||||
|
||||
#include <3d_viewer.h>
|
||||
#include <3d_canvas.h>
|
||||
#include <info3d_visu.h>
|
||||
#include <trackball.h>
|
||||
#include <3d_draw_basic_functions.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <geometry/shape_file_io.h>
|
||||
|
||||
|
||||
#include <CImage.h>
|
||||
#include <reporter.h>
|
||||
|
||||
// An option for all operations on polygons:
|
||||
// when useFastModeForPolygons = true, calculations can be *a lot* faster.
|
||||
// but created polygons can be not stricty simple (can share edges)
|
||||
// Although stricty simple are better for glu tesselation functions, I do not see
|
||||
// any issue when allowing not stricty simple polygons.
|
||||
// But I see *very* long calculations when setting useFastMode to false.
|
||||
// So, be careful if changing thie option
|
||||
bool useFastModeForPolygons = true;
|
||||
|
||||
/* returns the Z orientation parameter 1.0 or -1.0 for aLayer
|
||||
* Z orientation is 1.0 for all layers but "back" layers:
|
||||
* B_Cu , B_Adhes, B_Paste ), B_SilkS
|
||||
* used to calculate the Z orientation parameter for glNormal3f
|
||||
*/
|
||||
GLfloat Get3DLayer_Z_Orientation( LAYER_NUM aLayer );
|
||||
|
||||
void EDA_3D_CANVAS::buildBoardThroughHolesPolygonList( SHAPE_POLY_SET& allBoardHoles,
|
||||
int aSegCountPerCircle, bool aOptimizeLargeCircles )
|
||||
{
|
||||
// hole diameter value to change seg count by circle:
|
||||
int small_hole_limit = Millimeter2iu( 1.0 );
|
||||
int copper_thickness = GetPrm3DVisu().GetCopperThicknessBIU();
|
||||
|
||||
BOARD* pcb = GetBoard();
|
||||
|
||||
// Build holes of through vias:
|
||||
for( TRACK* track = pcb->m_Track; track; track = track->Next() )
|
||||
{
|
||||
if( track->Type() != PCB_VIA_T )
|
||||
continue;
|
||||
|
||||
VIA *via = static_cast<VIA*>( track );
|
||||
|
||||
if( via->GetViaType() != VIA_THROUGH )
|
||||
continue;
|
||||
|
||||
int holediameter = via->GetDrillValue();
|
||||
int hole_outer_radius = (holediameter + copper_thickness) / 2;
|
||||
|
||||
TransformCircleToPolygon( allBoardHoles,
|
||||
via->GetStart(), hole_outer_radius,
|
||||
aSegCountPerCircle );
|
||||
}
|
||||
|
||||
// Build holes of through pads:
|
||||
for( MODULE* footprint = pcb->m_Modules; footprint; footprint = footprint->Next() )
|
||||
{
|
||||
for( D_PAD* pad = footprint->Pads(); pad; pad = pad->Next() )
|
||||
{
|
||||
// Calculate a factor to apply to segcount for large holes ( > 1 mm)
|
||||
// (bigger pad drill size -> more segments) because holes in pads can have
|
||||
// very different sizes and optimizing this segcount gives a better look
|
||||
// Mainly mounting holes have a size bigger than small_hole_limit
|
||||
wxSize padHole = pad->GetDrillSize();
|
||||
|
||||
if( ! padHole.x ) // Not drilled pad like SMD pad
|
||||
continue;
|
||||
|
||||
// we use the hole diameter to calculate the seg count.
|
||||
// for round holes, padHole.x == padHole.y
|
||||
// for oblong holes, the diameter is the smaller of (padHole.x, padHole.y)
|
||||
int diam = std::min( padHole.x, padHole.y );
|
||||
int segcount = aSegCountPerCircle;
|
||||
|
||||
if( diam > small_hole_limit )
|
||||
{
|
||||
double segFactor = (double)diam / small_hole_limit;
|
||||
segcount = (int)(aSegCountPerCircle * segFactor);
|
||||
|
||||
// limit segcount to 48. For a circle this is a very good approx.
|
||||
if( segcount > 48 )
|
||||
segcount = 48;
|
||||
}
|
||||
|
||||
// The hole in the body is inflated by copper thickness.
|
||||
int inflate = copper_thickness;
|
||||
|
||||
// If not plated, no copper.
|
||||
if( pad->GetAttribute () == PAD_ATTRIB_HOLE_NOT_PLATED )
|
||||
inflate = 0;
|
||||
|
||||
pad->BuildPadDrillShapePolygon( allBoardHoles, inflate, segcount );
|
||||
}
|
||||
}
|
||||
|
||||
allBoardHoles.Simplify( useFastModeForPolygons );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
|
||||
REPORTER* aErrorMessages, REPORTER* aActivity )
|
||||
{
|
||||
BOARD* pcb = GetBoard();
|
||||
|
||||
// If FL_RENDER_SHOW_HOLES_IN_ZONES is true, holes are correctly removed from copper zones areas.
|
||||
// If FL_RENDER_SHOW_HOLES_IN_ZONES is false, holes are not removed from copper zones areas,
|
||||
// but the calculation time is twice shorter.
|
||||
bool remove_Holes = isEnabled( FL_RENDER_SHOW_HOLES_IN_ZONES );
|
||||
|
||||
bool realistic_mode = isRealisticMode();
|
||||
bool useTextures = isRealisticMode() && isEnabled( FL_RENDER_TEXTURES );
|
||||
|
||||
// Number of segments to convert a circle to polygon
|
||||
// We use 2 values: the first gives a good shape (for instanes rond pads)
|
||||
// the second is used to speed up calculations, when a poor approximation is acceptable (holes)
|
||||
const int segcountforcircle = 18;
|
||||
double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2.0) );
|
||||
const int segcountLowQuality = 12; // segments to draw a circle with low quality
|
||||
// to reduce time calculations
|
||||
// for holes and items which do not need
|
||||
// a fine representation
|
||||
double correctionFactorLQ = 1.0 / cos( M_PI / (segcountLowQuality * 2.0) );
|
||||
|
||||
SHAPE_POLY_SET bufferPolys; // copper areas: tracks, pads and filled zones areas
|
||||
// when holes are removed from zones
|
||||
SHAPE_POLY_SET bufferPcbOutlines; // stores the board main outlines
|
||||
SHAPE_POLY_SET bufferZonesPolys; // copper filled zones areas
|
||||
// when holes are not removed from zones
|
||||
SHAPE_POLY_SET currLayerHoles; // Contains holes for the current layer
|
||||
SHAPE_POLY_SET allLayerHoles; // Contains holes for all layers
|
||||
|
||||
// Build a polygon from edge cut items
|
||||
wxString msg;
|
||||
|
||||
if( !pcb->GetBoardPolygonOutlines( bufferPcbOutlines, allLayerHoles, &msg ) )
|
||||
{
|
||||
if( aErrorMessages )
|
||||
{
|
||||
msg << wxT("\n") << _("Unable to calculate the board outlines.\n"
|
||||
"Therefore use the board boundary box.") << wxT("\n\n");
|
||||
|
||||
aErrorMessages->Report( msg, REPORTER::RPT_WARNING );
|
||||
}
|
||||
}
|
||||
|
||||
// Build board holes, with optimization of large holes shape.
|
||||
buildBoardThroughHolesPolygonList( allLayerHoles, segcountLowQuality, true );
|
||||
|
||||
LSET cu_set = LSET::AllCuMask( GetPrm3DVisu().m_CopperLayersCount );
|
||||
|
||||
glNewList( aBoardList, GL_COMPILE );
|
||||
|
||||
for( LSEQ cu = cu_set.CuStack(); cu; ++cu )
|
||||
{
|
||||
LAYER_ID layer = *cu;
|
||||
|
||||
// Skip non enabled layers in normal mode,
|
||||
// and internal layers in realistic mode
|
||||
if( !is3DLayerEnabled( layer ) )
|
||||
continue;
|
||||
|
||||
if( aActivity )
|
||||
aActivity->Report( wxString::Format( _( "Build layer %s" ), LSET::Name( layer ) ) );
|
||||
|
||||
bufferPolys.RemoveAllContours();
|
||||
bufferZonesPolys.RemoveAllContours();
|
||||
currLayerHoles.RemoveAllContours();
|
||||
|
||||
// Draw track shapes:
|
||||
for( TRACK* track = pcb->m_Track; track; track = track->Next() )
|
||||
{
|
||||
if( !track->IsOnLayer( layer ) )
|
||||
continue;
|
||||
|
||||
track->TransformShapeWithClearanceToPolygon( bufferPolys,
|
||||
0, segcountforcircle,
|
||||
correctionFactor );
|
||||
|
||||
// Add blind/buried via holes
|
||||
if( track->Type() == PCB_VIA_T )
|
||||
{
|
||||
VIA *via = static_cast<VIA*>( track );
|
||||
|
||||
if( via->GetViaType() == VIA_THROUGH )
|
||||
continue; // already done
|
||||
|
||||
int holediameter = via->GetDrillValue();
|
||||
int thickness = GetPrm3DVisu().GetCopperThicknessBIU();
|
||||
int hole_outer_radius = (holediameter + thickness) / 2;
|
||||
|
||||
TransformCircleToPolygon( currLayerHoles,
|
||||
via->GetStart(), hole_outer_radius,
|
||||
segcountLowQuality );
|
||||
}
|
||||
}
|
||||
|
||||
// draw pad shapes
|
||||
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
|
||||
{
|
||||
// Note: NPTH pads are not drawn on copper layers when the pad
|
||||
// has same shape as its hole
|
||||
module->TransformPadsShapesWithClearanceToPolygon( layer,
|
||||
bufferPolys,
|
||||
0,
|
||||
segcountforcircle,
|
||||
correctionFactor, true );
|
||||
|
||||
// Micro-wave modules may have items on copper layers
|
||||
module->TransformGraphicShapesWithClearanceToPolygonSet( layer,
|
||||
bufferPolys,
|
||||
0,
|
||||
segcountforcircle,
|
||||
correctionFactor );
|
||||
|
||||
// pad holes are already in list.
|
||||
}
|
||||
|
||||
// Draw copper zones. Note:
|
||||
// * if the holes are removed from copper zones
|
||||
// the polygons are stored in bufferPolys (which contains all other polygons)
|
||||
// * if the holes are NOT removed from copper zones
|
||||
// the polygons are stored in bufferZonesPolys
|
||||
if( isEnabled( FL_ZONE ) )
|
||||
{
|
||||
for( int ii = 0; ii < pcb->GetAreaCount(); ii++ )
|
||||
{
|
||||
ZONE_CONTAINER* zone = pcb->GetArea( ii );
|
||||
LAYER_NUM zonelayer = zone->GetLayer();
|
||||
|
||||
if( zonelayer == layer )
|
||||
{
|
||||
zone->TransformSolidAreasShapesToPolygonSet(
|
||||
remove_Holes ? bufferPolys : bufferZonesPolys,
|
||||
segcountLowQuality, correctionFactorLQ );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draw graphic items on copper layers (texts)
|
||||
for( BOARD_ITEM* item = pcb->m_Drawings; item; item = item->Next() )
|
||||
{
|
||||
if( !item->IsOnLayer( layer ) )
|
||||
continue;
|
||||
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_LINE_T: // should not exist on copper layers
|
||||
( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon(
|
||||
bufferPolys, 0, segcountforcircle, correctionFactor );
|
||||
break;
|
||||
|
||||
case PCB_TEXT_T:
|
||||
( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet(
|
||||
bufferPolys, 0, segcountLowQuality, correctionFactor );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// bufferPolys contains polygons to merge. Many overlaps .
|
||||
// Calculate merged polygons
|
||||
if( bufferPolys.IsEmpty() )
|
||||
continue;
|
||||
|
||||
// Use Clipper lib to subtract holes to copper areas
|
||||
if( currLayerHoles.OutlineCount() )
|
||||
{
|
||||
currLayerHoles.Append(allLayerHoles);
|
||||
currLayerHoles.Simplify( useFastModeForPolygons );
|
||||
bufferPolys.BooleanSubtract( currLayerHoles, useFastModeForPolygons );
|
||||
}
|
||||
else
|
||||
bufferPolys.BooleanSubtract( allLayerHoles, useFastModeForPolygons );
|
||||
|
||||
int thickness = GetPrm3DVisu().GetLayerObjectThicknessBIU( layer );
|
||||
int zpos = GetPrm3DVisu().GetLayerZcoordBIU( layer );
|
||||
|
||||
float zNormal = 1.0f; // When using thickness it will draw first the top and then botton (with z inverted)
|
||||
|
||||
// If we are not using thickness, then the z-normal has to match the layer direction
|
||||
// because just one plane will be drawn
|
||||
if( !thickness )
|
||||
zNormal = Get3DLayer_Z_Orientation( layer );
|
||||
|
||||
if( realistic_mode )
|
||||
{
|
||||
setGLCopperColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
EDA_COLOR_T color = g_ColorsSettings.GetLayerColor( layer );
|
||||
SetGLColor( color );
|
||||
}
|
||||
|
||||
// If holes are removed from copper zones, bufferPolys contains all polygons
|
||||
// to draw (tracks+zones+texts).
|
||||
Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos, thickness,
|
||||
GetPrm3DVisu().m_BiuTo3Dunits, useTextures,
|
||||
zNormal );
|
||||
|
||||
// If holes are not removed from copper zones (for calculation time reasons,
|
||||
// the zone polygons are stored in bufferZonesPolys and have to be drawn now:
|
||||
if( !bufferZonesPolys.IsEmpty() )
|
||||
{
|
||||
Draw3D_SolidHorizontalPolyPolygons( bufferZonesPolys, zpos, thickness,
|
||||
GetPrm3DVisu().m_BiuTo3Dunits, useTextures,
|
||||
zNormal );
|
||||
}
|
||||
}
|
||||
|
||||
if( aActivity )
|
||||
aActivity->Report( _( "Build board body" ) );
|
||||
|
||||
// Draw plated vertical holes inside the board, but not always. They are drawn:
|
||||
// - if the board body is not shown, to show the holes.
|
||||
// - or if the copper thickness is shown
|
||||
if( !isEnabled( FL_SHOW_BOARD_BODY ) || isEnabled( FL_USE_COPPER_THICKNESS ) )
|
||||
{
|
||||
// Draw vias holes (vertical cylinders)
|
||||
for( const TRACK* track = pcb->m_Track; track; track = track->Next() )
|
||||
{
|
||||
if( track->Type() == PCB_VIA_T )
|
||||
{
|
||||
const VIA *via = static_cast<const VIA*>(track);
|
||||
draw3DViaHole( via );
|
||||
}
|
||||
}
|
||||
|
||||
// Draw pads holes (vertical cylinders)
|
||||
for( const MODULE* module = pcb->m_Modules; module; module = module->Next() )
|
||||
{
|
||||
for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() )
|
||||
if( pad->GetAttribute () != PAD_ATTRIB_HOLE_NOT_PLATED )
|
||||
draw3DPadHole( pad );
|
||||
}
|
||||
}
|
||||
|
||||
glEndList();
|
||||
|
||||
// Build the body board:
|
||||
glNewList( aBodyOnlyList, GL_COMPILE );
|
||||
|
||||
if( isRealisticMode() )
|
||||
{
|
||||
setGLEpoxyColor( 1.00 );
|
||||
}
|
||||
else
|
||||
{
|
||||
EDA_COLOR_T color = g_ColorsSettings.GetLayerColor( Edge_Cuts );
|
||||
SetGLColor( color, 0.7 );
|
||||
}
|
||||
|
||||
float copper_thickness = GetPrm3DVisu().GetCopperThicknessBIU();
|
||||
|
||||
// a small offset between substrate and external copper layer to avoid artifacts
|
||||
// when drawing copper items on board
|
||||
float epsilon = Millimeter2iu( 0.01 );
|
||||
float zpos = GetPrm3DVisu().GetLayerZcoordBIU( B_Cu );
|
||||
float board_thickness = GetPrm3DVisu().GetLayerZcoordBIU( F_Cu )
|
||||
- GetPrm3DVisu().GetLayerZcoordBIU( B_Cu );
|
||||
|
||||
// items on copper layers and having a thickness = copper_thickness
|
||||
// are drawn from zpos - copper_thickness/2 to zpos + copper_thickness
|
||||
// therefore substrate position is copper_thickness/2 to
|
||||
// substrate_height - copper_thickness/2
|
||||
zpos += (copper_thickness + epsilon) / 2.0f;
|
||||
board_thickness -= copper_thickness + epsilon;
|
||||
|
||||
bufferPcbOutlines.BooleanSubtract( allLayerHoles, useFastModeForPolygons );
|
||||
|
||||
if( !bufferPcbOutlines.IsEmpty() )
|
||||
{
|
||||
Draw3D_SolidHorizontalPolyPolygons( bufferPcbOutlines, zpos + board_thickness / 2.0,
|
||||
board_thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures,
|
||||
1.0f );
|
||||
}
|
||||
|
||||
glEndList();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::buildTechLayers3DView( REPORTER* aErrorMessages, REPORTER* aActivity )
|
||||
{
|
||||
BOARD* pcb = GetBoard();
|
||||
bool useTextures = isRealisticMode() && isEnabled( FL_RENDER_TEXTURES );
|
||||
|
||||
// Number of segments to draw a circle using segments
|
||||
const int segcountforcircle = 18;
|
||||
double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2) );
|
||||
const int segcountLowQuality = 12; // segments to draw a circle with low quality
|
||||
// to reduce time calculations
|
||||
// for holes and items which do not need
|
||||
// a fine representation
|
||||
|
||||
double correctionFactorLQ = 1.0 / cos( M_PI / (segcountLowQuality * 2) );
|
||||
|
||||
// segments to draw a circle to build texts. Is is used only to build
|
||||
// the shape of each segment of the stroke font, therefore no need to have
|
||||
// many segments per circle.
|
||||
const int segcountInStrokeFont = 8;
|
||||
|
||||
SHAPE_POLY_SET bufferPolys;
|
||||
SHAPE_POLY_SET allLayerHoles; // Contains through holes, calculated only once
|
||||
SHAPE_POLY_SET bufferPcbOutlines; // stores the board main outlines
|
||||
|
||||
// Build a polygon from edge cut items
|
||||
wxString msg;
|
||||
|
||||
if( !pcb->GetBoardPolygonOutlines( bufferPcbOutlines, allLayerHoles, &msg ) )
|
||||
{
|
||||
if( aErrorMessages )
|
||||
{
|
||||
msg << wxT("\n") <<
|
||||
_("Unable to calculate the board outlines.\n"
|
||||
"Therefore use the board boundary box.") << wxT("\n\n");
|
||||
aErrorMessages->Report( msg, REPORTER::RPT_WARNING );
|
||||
}
|
||||
}
|
||||
|
||||
// Build board holes, with no optimization of large holes shape.
|
||||
buildBoardThroughHolesPolygonList( allLayerHoles, segcountLowQuality, false );
|
||||
|
||||
// draw graphic items, on technical layers
|
||||
|
||||
static const LAYER_ID teckLayerList[] = {
|
||||
B_Adhes,
|
||||
F_Adhes,
|
||||
B_Paste,
|
||||
F_Paste,
|
||||
B_SilkS,
|
||||
F_SilkS,
|
||||
B_Mask,
|
||||
F_Mask,
|
||||
};
|
||||
|
||||
// User layers are not drawn here, only technical layers
|
||||
for( LSEQ seq = LSET::AllTechMask().Seq( teckLayerList, DIM( teckLayerList ) ); seq; ++seq )
|
||||
{
|
||||
LAYER_ID layer = *seq;
|
||||
|
||||
if( !is3DLayerEnabled( layer ) )
|
||||
continue;
|
||||
|
||||
if( layer == Edge_Cuts && isEnabled( FL_SHOW_BOARD_BODY ) )
|
||||
continue;
|
||||
|
||||
if( aActivity )
|
||||
aActivity->Report( wxString::Format( _( "Build layer %s" ), LSET::Name( layer ) ) );
|
||||
|
||||
bufferPolys.RemoveAllContours();
|
||||
|
||||
for( BOARD_ITEM* item = pcb->m_Drawings; item; item = item->Next() )
|
||||
{
|
||||
if( !item->IsOnLayer( layer ) )
|
||||
continue;
|
||||
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_LINE_T:
|
||||
( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon(
|
||||
bufferPolys, 0, segcountforcircle, correctionFactor );
|
||||
break;
|
||||
|
||||
case PCB_TEXT_T:
|
||||
( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet(
|
||||
bufferPolys, 0, segcountLowQuality, 1.0 );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
|
||||
{
|
||||
if( layer == F_SilkS || layer == B_SilkS )
|
||||
{
|
||||
// On silk screen layers, the pad shape is only the pad outline
|
||||
// never a filled shape
|
||||
D_PAD* pad = module->Pads();
|
||||
int linewidth = g_DrawDefaultLineThickness;
|
||||
|
||||
for( ; pad; pad = pad->Next() )
|
||||
{
|
||||
if( !pad->IsOnLayer( layer ) )
|
||||
continue;
|
||||
|
||||
buildPadShapeThickOutlineAsPolygon( pad, bufferPolys,
|
||||
linewidth, segcountforcircle, correctionFactor );
|
||||
}
|
||||
}
|
||||
else
|
||||
module->TransformPadsShapesWithClearanceToPolygon( layer,
|
||||
bufferPolys, 0, segcountforcircle, correctionFactor );
|
||||
|
||||
// On tech layers, use a poor circle approximation, only for texts (stroke font)
|
||||
module->TransformGraphicShapesWithClearanceToPolygonSet( layer,
|
||||
bufferPolys, 0, segcountforcircle, correctionFactor, segcountInStrokeFont );
|
||||
}
|
||||
|
||||
// Draw non copper zones
|
||||
if( isEnabled( FL_ZONE ) )
|
||||
{
|
||||
for( int ii = 0; ii < pcb->GetAreaCount(); ii++ )
|
||||
{
|
||||
ZONE_CONTAINER* zone = pcb->GetArea( ii );
|
||||
|
||||
if( !zone->IsOnLayer( layer ) )
|
||||
continue;
|
||||
|
||||
zone->TransformSolidAreasShapesToPolygonSet(
|
||||
bufferPolys, segcountLowQuality, correctionFactorLQ );
|
||||
}
|
||||
}
|
||||
|
||||
// bufferPolys contains polygons to merge. Many overlaps .
|
||||
// Calculate merged polygons and remove pads and vias holes
|
||||
if( layer != B_Mask && layer != F_Mask && bufferPolys.IsEmpty() )
|
||||
// if a layer has no iten to draw, skip it
|
||||
// However solder mask layers are negative layers, so no item
|
||||
// means only a full layer mask
|
||||
continue;
|
||||
|
||||
// Solder mask layers are "negative" layers.
|
||||
// Shapes should be removed from the full board area.
|
||||
if( layer == B_Mask || layer == F_Mask )
|
||||
{
|
||||
SHAPE_POLY_SET cuts = bufferPolys;
|
||||
bufferPolys = bufferPcbOutlines;
|
||||
|
||||
cuts.Append(allLayerHoles);
|
||||
cuts.Simplify( useFastModeForPolygons );
|
||||
|
||||
bufferPolys.BooleanSubtract( cuts, useFastModeForPolygons );
|
||||
}
|
||||
// Remove holes from Solder paste layers and silkscreen
|
||||
else if( layer == B_Paste || layer == F_Paste
|
||||
|| layer == B_SilkS || layer == F_SilkS )
|
||||
{
|
||||
bufferPolys.BooleanSubtract( allLayerHoles, useFastModeForPolygons );
|
||||
}
|
||||
|
||||
int thickness = 0;
|
||||
|
||||
if( layer != B_Mask && layer != F_Mask )
|
||||
thickness = GetPrm3DVisu().GetLayerObjectThicknessBIU( layer );
|
||||
|
||||
int zpos = GetPrm3DVisu().GetLayerZcoordBIU( layer );
|
||||
|
||||
if( layer == Edge_Cuts )
|
||||
{
|
||||
thickness = GetPrm3DVisu().GetLayerZcoordBIU( F_Cu )
|
||||
- GetPrm3DVisu().GetLayerZcoordBIU( B_Cu );
|
||||
zpos = GetPrm3DVisu().GetLayerZcoordBIU( B_Cu )
|
||||
+ (thickness / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// for Draw3D_SolidHorizontalPolyPolygons, zpos it the middle between bottom and top
|
||||
// sides.
|
||||
// However for top layers, zpos should be the bottom layer pos,
|
||||
// and for bottom layers, zpos should be the top layer pos.
|
||||
if( Get3DLayer_Z_Orientation( layer ) > 0 )
|
||||
zpos += thickness/2;
|
||||
else
|
||||
zpos -= thickness/2 ;
|
||||
}
|
||||
|
||||
|
||||
float zNormal = 1.0f; // When using thickness it will draw first the top and then botton (with z inverted)
|
||||
|
||||
// If we are not using thickness, then the znormal must face the layer direction
|
||||
// because it will draw just one plane
|
||||
if( !thickness )
|
||||
zNormal = Get3DLayer_Z_Orientation( layer );
|
||||
|
||||
|
||||
setGLTechLayersColor( layer );
|
||||
Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos,
|
||||
thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures,
|
||||
zNormal );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,493 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_draw_helper_functions.cpp
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
|
||||
#include <PolyLine.h>
|
||||
#include <colors.h>
|
||||
#include <colors_selection.h>
|
||||
#include <class_pad.h>
|
||||
#include <class_track.h>
|
||||
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
|
||||
#include <3d_viewer.h>
|
||||
#include <3d_canvas.h>
|
||||
#include <info3d_visu.h>
|
||||
#include <3d_draw_basic_functions.h>
|
||||
|
||||
#define TEXTURE_PCB_SCALE 5.0
|
||||
|
||||
// -----------------
|
||||
// helper function (from wxWidgets, opengl/cube.cpp sample
|
||||
// -----------------
|
||||
void CheckGLError(const char *aFileName, int aLineNumber)
|
||||
{
|
||||
GLenum errLast = GL_NO_ERROR;
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
GLenum err = glGetError();
|
||||
if ( err == GL_NO_ERROR )
|
||||
return;
|
||||
|
||||
// normally the error is reset by the call to glGetError() but if
|
||||
// glGetError() itself returns an error, we risk looping forever here
|
||||
// so check that we get a different error than the last time
|
||||
if ( err == errLast )
|
||||
{
|
||||
wxLogError(wxT("OpenGL error state couldn't be reset."));
|
||||
return;
|
||||
}
|
||||
|
||||
errLast = err;
|
||||
|
||||
wxLogError( wxT( "OpenGL error %d At: %s, line: %d" ), err,
|
||||
GetChars( FROM_UTF8( aFileName ) ), aLineNumber );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INFO3D_VISU& EDA_3D_CANVAS::GetPrm3DVisu() const
|
||||
{
|
||||
return Parent()->GetPrm3DVisu();
|
||||
}
|
||||
|
||||
wxSize EDA_3D_CANVAS::getBoardSize() const
|
||||
{
|
||||
// return the size of the board in pcb units
|
||||
return GetPrm3DVisu().m_BoardSize;
|
||||
}
|
||||
|
||||
|
||||
wxPoint EDA_3D_CANVAS::getBoardCenter() const
|
||||
{
|
||||
// return the position of the board center in pcb units
|
||||
return GetPrm3DVisu().m_BoardPos;
|
||||
}
|
||||
|
||||
// return true if we are in realistic mode render
|
||||
bool EDA_3D_CANVAS::isRealisticMode() const
|
||||
{
|
||||
return GetPrm3DVisu().IsRealisticMode();
|
||||
}
|
||||
|
||||
// return true if aItem should be displayed
|
||||
bool EDA_3D_CANVAS::isEnabled( DISPLAY3D_FLG aItem ) const
|
||||
{
|
||||
return GetPrm3DVisu().GetFlag( aItem );
|
||||
}
|
||||
|
||||
|
||||
// Helper function: initialize the copper color to draw the board
|
||||
// in realistic mode.
|
||||
void EDA_3D_CANVAS::setGLCopperColor()
|
||||
{
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
SetGLColor( GetPrm3DVisu().m_CopperColor, 1.0 );
|
||||
}
|
||||
|
||||
// Helper function: initialize the color to draw the epoxy
|
||||
// body board in realistic mode.
|
||||
void EDA_3D_CANVAS::setGLEpoxyColor( float aTransparency )
|
||||
{
|
||||
// Generates an epoxy color, near board color
|
||||
SetGLColor( GetPrm3DVisu().m_BoardBodyColor, aTransparency );
|
||||
|
||||
if( isEnabled( FL_RENDER_TEXTURES ) )
|
||||
{
|
||||
SetGLTexture( m_text_pcb, TEXTURE_PCB_SCALE );
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function: initialize the color to draw the
|
||||
// solder mask layers in realistic mode.
|
||||
void EDA_3D_CANVAS::setGLSolderMaskColor( float aTransparency )
|
||||
{
|
||||
// Generates a solder mask color
|
||||
SetGLColor( GetPrm3DVisu().m_SolderMaskColor, aTransparency );
|
||||
|
||||
if( isEnabled( FL_RENDER_TEXTURES ) )
|
||||
{
|
||||
SetGLTexture( m_text_pcb, TEXTURE_PCB_SCALE );
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function: initialize the color to draw the non copper layers
|
||||
// in realistic mode and normal mode.
|
||||
void EDA_3D_CANVAS::setGLTechLayersColor( LAYER_NUM aLayer )
|
||||
{
|
||||
EDA_COLOR_T color;
|
||||
|
||||
if( isRealisticMode() )
|
||||
{
|
||||
switch( aLayer )
|
||||
{
|
||||
case B_Paste:
|
||||
case F_Paste:
|
||||
SetGLColor( GetPrm3DVisu().m_SolderPasteColor, 1 );
|
||||
break;
|
||||
|
||||
case B_SilkS:
|
||||
case F_SilkS:
|
||||
SetGLColor( GetPrm3DVisu().m_SilkScreenColor, 0.96 );
|
||||
|
||||
if( isEnabled( FL_RENDER_TEXTURES ) )
|
||||
{
|
||||
SetGLTexture( m_text_silk, 10.0f );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case B_Mask:
|
||||
case F_Mask:
|
||||
setGLSolderMaskColor( 0.90 );
|
||||
break;
|
||||
|
||||
default:
|
||||
color = g_ColorsSettings.GetLayerColor( aLayer );
|
||||
SetGLColor( color, 0.7 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
color = g_ColorsSettings.GetLayerColor( aLayer );
|
||||
SetGLColor( color, 0.7 );
|
||||
}
|
||||
}
|
||||
|
||||
void EDA_3D_CANVAS::draw3DAxis()
|
||||
{
|
||||
if( ! m_glLists[GL_ID_AXIS] )
|
||||
{
|
||||
m_glLists[GL_ID_AXIS] = glGenLists( 1 );
|
||||
glNewList( m_glLists[GL_ID_AXIS], GL_COMPILE );
|
||||
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glBegin( GL_LINES );
|
||||
SetGLColor( RED );
|
||||
glNormal3f( 0.0f, 0.0f, 1.0f ); // Normal is Z axis
|
||||
glVertex3f( 0.0f, 0.0f, 0.0f );
|
||||
glVertex3f( -10.0f, 0.0f, 0.0f );
|
||||
glVertex3f( 0.0f, 0.0f, 0.0f );
|
||||
glVertex3f( 10.0f, 0.0f, 0.0f ); // X axis
|
||||
SetGLColor( GREEN );
|
||||
glVertex3f( 0.0f, 0.0f, 0.0f );
|
||||
glVertex3f( 0.0f, -10.0f, 0.0f ); // Y axis
|
||||
glVertex3f( 0.0f, 0.0f, 0.0f );
|
||||
glVertex3f( 0.0f, 10.0f, 0.0f );
|
||||
SetGLColor( BLUE );
|
||||
glNormal3f( 1.0f, 0.0f, 0.0f ); // Normal is Y axis
|
||||
glVertex3f( 0.0f, 0.0f, 0.0f );
|
||||
glVertex3f( 0.0f, 0.0f, -10.0f );
|
||||
glVertex3f( 0.0f, 0.0f, 0.0f );
|
||||
glVertex3f( 0.0f, 0.0f, 10.0f ); // Z axis
|
||||
glEnd();
|
||||
|
||||
glEndList();
|
||||
}
|
||||
}
|
||||
|
||||
// draw a 3D grid: an horizontal grid (XY plane and Z = 0,
|
||||
// and a vertical grid (XZ plane and Y = 0)
|
||||
void EDA_3D_CANVAS::draw3DGrid( double aGriSizeMM )
|
||||
{
|
||||
double zpos = 0.0;
|
||||
EDA_COLOR_T gridcolor = DARKGRAY; // Color of grid lines
|
||||
EDA_COLOR_T gridcolor_marker = LIGHTGRAY; // Color of grid lines every 5 lines
|
||||
const double scale = GetPrm3DVisu().m_BiuTo3Dunits;
|
||||
const double transparency = 0.3;
|
||||
|
||||
glNormal3f( 0.0, 0.0, 1.0 );
|
||||
|
||||
wxSize brd_size = getBoardSize();
|
||||
wxPoint brd_center_pos = getBoardCenter();
|
||||
brd_center_pos.y = -brd_center_pos.y;
|
||||
|
||||
int xsize = std::max( brd_size.x, Millimeter2iu( 100 ) ) * 1.2;
|
||||
int ysize = std::max( brd_size.y, Millimeter2iu( 100 ) ) * 1.2;
|
||||
|
||||
// Grid limits, in 3D units
|
||||
double xmin = (brd_center_pos.x - xsize / 2) * scale;
|
||||
double xmax = (brd_center_pos.x + xsize / 2) * scale;
|
||||
double ymin = (brd_center_pos.y - ysize / 2) * scale;
|
||||
double ymax = (brd_center_pos.y + ysize / 2) * scale;
|
||||
double zmin = Millimeter2iu( -50 ) * scale;
|
||||
double zmax = Millimeter2iu( 100 ) * scale;
|
||||
|
||||
// Draw horizontal grid centered on 3D origin (center of the board)
|
||||
for( int ii = 0; ; ii++ )
|
||||
{
|
||||
if( (ii % 5) )
|
||||
SetGLColor( gridcolor, transparency );
|
||||
else
|
||||
SetGLColor( gridcolor_marker, transparency );
|
||||
|
||||
int delta = KiROUND( ii * aGriSizeMM * IU_PER_MM );
|
||||
|
||||
if( delta <= xsize / 2 ) // Draw grid lines parallel to X axis
|
||||
{
|
||||
glBegin( GL_LINES );
|
||||
glVertex3f( (brd_center_pos.x + delta) * scale, -ymin, zpos );
|
||||
glVertex3f( (brd_center_pos.x + delta) * scale, -ymax, zpos );
|
||||
glEnd();
|
||||
|
||||
if( ii != 0 )
|
||||
{
|
||||
glBegin( GL_LINES );
|
||||
glVertex3f( (brd_center_pos.x - delta) * scale, -ymin, zpos );
|
||||
glVertex3f( (brd_center_pos.x - delta) * scale, -ymax, zpos );
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
if( delta <= ysize / 2 ) // Draw grid lines parallel to Y axis
|
||||
{
|
||||
glBegin( GL_LINES );
|
||||
glVertex3f( xmin, -(brd_center_pos.y + delta) * scale, zpos );
|
||||
glVertex3f( xmax, -(brd_center_pos.y + delta) * scale, zpos );
|
||||
glEnd();
|
||||
|
||||
if( ii != 0 )
|
||||
{
|
||||
glBegin( GL_LINES );
|
||||
glVertex3f( xmin, -(brd_center_pos.y - delta) * scale, zpos );
|
||||
glVertex3f( xmax, -(brd_center_pos.y - delta) * scale, zpos );
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
if( ( delta > ysize / 2 ) && ( delta > xsize / 2 ) )
|
||||
break;
|
||||
}
|
||||
|
||||
// Draw vertical grid on Z axis
|
||||
glNormal3f( 0.0, -1.0, 0.0 );
|
||||
|
||||
// Draw vertical grid lines (parallel to Z axis)
|
||||
double posy = -brd_center_pos.y * scale;
|
||||
|
||||
for( int ii = 0; ; ii++ )
|
||||
{
|
||||
if( (ii % 5) )
|
||||
SetGLColor( gridcolor, transparency );
|
||||
else
|
||||
SetGLColor( gridcolor_marker, transparency );
|
||||
|
||||
double delta = ii * aGriSizeMM * IU_PER_MM;
|
||||
|
||||
glBegin( GL_LINES );
|
||||
xmax = (brd_center_pos.x + delta) * scale;
|
||||
|
||||
glVertex3f( xmax, posy, zmin );
|
||||
glVertex3f( xmax, posy, zmax );
|
||||
glEnd();
|
||||
|
||||
if( ii != 0 )
|
||||
{
|
||||
glBegin( GL_LINES );
|
||||
xmin = (brd_center_pos.x - delta) * scale;
|
||||
glVertex3f( xmin, posy, zmin );
|
||||
glVertex3f( xmin, posy, zmax );
|
||||
glEnd();
|
||||
}
|
||||
|
||||
if( delta > xsize / 2.0f )
|
||||
break;
|
||||
}
|
||||
|
||||
// Draw horizontal grid lines on Z axis (parallel to X axis)
|
||||
for( int ii = 0; ; ii++ )
|
||||
{
|
||||
if( (ii % 5) )
|
||||
SetGLColor( gridcolor, transparency);
|
||||
else
|
||||
SetGLColor( gridcolor_marker, transparency );
|
||||
|
||||
double delta = ii * aGriSizeMM * IU_PER_MM * scale;
|
||||
|
||||
if( delta <= zmax )
|
||||
{
|
||||
// Draw grid lines on Z axis (positive Z axis coordinates)
|
||||
glBegin( GL_LINES );
|
||||
glVertex3f( xmin, posy, delta );
|
||||
glVertex3f( xmax, posy, delta );
|
||||
glEnd();
|
||||
}
|
||||
|
||||
if( delta <= -zmin && ( ii != 0 ) )
|
||||
{
|
||||
// Draw grid lines on Z axis (negative Z axis coordinates)
|
||||
glBegin( GL_LINES );
|
||||
glVertex3f( xmin, posy, -delta );
|
||||
glVertex3f( xmax, posy, -delta );
|
||||
glEnd();
|
||||
}
|
||||
|
||||
if( ( delta > zmax ) && ( delta > -zmin ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Draw 3D pads.
|
||||
void EDA_3D_CANVAS::draw3DPadHole( const D_PAD* aPad )
|
||||
{
|
||||
// Draw the pad hole
|
||||
wxSize drillsize = aPad->GetDrillSize();
|
||||
bool hasHole = drillsize.x && drillsize.y;
|
||||
|
||||
if( !hasHole )
|
||||
return;
|
||||
|
||||
// Store here the points to approximate hole by segments
|
||||
SHAPE_POLY_SET holecornersBuffer;
|
||||
int thickness = GetPrm3DVisu().GetCopperThicknessBIU();
|
||||
int height = GetPrm3DVisu().GetLayerZcoordBIU( F_Cu ) -
|
||||
GetPrm3DVisu().GetLayerZcoordBIU( B_Cu );
|
||||
|
||||
if( isRealisticMode() )
|
||||
setGLCopperColor();
|
||||
else
|
||||
SetGLColor( DARKGRAY );
|
||||
|
||||
int holeZpoz = GetPrm3DVisu().GetLayerZcoordBIU( B_Cu ) - thickness / 2;
|
||||
int holeHeight = height + thickness;
|
||||
|
||||
if( drillsize.x == drillsize.y ) // usual round hole
|
||||
{
|
||||
int hole_radius = ( drillsize.x + thickness ) / 2;
|
||||
Draw3D_ZaxisCylinder( aPad->GetPosition(),
|
||||
hole_radius, holeHeight,
|
||||
thickness, holeZpoz, GetPrm3DVisu().m_BiuTo3Dunits );
|
||||
}
|
||||
else // Oblong hole
|
||||
{
|
||||
wxPoint ends_offset;
|
||||
int width;
|
||||
|
||||
if( drillsize.x > drillsize.y ) // Horizontal oval
|
||||
{
|
||||
ends_offset.x = ( drillsize.x - drillsize.y ) / 2;
|
||||
width = drillsize.y;
|
||||
}
|
||||
else // Vertical oval
|
||||
{
|
||||
ends_offset.y = ( drillsize.y - drillsize.x ) / 2;
|
||||
width = drillsize.x;
|
||||
}
|
||||
|
||||
RotatePoint( &ends_offset, aPad->GetOrientation() );
|
||||
|
||||
wxPoint start = aPad->GetPosition() + ends_offset;
|
||||
wxPoint end = aPad->GetPosition() - ends_offset;
|
||||
int hole_radius = ( width + thickness ) / 2;
|
||||
|
||||
// Draw the hole
|
||||
Draw3D_ZaxisOblongCylinder( start, end, hole_radius, holeHeight,
|
||||
thickness, holeZpoz, GetPrm3DVisu().m_BiuTo3Dunits );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::draw3DViaHole( const VIA* aVia )
|
||||
{
|
||||
LAYER_ID top_layer, bottom_layer;
|
||||
int thickness = GetPrm3DVisu().GetCopperThicknessBIU();
|
||||
int inner_radius = (int)((float)aVia->GetDrillValue() * 1.01f) / 2.0f; // This add a bit more in order to correct a draw artifact while using tickness
|
||||
|
||||
aVia->LayerPair( &top_layer, &bottom_layer );
|
||||
|
||||
// Drawing via hole:
|
||||
if( isRealisticMode() )
|
||||
setGLCopperColor();
|
||||
else
|
||||
{
|
||||
EDA_COLOR_T color = g_ColorsSettings.GetItemColor( VIAS_VISIBLE + aVia->GetViaType() );
|
||||
SetGLColor( color );
|
||||
}
|
||||
|
||||
int height = GetPrm3DVisu().GetLayerZcoordBIU( top_layer ) -
|
||||
GetPrm3DVisu().GetLayerZcoordBIU( bottom_layer ) + thickness;
|
||||
int zpos = GetPrm3DVisu().GetLayerZcoordBIU( bottom_layer ) - thickness / 2;
|
||||
|
||||
Draw3D_ZaxisCylinder( aVia->GetStart(), inner_radius, height,
|
||||
thickness, zpos, GetPrm3DVisu().m_BiuTo3Dunits );
|
||||
}
|
||||
|
||||
/* Build a pad outline as non filled polygon, to draw pads on silkscreen layer
|
||||
* Used only to draw pads outlines on silkscreen layers.
|
||||
*/
|
||||
void EDA_3D_CANVAS::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aWidth,
|
||||
int aCircleToSegmentsCount,
|
||||
double aCorrectionFactor )
|
||||
{
|
||||
if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring
|
||||
{
|
||||
TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(),
|
||||
aPad->GetSize().x / 2, aCircleToSegmentsCount, aWidth );
|
||||
return;
|
||||
}
|
||||
|
||||
// For other shapes, draw polygon outlines
|
||||
SHAPE_POLY_SET corners;
|
||||
aPad->BuildPadShapePolygon( corners, wxSize( 0, 0 ),
|
||||
aCircleToSegmentsCount, aCorrectionFactor );
|
||||
|
||||
// Add outlines as thick segments in polygon buffer
|
||||
|
||||
const SHAPE_LINE_CHAIN& path = corners.COutline( 0 );
|
||||
|
||||
for( int ii = 0; ii < path.PointCount(); ii++ )
|
||||
{
|
||||
const VECTOR2I& a = path.CPoint( ii );
|
||||
const VECTOR2I& b = path.CPoint( ii + 1 );
|
||||
|
||||
TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
|
||||
wxPoint( a.x, a.y ),
|
||||
wxPoint( b.x, b.y ),
|
||||
aCircleToSegmentsCount, aWidth );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLfloat Get3DLayer_Z_Orientation( LAYER_NUM aLayer )
|
||||
{
|
||||
double nZ = 1.0;
|
||||
|
||||
if( ( aLayer == B_Cu )
|
||||
|| ( aLayer == B_Adhes )
|
||||
|| ( aLayer == B_Paste )
|
||||
|| ( aLayer == B_SilkS )
|
||||
|| ( aLayer == B_Mask ) )
|
||||
nZ = -1.0;
|
||||
|
||||
return nZ;
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_enums.h
|
||||
* @brief declared enumerations and flags
|
||||
*/
|
||||
|
||||
#ifndef _3D_ENUMS_H_
|
||||
#define _3D_ENUMS_H_
|
||||
|
||||
/// Flags used in rendering options
|
||||
enum DISPLAY3D_FLG {
|
||||
FL_AXIS=0, FL_ZONE,
|
||||
FL_ADHESIVE, FL_SILKSCREEN, FL_SOLDERMASK, FL_SOLDERPASTE,
|
||||
FL_COMMENTS, FL_ECO,
|
||||
|
||||
FL_MODULE_ATTRIBUTES_NORMAL,
|
||||
FL_MODULE_ATTRIBUTES_NORMAL_INSERT,
|
||||
FL_MODULE_ATTRIBUTES_VIRTUAL,
|
||||
|
||||
FL_SHOW_BOARD_BODY,
|
||||
FL_MOUSEWHEEL_PANNING,
|
||||
FL_USE_REALISTIC_MODE,
|
||||
|
||||
// OpenGL options
|
||||
FL_RENDER_OPENGL_SHOW_MODEL_BBOX,
|
||||
FL_RENDER_OPENGL_COPPER_THICKNESS,
|
||||
|
||||
// Raytracing options
|
||||
FL_RENDER_RAYTRACING_SHADOWS,
|
||||
FL_RENDER_RAYTRACING_BACKFLOOR,
|
||||
FL_RENDER_RAYTRACING_REFRACTIONS,
|
||||
FL_RENDER_RAYTRACING_REFLECTIONS,
|
||||
FL_RENDER_RAYTRACING_POST_PROCESSING,
|
||||
FL_RENDER_RAYTRACING_ANTI_ALIASING,
|
||||
FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES,
|
||||
FL_LAST
|
||||
};
|
||||
|
||||
|
||||
/// Camera types
|
||||
enum CAMERA_TYPE
|
||||
{
|
||||
CAMERA_TRACKBALL
|
||||
};
|
||||
|
||||
|
||||
/// Grid types
|
||||
enum GRID3D_TYPE
|
||||
{
|
||||
GRID3D_NONE,
|
||||
GRID3D_1MM,
|
||||
GRID3D_2P5MM,
|
||||
GRID3D_5MM,
|
||||
GRID3D_10MM
|
||||
};
|
||||
|
||||
|
||||
/// Render engine mode
|
||||
enum RENDER_ENGINE
|
||||
{
|
||||
RENDER_ENGINE_OPENGL_LEGACY,
|
||||
RENDER_ENGINE_RAYTRACING,
|
||||
};
|
||||
|
||||
|
||||
/// Render 3d model shape materials mode
|
||||
enum MATERIAL_MODE
|
||||
{
|
||||
MATERIAL_MODE_NORMAL, ///< Use all material properties from model file
|
||||
MATERIAL_MODE_DIFFUSE_ONLY, ///< Use only diffuse material properties
|
||||
MATERIAL_MODE_CAD_MODE ///< Use a gray shading based on diffuse material
|
||||
};
|
||||
|
||||
#endif // _3D_ENUMS_H_
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_fastmath.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
|
||||
#include "3d_fastmath.h"
|
||||
|
||||
|
||||
// Fast Float Random Numbers
|
||||
// a small and fast implementation for random float numbers in the range [-1,1]
|
||||
// References : Posted by dominik.ries[AT]gmail[DOT]com
|
||||
// http://www.musicdsp.org/showone.php?id=273
|
||||
|
||||
|
||||
// set the initial seed to whatever you like
|
||||
static int s_randSeed = 1;
|
||||
|
||||
// fast rand float, using full 32bit precision
|
||||
// returns in the range [-1, 1] (not confirmed)
|
||||
float Fast_RandFloat()
|
||||
{
|
||||
s_randSeed *= 16807;
|
||||
|
||||
return (float)s_randSeed * 4.6566129e-010f;
|
||||
}
|
||||
|
||||
|
||||
// Fast rand, as described here:
|
||||
// http://wiki.osdev.org/Random_Number_Generator
|
||||
|
||||
static unsigned long int s_nextRandSeed = 1;
|
||||
|
||||
int Fast_rand( void ) // RAND_MAX assumed to be 32767
|
||||
{
|
||||
s_nextRandSeed = s_nextRandSeed * 1103515245 + 12345;
|
||||
|
||||
return (unsigned int)(s_nextRandSeed >> 16) & 0x7FFF;
|
||||
}
|
||||
|
||||
void Fast_srand( unsigned int seed )
|
||||
{
|
||||
s_nextRandSeed = seed;
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_fastmath.h
|
||||
* @brief Defines math related functions
|
||||
*/
|
||||
|
||||
#ifndef _3D_FASTMATH_H
|
||||
#define _3D_FASTMATH_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
// Define this flag to use fast math optimizations
|
||||
#define FASTMATH_USE
|
||||
|
||||
#define L1_CACHE_LINE_SIZE 64
|
||||
|
||||
#ifdef FASTMATH_USE
|
||||
#define INTFLOORF(s) (lrintf( (s) - (0.5f - FLT_EPSILON) ))
|
||||
#else
|
||||
#define INTFLOORF(s) ((int)( floor(s) ))
|
||||
#endif
|
||||
|
||||
|
||||
// Fast Float Random Numbers
|
||||
// a small and fast implementation for random float numbers in the range [-1,1]
|
||||
// This is not thread safe
|
||||
float Fast_RandFloat();
|
||||
|
||||
int Fast_rand( void );
|
||||
void Fast_srand( unsigned int seed );
|
||||
|
||||
/**
|
||||
* This part contains some functions from the PBRT 3 source code.
|
||||
* https://github.com/mmp/pbrt-v3/blob/master/src/core/pbrt.h
|
||||
*/
|
||||
|
||||
/*
|
||||
pbrt source code is Copyright(c) 1998-2015
|
||||
Matt Pharr, Greg Humphreys, and Wenzel Jakob.
|
||||
|
||||
This file is part of pbrt.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// Global Inline Functions
|
||||
inline uint32_t FloatToBits( float f )
|
||||
{
|
||||
uint32_t ui;
|
||||
|
||||
memcpy( &ui, &f, sizeof( float ) );
|
||||
|
||||
return ui;
|
||||
}
|
||||
|
||||
|
||||
inline float BitsToFloat( uint32_t ui )
|
||||
{
|
||||
float f;
|
||||
|
||||
memcpy( &f, &ui, sizeof (uint32_t ) );
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
inline uint64_t FloatToBits( double f )
|
||||
{
|
||||
uint64_t ui;
|
||||
|
||||
memcpy( &ui, &f, sizeof( double ) );
|
||||
|
||||
return ui;
|
||||
}
|
||||
|
||||
|
||||
inline double BitsToFloat( uint64_t ui )
|
||||
{
|
||||
double f;
|
||||
|
||||
memcpy( &f, &ui, sizeof( uint64_t ) );
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
inline float NextFloatUp( float v )
|
||||
{
|
||||
// Handle infinity and negative zero for _NextFloatUp()_
|
||||
if( std::isinf( v ) && (v > 0.) )
|
||||
return v;
|
||||
|
||||
if( v == -0.f )
|
||||
v = 0.f;
|
||||
|
||||
// Advance _v_ to next higher float
|
||||
uint32_t ui = FloatToBits( v );
|
||||
|
||||
if( v >= 0. )
|
||||
++ui;
|
||||
else
|
||||
--ui;
|
||||
|
||||
return BitsToFloat( ui );
|
||||
}
|
||||
|
||||
|
||||
inline float NextFloatDown( float v )
|
||||
{
|
||||
// Handle infinity and positive zero for _NextFloatDown()_
|
||||
if( std::isinf( v ) && (v < 0.) )
|
||||
return v;
|
||||
|
||||
if( v == 0.f )
|
||||
v = -0.f;
|
||||
|
||||
uint32_t ui = FloatToBits( v );
|
||||
|
||||
if( v > 0. )
|
||||
--ui;
|
||||
else
|
||||
++ui;
|
||||
|
||||
return BitsToFloat( ui );
|
||||
}
|
||||
|
||||
#endif // 3D_FASTMATH_H
|
||||
@@ -0,0 +1,915 @@
|
||||
/**
|
||||
* @file 3d_frame.cpp
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <kiface_i.h>
|
||||
#include <pgm_base.h>
|
||||
#include <macros.h>
|
||||
|
||||
#include <3d_viewer.h>
|
||||
#include <3d_canvas.h>
|
||||
#include <info3d_visu.h>
|
||||
#include <trackball.h>
|
||||
|
||||
#include <wx/colordlg.h>
|
||||
#include <3d_viewer_id.h>
|
||||
#include <wxBasePcbFrame.h>
|
||||
|
||||
INFO3D_VISU g_Parm_3D_Visu;
|
||||
|
||||
// Key to store 3D Viewer config:
|
||||
static const wxChar keyBgColor_Red[] = wxT( "BgColor_Red" );
|
||||
static const wxChar keyBgColor_Green[] = wxT( "BgColor_Green" );
|
||||
static const wxChar keyBgColor_Blue[] = wxT( "BgColor_Blue" );
|
||||
|
||||
static const wxChar keyBgColor_Red_Top[] = wxT( "BgColor_Red_Top" );
|
||||
static const wxChar keyBgColor_Green_Top[] = wxT( "BgColor_Green_Top" );
|
||||
static const wxChar keyBgColor_Blue_Top[] = wxT( "BgColor_Blue_Top" );
|
||||
|
||||
static const wxChar keySMaskColor_Red[] = wxT( "SMaskColor_Red" );
|
||||
static const wxChar keySMaskColor_Green[] = wxT( "SMaskColor_Green" );
|
||||
static const wxChar keySMaskColor_Blue[] = wxT( "SMaskColor_Blue" );
|
||||
|
||||
static const wxChar keySPasteColor_Red[] = wxT( "SPasteColor_Red" );
|
||||
static const wxChar keySPasteColor_Green[] = wxT( "SPasteColor_Green" );
|
||||
static const wxChar keySPasteColor_Blue[] = wxT( "SPasteColor_Blue" );
|
||||
|
||||
static const wxChar keySilkColor_Red[] = wxT( "SilkColor_Red" );
|
||||
static const wxChar keySilkColor_Green[] = wxT( "SilkColor_Green" );
|
||||
static const wxChar keySilkColor_Blue[] = wxT( "SilkColor_Blue" );
|
||||
|
||||
static const wxChar keyCopperColor_Red[] = wxT( "CopperColor_Red" );
|
||||
static const wxChar keyCopperColor_Green[] = wxT( "CopperColor_Green" );
|
||||
static const wxChar keyCopperColor_Blue[] = wxT( "CopperColor_Blue" );
|
||||
|
||||
static const wxChar keyBoardBodyColor_Red[] = wxT( "BoardBodyColor_Red" );
|
||||
static const wxChar keyBoardBodyColor_Green[] = wxT( "BoardBodyColor_Green" );
|
||||
static const wxChar keyBoardBodyColor_Blue[]= wxT( "BoardBodyColor_Blue" );
|
||||
|
||||
static const wxChar keyMousewheelPanning[] = wxT( "MousewheelPAN3D" );
|
||||
|
||||
static const wxChar keyShowRealisticMode[] = wxT( "ShowRealisticMode" );
|
||||
static const wxChar keyRenderShadows[] = wxT( "Render_Shadows" );
|
||||
static const wxChar keyRenderRemoveHoles[] = wxT( "Render_RemoveHoles" );
|
||||
static const wxChar keyRenderTextures[] = wxT( "Render_Textures" );
|
||||
static const wxChar keyRenderSmoothNormals[] = wxT( "Render_Smooth_Normals" );
|
||||
static const wxChar keyRenderUseModelNormals[] =wxT( "Render_Use_Model_Normals" );
|
||||
static const wxChar keyRenderMaterial[] = wxT( "Render_Material" );
|
||||
static const wxChar keyRenderShowModelBBox[] = wxT( "Render_ShowModelBoudingBoxes" );
|
||||
|
||||
static const wxChar keyShowAxis[] = wxT( "ShowAxis" );
|
||||
static const wxChar keyShowGrid[] = wxT( "ShowGrid3D" );
|
||||
static const wxChar keyShowGridSize[] = wxT( "Grid3DSize" );
|
||||
static const wxChar keyShowZones[] = wxT( "ShowZones" );
|
||||
static const wxChar keyShowFootprints[] = wxT( "ShowFootprints" );
|
||||
static const wxChar keyShowCopperThickness[] = wxT( "ShowCopperThickness" );
|
||||
static const wxChar keyShowAdhesiveLayers[] = wxT( "ShowAdhesiveLayers" );
|
||||
static const wxChar keyShowSilkScreenLayers[] = wxT( "ShowSilkScreenLayers" );
|
||||
static const wxChar keyShowSolderMaskLayers[] = wxT( "ShowSolderMasLayers" );
|
||||
static const wxChar keyShowSolderPasteLayers[] =wxT( "ShowSolderPasteLayers" );
|
||||
static const wxChar keyShowCommentsLayer[] = wxT( "ShowCommentsLayers" );
|
||||
static const wxChar keyShowBoardBody[] = wxT( "ShowBoardBody" );
|
||||
static const wxChar keyShowEcoLayers[] = wxT( "ShowEcoLayers" );
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( EDA_3D_FRAME, EDA_BASE_FRAME )
|
||||
EVT_ACTIVATE( EDA_3D_FRAME::OnActivate )
|
||||
|
||||
EVT_TOOL_RANGE( ID_ZOOM_IN, ID_ZOOM_PAGE, EDA_3D_FRAME::Process_Zoom )
|
||||
EVT_TOOL_RANGE( ID_START_COMMAND_3D, ID_END_COMMAND_3D,
|
||||
EDA_3D_FRAME::Process_Special_Functions )
|
||||
EVT_TOOL( ID_TOOL_SET_VISIBLE_ITEMS, EDA_3D_FRAME::Process_Special_Functions )
|
||||
EVT_MENU( wxID_EXIT, EDA_3D_FRAME::Exit3DFrame )
|
||||
EVT_MENU( ID_MENU_SCREENCOPY_PNG, EDA_3D_FRAME::Process_Special_Functions )
|
||||
EVT_MENU( ID_MENU_SCREENCOPY_JPEG, EDA_3D_FRAME::Process_Special_Functions )
|
||||
|
||||
EVT_MENU_RANGE( ID_MENU3D_GRID, ID_MENU3D_GRID_END,
|
||||
EDA_3D_FRAME::On3DGridSelection )
|
||||
|
||||
EVT_CLOSE( EDA_3D_FRAME::OnCloseWindow )
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
EDA_3D_FRAME::EDA_3D_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent,
|
||||
const wxString& aTitle, long style ) :
|
||||
KIWAY_PLAYER( aKiway, aParent, FRAME_PCB_DISPLAY3D, aTitle,
|
||||
wxDefaultPosition, wxDefaultSize, style, wxT( "Frame3D" ) )
|
||||
{
|
||||
m_canvas = NULL;
|
||||
m_reloadRequest = false;
|
||||
m_ortho = false;
|
||||
|
||||
// Give it an icon
|
||||
wxIcon icon;
|
||||
icon.CopyFromBitmap( KiBitmap( icon_3d_xpm ) );
|
||||
SetIcon( icon );
|
||||
|
||||
LoadSettings( config() );
|
||||
SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );
|
||||
|
||||
// Create the status line
|
||||
static const int status_dims[4] = { -1, 130, 130, 170 };
|
||||
|
||||
CreateStatusBar( DIM( status_dims ) );
|
||||
SetStatusWidths( DIM( status_dims ), status_dims );
|
||||
|
||||
CreateMenuBar();
|
||||
ReCreateMainToolbar();
|
||||
|
||||
// Make a EDA_3D_CANVAS
|
||||
// Note: We try to use anti aliasing if the graphic card allows that,
|
||||
// but only on wxWidgets >= 3.0.0 (this option does not exist on wxWidgets 2.8)
|
||||
int attrs[] = { // This array should be 2*n+1
|
||||
// Sadly wxwidgets / glx < 13 allowed
|
||||
// a thing named "boolean attributes" that don't take a value.
|
||||
// (See src/unix/glx11.cpp -> wxGLCanvasX11::ConvertWXAttrsToGL() ).
|
||||
// To avoid problems due to this, just specify those attributes twice.
|
||||
// Only WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_STEREO are such boolean
|
||||
// attributes.
|
||||
|
||||
// Boolean attributes (using itself at padding):
|
||||
WX_GL_RGBA, WX_GL_RGBA,
|
||||
WX_GL_DOUBLEBUFFER, WX_GL_DOUBLEBUFFER,
|
||||
|
||||
// Normal attributes with values:
|
||||
WX_GL_DEPTH_SIZE, 16,
|
||||
WX_GL_STENCIL_SIZE, 1,
|
||||
WX_GL_SAMPLE_BUFFERS, 1, // Enable multisampling support (antialiasing).
|
||||
WX_GL_SAMPLES, 0, // Disable AA for the start.
|
||||
0 }; // NULL termination
|
||||
|
||||
|
||||
// Check if the canvas supports multisampling.
|
||||
if( EDA_3D_CANVAS::IsDisplaySupported( attrs ) )
|
||||
{
|
||||
// Check for possible sample sizes, start form the top.
|
||||
int maxSamples = 8; // Any higher doesn't change anything.
|
||||
int samplesOffset = 0;
|
||||
|
||||
for( unsigned int ii = 0; ii < DIM( attrs ); ii += 2 )
|
||||
{
|
||||
if( attrs[ii] == WX_GL_SAMPLES )
|
||||
{
|
||||
samplesOffset = ii+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
attrs[samplesOffset] = maxSamples;
|
||||
|
||||
for( ; maxSamples > 0 && !EDA_3D_CANVAS::IsDisplaySupported( attrs );
|
||||
maxSamples = maxSamples>>1 )
|
||||
{
|
||||
attrs[samplesOffset] = maxSamples;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable multisampling
|
||||
for( unsigned int ii = 0; ii < DIM( attrs ); ii += 2 )
|
||||
{
|
||||
if( attrs[ii] == WX_GL_SAMPLE_BUFFERS )
|
||||
{
|
||||
attrs[ii+1] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_canvas = new EDA_3D_CANVAS( this, attrs );
|
||||
|
||||
m_auimgr.SetManagedWindow( this );
|
||||
|
||||
|
||||
EDA_PANEINFO horiztb;
|
||||
horiztb.HorizontalToolbarPane();
|
||||
|
||||
m_auimgr.AddPane( m_mainToolBar,
|
||||
wxAuiPaneInfo( horiztb ).Name( wxT( "m_mainToolBar" ) ).Top() );
|
||||
|
||||
m_auimgr.AddPane( m_canvas,
|
||||
wxAuiPaneInfo().Name( wxT( "DrawFrame" ) ).CentrePane() );
|
||||
|
||||
m_auimgr.Update();
|
||||
|
||||
// Fixes bug in Windows (XP and possibly others) where the canvas requires the focus
|
||||
// in order to receive mouse events. Otherwise, the user has to click somewhere on
|
||||
// the canvas before it will respond to mouse wheel events.
|
||||
m_canvas->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
EDA_3D_FRAME::~EDA_3D_FRAME()
|
||||
{
|
||||
m_auimgr.UnInit();
|
||||
}
|
||||
|
||||
void EDA_3D_FRAME::Exit3DFrame( wxCommandEvent& event )
|
||||
{
|
||||
Close( true );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::OnCloseWindow( wxCloseEvent& Event )
|
||||
{
|
||||
if( Parent() )
|
||||
Parent()->m_Draw3DFrame = NULL;
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::LoadSettings( wxConfigBase* aCfg )
|
||||
{
|
||||
EDA_BASE_FRAME::LoadSettings( aCfg );
|
||||
|
||||
INFO3D_VISU& prms = GetPrm3DVisu();
|
||||
|
||||
aCfg->Read( keyBgColor_Red, &GetPrm3DVisu().m_BgColor.m_Red, 0.4 );
|
||||
aCfg->Read( keyBgColor_Green, &GetPrm3DVisu().m_BgColor.m_Green, 0.4 );
|
||||
aCfg->Read( keyBgColor_Blue, &GetPrm3DVisu().m_BgColor.m_Blue, 0.5 );
|
||||
|
||||
aCfg->Read( keyBgColor_Red_Top, &GetPrm3DVisu().m_BgColor_Top.m_Red, 0.8 );
|
||||
aCfg->Read( keyBgColor_Green_Top, &GetPrm3DVisu().m_BgColor_Top.m_Green, 0.8 );
|
||||
aCfg->Read( keyBgColor_Blue_Top, &GetPrm3DVisu().m_BgColor_Top.m_Blue, 0.9 );
|
||||
|
||||
// m_SolderMaskColor default value = dark grey-green
|
||||
aCfg->Read( keySMaskColor_Red, &GetPrm3DVisu().m_SolderMaskColor.m_Red, 100.0 * 0.2 / 255.0 );
|
||||
aCfg->Read( keySMaskColor_Green, &GetPrm3DVisu().m_SolderMaskColor.m_Green, 255.0 * 0.2 / 255.0 );
|
||||
aCfg->Read( keySMaskColor_Blue, &GetPrm3DVisu().m_SolderMaskColor.m_Blue, 180.0 * 0.2 / 255.0 );
|
||||
|
||||
// m_SolderPasteColor default value = light grey
|
||||
aCfg->Read( keySPasteColor_Red, &GetPrm3DVisu().m_SolderPasteColor.m_Red, 128.0 /255.0 );
|
||||
aCfg->Read( keySPasteColor_Green, &GetPrm3DVisu().m_SolderPasteColor.m_Green, 128.0 /255.0 );
|
||||
aCfg->Read( keySPasteColor_Blue, &GetPrm3DVisu().m_SolderPasteColor.m_Blue, 128.0 /255.0 );
|
||||
|
||||
// m_SilkScreenColor default value = white
|
||||
aCfg->Read( keySilkColor_Red, &GetPrm3DVisu().m_SilkScreenColor.m_Red, 0.9 );
|
||||
aCfg->Read( keySilkColor_Green, &GetPrm3DVisu().m_SilkScreenColor.m_Green, 0.9 );
|
||||
aCfg->Read( keySilkColor_Blue, &GetPrm3DVisu().m_SilkScreenColor.m_Blue, 0.9 );
|
||||
|
||||
// m_CopperColor default value = gold
|
||||
aCfg->Read( keyCopperColor_Red, &GetPrm3DVisu().m_CopperColor.m_Red, 255.0 * 0.7 / 255.0 );
|
||||
aCfg->Read( keyCopperColor_Green, &GetPrm3DVisu().m_CopperColor.m_Green, 223.0 * 0.7 / 255.0 );
|
||||
aCfg->Read( keyCopperColor_Blue, &GetPrm3DVisu().m_CopperColor.m_Blue, 0.0 /255.0 );
|
||||
|
||||
// m_BoardBodyColor default value = FR4, in realistic mode
|
||||
aCfg->Read( keyBoardBodyColor_Red, &GetPrm3DVisu().m_BoardBodyColor.m_Red, 51.0 / 255.0 );
|
||||
aCfg->Read( keyBoardBodyColor_Green, &GetPrm3DVisu().m_BoardBodyColor.m_Green, 43.0 / 255.0 );
|
||||
aCfg->Read( keyBoardBodyColor_Blue, &GetPrm3DVisu().m_BoardBodyColor.m_Blue, 22.0 /255.0 );
|
||||
|
||||
bool tmp;
|
||||
aCfg->Read( keyMousewheelPanning, &tmp, false );
|
||||
prms.SetFlag( FL_MOUSEWHEEL_PANNING, tmp );
|
||||
|
||||
aCfg->Read( keyShowRealisticMode, &tmp, false );
|
||||
prms.SetFlag( FL_USE_REALISTIC_MODE, tmp );
|
||||
|
||||
aCfg->Read( keyRenderShadows, &tmp, false );
|
||||
prms.SetFlag( FL_RENDER_SHADOWS, tmp );
|
||||
|
||||
aCfg->Read( keyRenderRemoveHoles, &tmp, false );
|
||||
prms.SetFlag( FL_RENDER_SHOW_HOLES_IN_ZONES, tmp );
|
||||
|
||||
aCfg->Read( keyRenderTextures, &tmp, false );
|
||||
prms.SetFlag( FL_RENDER_TEXTURES, tmp );
|
||||
|
||||
aCfg->Read( keyRenderSmoothNormals, &tmp, false );
|
||||
prms.SetFlag( FL_RENDER_SMOOTH_NORMALS, tmp );
|
||||
|
||||
aCfg->Read( keyRenderUseModelNormals, &tmp, false );
|
||||
prms.SetFlag( FL_RENDER_USE_MODEL_NORMALS, tmp );
|
||||
|
||||
aCfg->Read( keyRenderMaterial, &tmp, false );
|
||||
prms.SetFlag( FL_RENDER_MATERIAL, tmp );
|
||||
|
||||
aCfg->Read( keyRenderShowModelBBox, &tmp, false );
|
||||
prms.SetFlag( FL_RENDER_SHOW_MODEL_BBOX, tmp );
|
||||
|
||||
aCfg->Read( keyShowAxis, &tmp, true );
|
||||
prms.SetFlag( FL_AXIS, tmp );
|
||||
|
||||
aCfg->Read( keyShowGrid, &tmp, true );
|
||||
prms.SetFlag( FL_GRID, tmp );
|
||||
|
||||
aCfg->Read( keyShowGridSize, &prms.m_3D_Grid, 10.0 );
|
||||
|
||||
aCfg->Read( keyShowFootprints, &tmp, true );
|
||||
prms.SetFlag( FL_MODULE, tmp );
|
||||
|
||||
aCfg->Read( keyShowCopperThickness, &tmp, false );
|
||||
prms.SetFlag( FL_USE_COPPER_THICKNESS, tmp );
|
||||
|
||||
aCfg->Read( keyShowZones, &tmp, true );
|
||||
prms.SetFlag( FL_ZONE, tmp );
|
||||
|
||||
aCfg->Read( keyShowAdhesiveLayers, &tmp, true );
|
||||
prms.SetFlag( FL_ADHESIVE, tmp );
|
||||
|
||||
aCfg->Read( keyShowSilkScreenLayers, &tmp, true );
|
||||
prms.SetFlag( FL_SILKSCREEN, tmp );
|
||||
|
||||
aCfg->Read( keyShowSolderMaskLayers, &tmp, true );
|
||||
prms.SetFlag( FL_SOLDERMASK, tmp );
|
||||
|
||||
aCfg->Read( keyShowSolderPasteLayers, &tmp, true );
|
||||
prms.SetFlag( FL_SOLDERPASTE, tmp );
|
||||
|
||||
aCfg->Read( keyShowCommentsLayer, &tmp, true );
|
||||
prms.SetFlag( FL_COMMENTS, tmp );
|
||||
|
||||
aCfg->Read( keyShowEcoLayers, &tmp, true );
|
||||
prms.SetFlag( FL_ECO, tmp );
|
||||
|
||||
aCfg->Read( keyShowBoardBody, &tmp, true );
|
||||
prms.SetFlag( FL_SHOW_BOARD_BODY, tmp );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::SaveSettings( wxConfigBase* aCfg )
|
||||
{
|
||||
EDA_BASE_FRAME::SaveSettings( aCfg );
|
||||
|
||||
INFO3D_VISU& prms = GetPrm3DVisu();
|
||||
|
||||
aCfg->Write( keyBgColor_Red, GetPrm3DVisu().m_BgColor.m_Red );
|
||||
aCfg->Write( keyBgColor_Green, GetPrm3DVisu().m_BgColor.m_Green );
|
||||
aCfg->Write( keyBgColor_Blue, GetPrm3DVisu().m_BgColor.m_Blue );
|
||||
|
||||
aCfg->Write( keyBgColor_Red_Top, GetPrm3DVisu().m_BgColor_Top.m_Red );
|
||||
aCfg->Write( keyBgColor_Green_Top, GetPrm3DVisu().m_BgColor_Top.m_Green );
|
||||
aCfg->Write( keyBgColor_Blue_Top, GetPrm3DVisu().m_BgColor_Top.m_Blue );
|
||||
|
||||
aCfg->Write( keySMaskColor_Red, GetPrm3DVisu().m_SolderMaskColor.m_Red );
|
||||
aCfg->Write( keySMaskColor_Green, GetPrm3DVisu().m_SolderMaskColor.m_Green );
|
||||
aCfg->Write( keySMaskColor_Blue, GetPrm3DVisu().m_SolderMaskColor.m_Blue );
|
||||
|
||||
aCfg->Write( keySPasteColor_Red, GetPrm3DVisu().m_SolderPasteColor.m_Red );
|
||||
aCfg->Write( keySPasteColor_Green, GetPrm3DVisu().m_SolderPasteColor.m_Green );
|
||||
aCfg->Write( keySPasteColor_Blue, GetPrm3DVisu().m_SolderPasteColor.m_Blue );
|
||||
|
||||
aCfg->Write( keySilkColor_Red, GetPrm3DVisu().m_SilkScreenColor.m_Red );
|
||||
aCfg->Write( keySilkColor_Green, GetPrm3DVisu().m_SilkScreenColor.m_Green );
|
||||
aCfg->Write( keySilkColor_Blue, GetPrm3DVisu().m_SilkScreenColor.m_Blue );
|
||||
|
||||
aCfg->Write( keyCopperColor_Red, GetPrm3DVisu().m_CopperColor.m_Red );
|
||||
aCfg->Write( keyCopperColor_Green, GetPrm3DVisu().m_CopperColor.m_Green );
|
||||
aCfg->Write( keyCopperColor_Blue, GetPrm3DVisu().m_CopperColor.m_Blue );
|
||||
|
||||
aCfg->Write( keyBoardBodyColor_Red, GetPrm3DVisu().m_BoardBodyColor.m_Red );
|
||||
aCfg->Write( keyBoardBodyColor_Green, GetPrm3DVisu().m_BoardBodyColor.m_Green );
|
||||
aCfg->Write( keyBoardBodyColor_Blue, GetPrm3DVisu().m_BoardBodyColor.m_Blue );
|
||||
|
||||
aCfg->Write( keyMousewheelPanning, prms.GetFlag( FL_MOUSEWHEEL_PANNING ) );
|
||||
|
||||
aCfg->Write( keyShowRealisticMode, prms.GetFlag( FL_USE_REALISTIC_MODE ) );
|
||||
|
||||
aCfg->Write( keyRenderShadows, prms.GetFlag( FL_RENDER_SHADOWS ) );
|
||||
aCfg->Write( keyRenderRemoveHoles, prms.GetFlag( FL_RENDER_SHOW_HOLES_IN_ZONES ) );
|
||||
aCfg->Write( keyRenderTextures, prms.GetFlag( FL_RENDER_TEXTURES ) );
|
||||
aCfg->Write( keyRenderSmoothNormals, prms.GetFlag( FL_RENDER_SMOOTH_NORMALS ) );
|
||||
aCfg->Write( keyRenderUseModelNormals, prms.GetFlag( FL_RENDER_USE_MODEL_NORMALS ) );
|
||||
aCfg->Write( keyRenderMaterial, prms.GetFlag( FL_RENDER_MATERIAL ) );
|
||||
aCfg->Write( keyRenderShowModelBBox, prms.GetFlag( FL_RENDER_SHOW_MODEL_BBOX ) );
|
||||
|
||||
aCfg->Write( keyShowAxis, prms.GetFlag( FL_AXIS ) );
|
||||
aCfg->Write( keyShowGrid, prms.GetFlag( FL_GRID ) );
|
||||
aCfg->Write( keyShowGridSize, prms.m_3D_Grid );
|
||||
aCfg->Write( keyShowFootprints, prms.GetFlag( FL_MODULE ) );
|
||||
aCfg->Write( keyShowCopperThickness, prms.GetFlag( FL_USE_COPPER_THICKNESS ) );
|
||||
aCfg->Write( keyShowZones, prms.GetFlag( FL_ZONE ) );
|
||||
aCfg->Write( keyShowAdhesiveLayers, prms.GetFlag( FL_ADHESIVE ) );
|
||||
aCfg->Write( keyShowSilkScreenLayers, prms.GetFlag( FL_SILKSCREEN ) );
|
||||
aCfg->Write( keyShowSolderMaskLayers, prms.GetFlag( FL_SOLDERMASK ) );
|
||||
aCfg->Write( keyShowSolderPasteLayers, prms.GetFlag( FL_SOLDERPASTE ) );
|
||||
aCfg->Write( keyShowCommentsLayer, prms.GetFlag( FL_COMMENTS ) );
|
||||
aCfg->Write( keyShowEcoLayers, prms.GetFlag( FL_ECO ) );
|
||||
aCfg->Write( keyShowBoardBody, prms.GetFlag( FL_SHOW_BOARD_BODY ) );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::Process_Zoom( wxCommandEvent& event )
|
||||
{
|
||||
int ii;
|
||||
|
||||
switch( event.GetId() )
|
||||
{
|
||||
case ID_ZOOM_PAGE:
|
||||
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
||||
|
||||
GetPrm3DVisu().m_Zoom = 1.0;
|
||||
m_canvas->SetOffset( 0.0, 0.0 );
|
||||
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
break;
|
||||
|
||||
case ID_ZOOM_IN:
|
||||
GetPrm3DVisu().m_Zoom /= 1.2;
|
||||
|
||||
if( GetPrm3DVisu().m_Zoom <= 0.01 )
|
||||
GetPrm3DVisu().m_Zoom = 0.01;
|
||||
|
||||
break;
|
||||
|
||||
case ID_ZOOM_OUT:
|
||||
GetPrm3DVisu().m_Zoom *= 1.2;
|
||||
break;
|
||||
|
||||
case ID_ZOOM_REDRAW:
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
m_canvas->Refresh( false );
|
||||
m_canvas->DisplayStatus();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
double EDA_3D_FRAME::BestZoom()
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event )
|
||||
{
|
||||
#define ROT_ANGLE 10.0
|
||||
int id = event.GetId();
|
||||
bool isChecked = event.IsChecked();
|
||||
|
||||
switch( id )
|
||||
{
|
||||
case ID_TOOL_SET_VISIBLE_ITEMS:
|
||||
Install_3D_ViewOptionDialog( event );
|
||||
break;
|
||||
|
||||
case ID_RELOAD3D_BOARD:
|
||||
m_reloadRequest = true;
|
||||
NewDisplay();
|
||||
return;
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_X_POS:
|
||||
GetPrm3DVisu().m_ROTX += ROT_ANGLE;
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_X_NEG:
|
||||
GetPrm3DVisu().m_ROTX -= ROT_ANGLE;
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_Y_POS:
|
||||
GetPrm3DVisu().m_ROTY += ROT_ANGLE;
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_Y_NEG:
|
||||
GetPrm3DVisu().m_ROTY -= ROT_ANGLE;
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_Z_POS:
|
||||
GetPrm3DVisu().m_ROTZ += ROT_ANGLE;
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_Z_NEG:
|
||||
GetPrm3DVisu().m_ROTZ -= ROT_ANGLE;
|
||||
break;
|
||||
|
||||
case ID_MOVE3D_LEFT:
|
||||
m_canvas->SetView3D( WXK_LEFT );
|
||||
return;
|
||||
|
||||
case ID_MOVE3D_RIGHT:
|
||||
m_canvas->SetView3D( WXK_RIGHT );
|
||||
return;
|
||||
|
||||
case ID_MOVE3D_UP:
|
||||
m_canvas->SetView3D( WXK_UP );
|
||||
return;
|
||||
|
||||
case ID_MOVE3D_DOWN:
|
||||
m_canvas->SetView3D( WXK_DOWN );
|
||||
return;
|
||||
|
||||
case ID_ORTHO:
|
||||
ToggleOrtho();
|
||||
return;
|
||||
|
||||
case ID_TOOL_SCREENCOPY_TOCLIBBOARD:
|
||||
case ID_MENU_SCREENCOPY_PNG:
|
||||
case ID_MENU_SCREENCOPY_JPEG:
|
||||
m_canvas->TakeScreenshot( event );
|
||||
break;
|
||||
|
||||
case ID_MENU3D_BGCOLOR_BOTTOM_SELECTION:
|
||||
if( Set3DColorFromUser( GetPrm3DVisu().m_BgColor, _( "Background Color, Bottom" ) ) )
|
||||
m_canvas->Refresh( true );
|
||||
return;
|
||||
|
||||
case ID_MENU3D_BGCOLOR_TOP_SELECTION:
|
||||
if( Set3DColorFromUser( GetPrm3DVisu().m_BgColor_Top, _( "Background Color, Top" ) ) )
|
||||
m_canvas->Refresh( true );
|
||||
return;
|
||||
|
||||
case ID_MENU3D_SILKSCREEN_COLOR_SELECTION:
|
||||
Set3DSilkScreenColorFromUser();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_SOLDERMASK_COLOR_SELECTION:
|
||||
Set3DSolderMaskColorFromUser();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_SOLDERPASTE_COLOR_SELECTION:
|
||||
Set3DSolderPasteColorFromUser();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_COPPER_COLOR_SELECTION:
|
||||
Set3DCopperColorFromUser();
|
||||
break;
|
||||
|
||||
case ID_MENU3D_PCB_BODY_COLOR_SELECTION:
|
||||
Set3DBoardBodyColorFromUser();
|
||||
break;
|
||||
|
||||
case ID_MENU3D_MOUSEWHEEL_PANNING:
|
||||
GetPrm3DVisu().SetFlag( FL_MOUSEWHEEL_PANNING, isChecked );
|
||||
return;
|
||||
|
||||
case ID_MENU3D_REALISTIC_MODE:
|
||||
GetPrm3DVisu().SetFlag( FL_USE_REALISTIC_MODE, isChecked );
|
||||
GetMenuBar()->FindItem( ID_MENU3D_COMMENTS_ONOFF )->Enable( !isChecked );
|
||||
GetMenuBar()->FindItem( ID_MENU3D_ECO_ONOFF )->Enable( !isChecked );
|
||||
NewDisplay();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_FL_RENDER_SHADOWS:
|
||||
GetPrm3DVisu().SetFlag( FL_RENDER_SHADOWS, isChecked );
|
||||
NewDisplay();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_FL_RENDER_SHOW_HOLES_IN_ZONES:
|
||||
GetPrm3DVisu().SetFlag( FL_RENDER_SHOW_HOLES_IN_ZONES, isChecked );
|
||||
NewDisplay();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_FL_RENDER_TEXTURES:
|
||||
GetPrm3DVisu().SetFlag( FL_RENDER_TEXTURES, isChecked );
|
||||
NewDisplay(GL_ID_BOARD);
|
||||
NewDisplay(GL_ID_TECH_LAYERS);
|
||||
return;
|
||||
|
||||
case ID_MENU3D_FL_RENDER_SMOOTH_NORMALS:
|
||||
GetPrm3DVisu().SetFlag( FL_RENDER_SMOOTH_NORMALS, isChecked );
|
||||
NewDisplay();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_FL_RENDER_USE_MODEL_NORMALS:
|
||||
GetPrm3DVisu().SetFlag( FL_RENDER_USE_MODEL_NORMALS, isChecked );
|
||||
NewDisplay();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_FL_RENDER_MATERIAL:
|
||||
GetPrm3DVisu().SetFlag( FL_RENDER_MATERIAL, isChecked );
|
||||
NewDisplay();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_FL_RENDER_SHOW_MODEL_BBOX:
|
||||
GetPrm3DVisu().SetFlag( FL_RENDER_SHOW_MODEL_BBOX, isChecked );
|
||||
NewDisplay();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_SHOW_BOARD_BODY:
|
||||
GetPrm3DVisu().SetFlag( FL_SHOW_BOARD_BODY, isChecked );
|
||||
NewDisplay();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_AXIS_ONOFF:
|
||||
GetPrm3DVisu().SetFlag( FL_AXIS, isChecked );
|
||||
m_canvas->Refresh();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_MODULE_ONOFF:
|
||||
GetPrm3DVisu().SetFlag( FL_MODULE, isChecked );
|
||||
m_canvas->Refresh();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_USE_COPPER_THICKNESS:
|
||||
GetPrm3DVisu().SetFlag( FL_USE_COPPER_THICKNESS, isChecked );
|
||||
NewDisplay( GL_ID_BOARD );
|
||||
NewDisplay( GL_ID_TECH_LAYERS );
|
||||
return;
|
||||
|
||||
case ID_MENU3D_ZONE_ONOFF:
|
||||
GetPrm3DVisu().SetFlag( FL_ZONE, isChecked );
|
||||
NewDisplay( GL_ID_BOARD );
|
||||
return;
|
||||
|
||||
case ID_MENU3D_ADHESIVE_ONOFF:
|
||||
GetPrm3DVisu().SetFlag( FL_ADHESIVE, isChecked );
|
||||
NewDisplay( GL_ID_TECH_LAYERS );
|
||||
return;
|
||||
|
||||
case ID_MENU3D_SILKSCREEN_ONOFF:
|
||||
GetPrm3DVisu().SetFlag( FL_SILKSCREEN, isChecked );
|
||||
NewDisplay( GL_ID_TECH_LAYERS );
|
||||
return;
|
||||
|
||||
case ID_MENU3D_SOLDER_MASK_ONOFF:
|
||||
GetPrm3DVisu().SetFlag( FL_SOLDERMASK, isChecked );
|
||||
NewDisplay( GL_ID_TECH_LAYERS );
|
||||
return;
|
||||
|
||||
case ID_MENU3D_SOLDER_PASTE_ONOFF:
|
||||
GetPrm3DVisu().SetFlag( FL_SOLDERPASTE, isChecked );
|
||||
NewDisplay( GL_ID_TECH_LAYERS );
|
||||
return;
|
||||
|
||||
case ID_MENU3D_COMMENTS_ONOFF:
|
||||
GetPrm3DVisu().SetFlag( FL_COMMENTS, isChecked );
|
||||
NewDisplay( GL_ID_AUX_LAYERS );
|
||||
return;
|
||||
|
||||
case ID_MENU3D_ECO_ONOFF:
|
||||
GetPrm3DVisu().SetFlag( FL_ECO, isChecked );
|
||||
NewDisplay( GL_ID_AUX_LAYERS );
|
||||
return;
|
||||
|
||||
default:
|
||||
wxLogMessage( wxT( "EDA_3D_FRAME::Process_Special_Functions() error: unknown command" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
m_canvas->Refresh( true );
|
||||
m_canvas->DisplayStatus();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::On3DGridSelection( wxCommandEvent& event )
|
||||
{
|
||||
int id = event.GetId();
|
||||
|
||||
for( int ii = ID_MENU3D_GRID_NOGRID; ii < ID_MENU3D_GRID_END; ii++ )
|
||||
{
|
||||
if( event.GetId() == ii )
|
||||
continue;
|
||||
|
||||
GetMenuBar()->Check( ii, false );
|
||||
}
|
||||
|
||||
switch( id )
|
||||
{
|
||||
case ID_MENU3D_GRID_NOGRID:
|
||||
GetPrm3DVisu().SetFlag( FL_GRID, false );
|
||||
break;
|
||||
|
||||
case ID_MENU3D_GRID_10_MM:
|
||||
GetPrm3DVisu().SetFlag( FL_GRID, true );
|
||||
GetPrm3DVisu().m_3D_Grid = 10.0;
|
||||
break;
|
||||
|
||||
case ID_MENU3D_GRID_5_MM:
|
||||
GetPrm3DVisu().SetFlag( FL_GRID, true );
|
||||
GetPrm3DVisu().m_3D_Grid = 5.0;
|
||||
break;
|
||||
|
||||
case ID_MENU3D_GRID_2P5_MM:
|
||||
GetPrm3DVisu().SetFlag( FL_GRID, true );
|
||||
GetPrm3DVisu().m_3D_Grid = 2.5;
|
||||
break;
|
||||
|
||||
case ID_MENU3D_GRID_1_MM:
|
||||
GetPrm3DVisu().SetFlag( FL_GRID, true );
|
||||
GetPrm3DVisu().m_3D_Grid = 1.0;
|
||||
break;
|
||||
|
||||
default:
|
||||
wxLogMessage( wxT( "EDA_3D_FRAME::On3DGridSelection() error: unknown command" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
NewDisplay( GL_ID_GRID );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::NewDisplay( int aGlList )
|
||||
{
|
||||
m_canvas->ClearLists( aGlList );
|
||||
|
||||
// Rebuild the 3D board and refresh the view on reload request:
|
||||
if( m_reloadRequest )
|
||||
m_canvas->ReportWarnings( true );
|
||||
|
||||
m_canvas->Refresh( true );
|
||||
|
||||
m_canvas->DisplayStatus();
|
||||
m_reloadRequest = false;
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::OnActivate( wxActivateEvent& event )
|
||||
{
|
||||
// Reload data if 3D frame shows a board,
|
||||
// because it can be changed since last frame activation
|
||||
if( m_reloadRequest )
|
||||
NewDisplay();
|
||||
|
||||
event.Skip(); // required under wxMAC
|
||||
}
|
||||
|
||||
|
||||
bool EDA_3D_FRAME::Set3DColorFromUser( S3D_COLOR &aColor, const wxString& aTitle,
|
||||
wxColourData* aPredefinedColors )
|
||||
{
|
||||
wxColour newcolor, oldcolor;
|
||||
|
||||
oldcolor.Set( KiROUND( aColor.m_Red * 255 ),
|
||||
KiROUND( aColor.m_Green * 255 ),
|
||||
KiROUND( aColor.m_Blue * 255 ) );
|
||||
|
||||
wxColourData emptyColorSet; // Provides a empty predefined set of colors
|
||||
// if no color set available to avoid use of an
|
||||
// old color set
|
||||
|
||||
if( aPredefinedColors == NULL )
|
||||
aPredefinedColors = &emptyColorSet;
|
||||
|
||||
newcolor = wxGetColourFromUser( this, oldcolor, aTitle, aPredefinedColors );
|
||||
|
||||
if( !newcolor.IsOk() ) // Cancel command
|
||||
return false;
|
||||
|
||||
if( newcolor != oldcolor )
|
||||
{
|
||||
aColor.m_Red = (double) newcolor.Red() / 255.0;
|
||||
aColor.m_Green = (double) newcolor.Green() / 255.0;
|
||||
aColor.m_Blue = (double) newcolor.Blue() / 255.0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool EDA_3D_FRAME::Set3DSilkScreenColorFromUser()
|
||||
{
|
||||
wxColourData definedColors;
|
||||
|
||||
definedColors.SetCustomColour(0, wxColour( 241, 241, 241 ) ); // White
|
||||
definedColors.SetCustomColour(1, wxColour( 180, 180, 180 ) ); // Gray
|
||||
|
||||
bool change = Set3DColorFromUser( GetPrm3DVisu().m_SilkScreenColor,
|
||||
_( "Silk Screen Color" ),
|
||||
&definedColors );
|
||||
|
||||
if( change )
|
||||
NewDisplay( GL_ID_TECH_LAYERS );
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
|
||||
bool EDA_3D_FRAME::Set3DSolderMaskColorFromUser()
|
||||
{
|
||||
wxColourData definedColors;
|
||||
|
||||
definedColors.SetCustomColour(0, wxColour( 20, 51, 36 ) ); // Green
|
||||
definedColors.SetCustomColour(1, wxColour( 43, 10, 65 ) ); // Purple
|
||||
definedColors.SetCustomColour(2, wxColour( 117, 19, 21 ) ); // Red
|
||||
definedColors.SetCustomColour(3, wxColour( 54, 79, 116) ); // Light blue
|
||||
definedColors.SetCustomColour(4, wxColour( 11, 11, 11 ) ); // Black
|
||||
definedColors.SetCustomColour(5, wxColour( 241, 241,241) ); // White
|
||||
|
||||
bool change = Set3DColorFromUser( GetPrm3DVisu().m_SolderMaskColor,
|
||||
_( "Solder Mask Color" ),
|
||||
&definedColors );
|
||||
|
||||
if( change )
|
||||
NewDisplay( GL_ID_TECH_LAYERS );
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
|
||||
bool EDA_3D_FRAME::Set3DCopperColorFromUser()
|
||||
{
|
||||
wxColourData definedColors;
|
||||
|
||||
definedColors.SetCustomColour( 0, wxColour( 184, 115, 50 ) ); // Copper
|
||||
definedColors.SetCustomColour( 1, wxColour( 233, 221, 82 ) ); // Gold
|
||||
definedColors.SetCustomColour( 2, wxColour( 213, 213, 213) ); // Silver
|
||||
definedColors.SetCustomColour( 3, wxColour( 160, 160, 160) ); // tin
|
||||
|
||||
|
||||
bool change = Set3DColorFromUser( GetPrm3DVisu().m_CopperColor,
|
||||
_( "Copper Color" ),
|
||||
&definedColors );
|
||||
|
||||
if( change )
|
||||
NewDisplay( GL_ID_BOARD );
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
|
||||
bool EDA_3D_FRAME::Set3DBoardBodyColorFromUser()
|
||||
{
|
||||
wxColourData definedColors;
|
||||
|
||||
definedColors.SetCustomColour( 0, wxColour( 51, 43, 22 ) ); // FR4 natural, dark
|
||||
definedColors.SetCustomColour( 1, wxColour( 109, 116, 75 ) ); // FR4 natural
|
||||
definedColors.SetCustomColour( 2, wxColour( 78, 14, 5 ) ); // brown/red
|
||||
definedColors.SetCustomColour( 3, wxColour( 146, 99, 47 ) ); // brown 1
|
||||
definedColors.SetCustomColour( 4, wxColour( 160, 123, 54 ) ); // brown 2
|
||||
definedColors.SetCustomColour( 5, wxColour( 146, 99, 47 ) ); // brown 3
|
||||
definedColors.SetCustomColour( 6, wxColour( 63, 126, 71 ) ); // green 1
|
||||
definedColors.SetCustomColour( 7, wxColour( 117, 122, 90 ) ); // green 2
|
||||
|
||||
bool change = Set3DColorFromUser( GetPrm3DVisu().m_BoardBodyColor,
|
||||
_( "Board Body Color" ),
|
||||
&definedColors );
|
||||
|
||||
if( change )
|
||||
NewDisplay( GL_ID_BOARD );
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
|
||||
bool EDA_3D_FRAME::Set3DSolderPasteColorFromUser()
|
||||
{
|
||||
wxColourData definedColors;
|
||||
|
||||
definedColors.SetCustomColour(0, wxColour( 128, 128, 128 ) ); // grey
|
||||
definedColors.SetCustomColour(1, wxColour( 213, 213, 213 ) ); // Silver
|
||||
definedColors.SetCustomColour(2, wxColour( 90, 90, 90 ) ); // grey 2
|
||||
|
||||
bool change = Set3DColorFromUser( GetPrm3DVisu().m_SolderPasteColor,
|
||||
_( "Solder Paste Color" ),
|
||||
&definedColors );
|
||||
|
||||
if( change )
|
||||
NewDisplay( GL_ID_TECH_LAYERS );
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
|
||||
BOARD* EDA_3D_FRAME::GetBoard()
|
||||
{
|
||||
return Parent()->GetBoard();
|
||||
}
|
||||
|
||||
|
||||
INFO3D_VISU& EDA_3D_FRAME::GetPrm3DVisu() const
|
||||
{
|
||||
// return the INFO3D_VISU which contains the current parameters
|
||||
// to draw the 3D view of the board
|
||||
return g_Parm_3D_Visu;
|
||||
}
|
||||
|
||||
|
||||
bool EDA_3D_FRAME::IsEnabled( DISPLAY3D_FLG aItem ) const
|
||||
{
|
||||
// return true if aItem must be displayed
|
||||
return GetPrm3DVisu().GetFlag( aItem );
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014-2015 Mario Luzeiro <mrluzeiro@gmail.com>
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
/**
|
||||
* @file 3d_class.cpp
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <3d_struct.h>
|
||||
#include <3d_material.h>
|
||||
#include <info3d_visu.h>
|
||||
|
||||
#ifdef __WXMAC__
|
||||
# ifdef __DARWIN__
|
||||
# include <OpenGL/glu.h>
|
||||
# else
|
||||
# include <glu.h>
|
||||
# endif
|
||||
#else
|
||||
# include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
S3D_MATERIAL::S3D_MATERIAL( S3D_MASTER* father, const wxString& name ) :
|
||||
EDA_ITEM( father, NOT_USED )
|
||||
{
|
||||
m_Name = name;
|
||||
m_AmbientColor.clear();
|
||||
m_DiffuseColor.clear();
|
||||
m_EmissiveColor.clear();
|
||||
m_SpecularColor.clear();
|
||||
m_Shininess.clear();
|
||||
m_Transparency.clear();
|
||||
m_ColorPerVertex = false;
|
||||
}
|
||||
|
||||
|
||||
void SetOpenGlDefaultMaterial()
|
||||
{
|
||||
glm::vec4 ambient( 0.2f, 0.2f, 0.2f, 1.0f );
|
||||
glm::vec4 specular( 0.0f, 0.0f, 0.0f, 1.0f );
|
||||
glm::vec4 emissive( 0.0f, 0.0f, 0.0f, 1.0f );
|
||||
glm::vec4 diffuse( 0.0f, 0.0f, 0.0f, 1.0f );
|
||||
GLint shininess_value = 0;
|
||||
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
glMateriali ( GL_FRONT_AND_BACK, GL_SHININESS, shininess_value );
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, &emissive.x );
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.x );
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.x );
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.x );
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool S3D_MATERIAL::SetOpenGLMaterial( unsigned int aMaterialIndex, bool aUseMaterial )
|
||||
{
|
||||
if( aUseMaterial )
|
||||
{
|
||||
float transparency_value = 0.0f;
|
||||
|
||||
if( m_Transparency.size() > aMaterialIndex )
|
||||
{
|
||||
transparency_value = m_Transparency[aMaterialIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_Transparency.size() > 0 )
|
||||
transparency_value = m_Transparency[0];
|
||||
}
|
||||
|
||||
if( m_DiffuseColor.size() > aMaterialIndex )
|
||||
{
|
||||
glm::vec3 color = m_DiffuseColor[aMaterialIndex];
|
||||
|
||||
glColor4f( color.x, color.y, color.z, 1.0f - transparency_value );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_DiffuseColor.size() == 0 )
|
||||
{
|
||||
glColor4f( 0.8f, 0.8f, 0.8f, 1.0f );
|
||||
}
|
||||
}
|
||||
|
||||
if( m_Shininess.size() > 0 )
|
||||
{
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, m_Shininess[0] );
|
||||
}
|
||||
|
||||
// emissive
|
||||
if( m_EmissiveColor.size() > aMaterialIndex )
|
||||
{
|
||||
glm::vec4 emissive;
|
||||
emissive[0] = m_EmissiveColor[aMaterialIndex].x;
|
||||
emissive[1] = m_EmissiveColor[aMaterialIndex].y;
|
||||
emissive[2] = m_EmissiveColor[aMaterialIndex].z;
|
||||
emissive[3] = 1.0f;
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, &emissive.x );
|
||||
}
|
||||
|
||||
// specular
|
||||
if( m_SpecularColor.size() > aMaterialIndex )
|
||||
{
|
||||
glm::vec4 specular;
|
||||
specular[0] = m_SpecularColor[aMaterialIndex].x;
|
||||
specular[1] = m_SpecularColor[aMaterialIndex].y;
|
||||
specular[2] = m_SpecularColor[aMaterialIndex].z;
|
||||
specular[3] = 1.0f;
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.x );
|
||||
}
|
||||
|
||||
// ambient
|
||||
if( m_AmbientColor.size() > aMaterialIndex )
|
||||
{
|
||||
glm::vec4 ambient;
|
||||
ambient[0] = m_AmbientColor[aMaterialIndex].x;
|
||||
ambient[1] = m_AmbientColor[aMaterialIndex].y;
|
||||
ambient[2] = m_AmbientColor[aMaterialIndex].z;
|
||||
ambient[3] = 1.0f;
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.x );
|
||||
}
|
||||
|
||||
return (transparency_value != 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_DiffuseColor.size() > aMaterialIndex )
|
||||
{
|
||||
glm::vec3 color = m_DiffuseColor[aMaterialIndex];
|
||||
glColor4f( color.x, color.y, color.z, 1.0 );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014-2015 Mario Luzeiro <mrluzeiro@gmail.com>
|
||||
* Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_material.h
|
||||
*/
|
||||
|
||||
#ifndef STRUCT_3D_MATERIAL_H
|
||||
#define STRUCT_3D_MATERIAL_H
|
||||
|
||||
#include <common.h>
|
||||
#include <base_struct.h>
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <gal/opengl/glm/glm.hpp>
|
||||
|
||||
class S3D_MASTER;
|
||||
|
||||
class S3D_MATERIAL : public EDA_ITEM // openGL "material" data
|
||||
{
|
||||
public:
|
||||
wxString m_Name;
|
||||
|
||||
// Material list
|
||||
std::vector< glm::vec3 > m_AmbientColor;
|
||||
std::vector< glm::vec3 > m_DiffuseColor;
|
||||
std::vector< glm::vec3 > m_EmissiveColor;
|
||||
std::vector< glm::vec3 > m_SpecularColor;
|
||||
std::vector< float > m_Shininess;
|
||||
std::vector< float > m_Transparency;
|
||||
bool m_ColorPerVertex;
|
||||
|
||||
public:
|
||||
S3D_MATERIAL( S3D_MASTER* father, const wxString& name );
|
||||
|
||||
S3D_MATERIAL* Next() const { return (S3D_MATERIAL*) Pnext; }
|
||||
S3D_MATERIAL* Back() const { return (S3D_MATERIAL*) Pback; }
|
||||
|
||||
/**
|
||||
* Initialize the material prms.
|
||||
* @param aMaterialIndex = the index in list of available materials
|
||||
* @param aUseMaterial = true to use the values found in the available material
|
||||
* = false to use only the color, and other prms are fixed
|
||||
* @return true if the material is transparency
|
||||
*/
|
||||
bool SetOpenGLMaterial(unsigned int aMaterialIndex, bool aUseMaterial);
|
||||
|
||||
#if defined(DEBUG)
|
||||
void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override
|
||||
#endif
|
||||
|
||||
/** Get class name
|
||||
* @return string "S3D_MATERIAL"
|
||||
*/
|
||||
virtual wxString GetClass() const
|
||||
{
|
||||
return wxT( "S3D_MATERIAL" );
|
||||
}
|
||||
};
|
||||
|
||||
void SetOpenGlDefaultMaterial();
|
||||
|
||||
#endif
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_math.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
|
||||
#include "3d_math.h"
|
||||
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_math.h
|
||||
* @brief Defines math related functions
|
||||
*/
|
||||
|
||||
#ifndef _3D_MATH_H
|
||||
#define _3D_MATH_H
|
||||
|
||||
#include <plugins/3dapi/xv3d_types.h>
|
||||
#include "3d_fastmath.h"
|
||||
|
||||
// https://en.wikipedia.org/wiki/Spherical_coordinate_system
|
||||
/**
|
||||
* @brief SphericalToCartesian
|
||||
* @param aInclination θ ∈ [0, π]
|
||||
* @param aAzimuth φ ∈ [0, 2π]
|
||||
* @return Cartesian cordinates
|
||||
*/
|
||||
inline SFVEC3F SphericalToCartesian( float aInclination, float aAzimuth )
|
||||
{
|
||||
float sinInc = glm::sin( aInclination );
|
||||
return SFVEC3F( sinInc * glm::cos( aAzimuth ),
|
||||
sinInc * glm::sin( aAzimuth ),
|
||||
glm::cos( aInclination ) );
|
||||
}
|
||||
|
||||
|
||||
// https://pathtracing.wordpress.com/2011/03/03/cosine-weighted-hemisphere/
|
||||
// !TODO: this is not correct because it is not a gaussian random
|
||||
inline SFVEC3F UniformRandomHemisphereDirection( )
|
||||
{
|
||||
// It was experienced that this function is slow! do not use it :/
|
||||
// SFVEC3F b( (rand()/(float)RAND_MAX) - 0.5f,
|
||||
// (rand()/(float)RAND_MAX) - 0.5f,
|
||||
// (rand()/(float)RAND_MAX) - 0.5f );
|
||||
|
||||
SFVEC3F b( Fast_RandFloat() * 0.5f,
|
||||
Fast_RandFloat() * 0.5f,
|
||||
Fast_RandFloat() * 0.5f );
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
// https://pathtracing.wordpress.com/2011/03/03/cosine-weighted-hemisphere/
|
||||
inline SFVEC3F CosWeightedRandomHemisphereDirection( const SFVEC3F &n )
|
||||
{
|
||||
const float Xi1 = (float)rand() / (float)RAND_MAX;
|
||||
const float Xi2 = (float)rand() / (float)RAND_MAX;
|
||||
|
||||
const float theta = acos( sqrt( 1.0f - Xi1 ) );
|
||||
const float phi = 2.0f * glm::pi<float>() * Xi2;
|
||||
|
||||
const float xs = sinf( theta ) * cosf( phi );
|
||||
const float ys = cosf( theta );
|
||||
const float zs = sinf( theta ) * sinf( phi );
|
||||
|
||||
const SFVEC3F y( n.x, n.y, n.z );
|
||||
SFVEC3F h = y;
|
||||
|
||||
if( fabs( h.x ) <= fabs( h.y ) && fabs( h.x ) <= fabs( h.z ) )
|
||||
h.x= 1.0f;
|
||||
else if( fabs( h.y ) <= fabs( h.x ) && fabs( h.y ) <= fabs( h.z ) )
|
||||
h.y= 1.0f;
|
||||
else
|
||||
h.z= 1.0f;
|
||||
|
||||
|
||||
const SFVEC3F x = glm::normalize( glm::cross( h, y ) );
|
||||
const SFVEC3F z = glm::normalize( glm::cross( x, y ) );
|
||||
|
||||
SFVEC3F direction = xs * x + ys * y + zs * z;
|
||||
return glm::normalize( direction );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Refract
|
||||
* Based on:
|
||||
* https://github.com/mmp/pbrt-v3/blob/master/src/core/reflection.h
|
||||
* See also:
|
||||
* http://www.flipcode.com/archives/Raytracing_Topics_Techniques-Part_3_Refractions_and_Beers_Law.shtml
|
||||
* @param aInVector incoming vector
|
||||
* @param aNormal normal in the intersection point
|
||||
* @param aRin_over_Rout incoming refraction index / out refraction index
|
||||
* @param aOutVector the refracted vector
|
||||
* @return true
|
||||
*/
|
||||
inline bool Refract( const SFVEC3F &aInVector,
|
||||
const SFVEC3F &aNormal,
|
||||
float aRin_over_Rout,
|
||||
SFVEC3F &aOutVector )
|
||||
{
|
||||
float cosThetaI = -glm::dot( aNormal, aInVector );
|
||||
float sin2ThetaI = glm::max( 0.0f, 1.0f - cosThetaI * cosThetaI );
|
||||
float sin2ThetaT = aRin_over_Rout * aRin_over_Rout * sin2ThetaI;
|
||||
|
||||
// Handle total internal reflection for transmission
|
||||
if( sin2ThetaT >= 1.0f )
|
||||
return false;
|
||||
|
||||
float cosThetaT = sqrtf( 1.0f - sin2ThetaT );
|
||||
|
||||
aOutVector = glm::normalize( aRin_over_Rout * aInVector +
|
||||
( aRin_over_Rout * cosThetaI - cosThetaT ) *
|
||||
aNormal );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline float mapf( float x,
|
||||
float in_min,
|
||||
float in_max,
|
||||
float out_min,
|
||||
float out_max)
|
||||
{
|
||||
x = glm::clamp( x, in_min, in_max );
|
||||
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
inline float RGBtoGray( const SFVEC3F &aColor )
|
||||
{
|
||||
return (aColor.r * 0.2126f +
|
||||
aColor.g * 0.7152f +
|
||||
aColor.b * 0.0722f);
|
||||
}
|
||||
|
||||
inline SFVEC3F MaterialDiffuseToColorCAD( const SFVEC3F &aDiffuseColor )
|
||||
{
|
||||
// convert to a discret scale of grays
|
||||
const float luminance = glm::min( (((float)((unsigned int) ( 4.0f *
|
||||
RGBtoGray( aDiffuseColor ) ) ) + 0.5f) /
|
||||
4.0f) * 1.0f,
|
||||
1.0f );
|
||||
|
||||
const float maxValue = glm::max( glm::max( glm::max( aDiffuseColor.r,
|
||||
aDiffuseColor.g),
|
||||
aDiffuseColor.b ),
|
||||
FLT_EPSILON );
|
||||
|
||||
return (aDiffuseColor / SFVEC3F(maxValue) ) * 0.125f + luminance* 0.875f;
|
||||
}
|
||||
|
||||
|
||||
// http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJ4KngqMiIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MCwiZXEiOiItKCh4LTEpXjIpKjIrMSIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MTAwMCwid2luZG93IjpbIi0xLjM4NzUwMDAwMDAwMDAwMDIiLCIxLjg2MjQ5OTk5OTk5OTk5OTgiLCItMC43IiwiMS4zIl19XQ--
|
||||
inline float QuadricEasingInOut( float t )
|
||||
{
|
||||
if( t <= 0.5f )
|
||||
{
|
||||
return t * t * 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = t - 1.0f;
|
||||
|
||||
return -2.0f * (t * t) + 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// http://www.wolframalpha.com/input/?i=t%5E2(3-2t)
|
||||
inline float BezierBlend( float t )
|
||||
{
|
||||
return t * t * ( 3.0f - 2.0f * t );
|
||||
}
|
||||
|
||||
#endif // 3D_MATH_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014-2015 Mario Luzeiro <mrluzeiro@gmail.com>
|
||||
* Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_mesh_model.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef __3D_MESH_MODEL_H__
|
||||
#define __3D_MESH_MODEL_H__
|
||||
|
||||
#include <memory>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <vector>
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <gal/opengl/glm/glm.hpp>
|
||||
#include "3d_struct.h"
|
||||
#include "3d_material.h"
|
||||
#include "CBBox.h"
|
||||
|
||||
class S3D_MESH;
|
||||
|
||||
/** A smart pointer to an S3D_MESH object */
|
||||
typedef boost::shared_ptr<S3D_MESH> S3D_MESH_PTR;
|
||||
|
||||
/** A container of smar S3D_MESH object pointers */
|
||||
typedef std::vector<S3D_MESH_PTR> S3D_MESH_PTRS;
|
||||
|
||||
class S3D_MESH
|
||||
{
|
||||
public:
|
||||
|
||||
S3D_MESH();
|
||||
~S3D_MESH();
|
||||
|
||||
void openGL_RenderAllChilds( bool aIsRenderingJustNonTransparentObjects,
|
||||
bool aIsRenderingJustTransparentObjects );
|
||||
|
||||
S3D_MATERIAL *m_Materials;
|
||||
|
||||
// Point and index list
|
||||
std::vector< S3D_VERTEX > m_Point;
|
||||
std::vector< std::vector<int> > m_CoordIndex;
|
||||
std::vector< std::vector<int> > m_NormalIndex;
|
||||
std::vector< S3D_VERTEX > m_PerFaceColor;
|
||||
std::vector< S3D_VERTEX > m_PerFaceNormalsNormalized;
|
||||
std::vector< S3D_VERTEX > m_PerVertexNormalsNormalized;
|
||||
std::vector< int > m_MaterialIndexPerFace;
|
||||
std::vector< std::vector<int> > m_MaterialIndexPerVertex;
|
||||
S3D_MESH_PTRS childs;
|
||||
|
||||
S3D_VERTEX m_translation;
|
||||
glm::vec4 m_rotation;
|
||||
S3D_VERTEX m_scale;
|
||||
|
||||
CBBOX &getBBox();
|
||||
|
||||
private:
|
||||
std::vector< S3D_VERTEX > m_PerFaceNormalsRaw_X_PerFaceSquaredArea;
|
||||
std::vector< std::vector< S3D_VERTEX > > m_PerFaceVertexNormals;
|
||||
std::vector< S3D_VERTEX > m_PointNormalized;
|
||||
|
||||
std::vector< std::vector<int> > m_InvalidCoordIndexes; //!TODO: check for invalid CoordIndex in file and remove the index and the same material index
|
||||
|
||||
bool isPerFaceNormalsComputed;
|
||||
void calcPerFaceNormals ();
|
||||
|
||||
bool isPointNormalizedComputed;
|
||||
void calcPointNormalized();
|
||||
|
||||
bool isPerPointNormalsComputed;
|
||||
void calcPerPointNormals();
|
||||
|
||||
bool isPerVertexNormalsVerified;
|
||||
void perVertexNormalsVerify_and_Repair();
|
||||
|
||||
void calcBBox();
|
||||
void calcBBoxAllChilds();
|
||||
|
||||
CBBOX m_BBox;
|
||||
|
||||
void openGL_Render( bool aIsRenderingJustNonTransparentObjects,
|
||||
bool aIsRenderingJustTransparentObjects );
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,471 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_model_viewer.cpp
|
||||
* @brief Implements a model viewer canvas. The propose of model viewer is to
|
||||
* render 3d models that come in the original data from the files without any
|
||||
* transformations.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h"
|
||||
#include "c3d_model_viewer.h"
|
||||
#include "../3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.h"
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
#include "common_ogl/ogl_utils.h"
|
||||
#include <wx/dcclient.h>
|
||||
#include <base_units.h>
|
||||
#include <gl_context_mgr.h>
|
||||
|
||||
/**
|
||||
* Scale convertion from 3d model units to pcb units
|
||||
*/
|
||||
#define UNITS3D_TO_UNITSPCB (IU_PER_MM)
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
const wxChar * C3D_MODEL_VIEWER::m_logTrace = wxT( "KI_TRACE_EDA_3D_MODEL_VIEWER" );
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( C3D_MODEL_VIEWER, wxGLCanvas )
|
||||
EVT_PAINT( C3D_MODEL_VIEWER::OnPaint )
|
||||
|
||||
// mouse events
|
||||
EVT_LEFT_DOWN( C3D_MODEL_VIEWER::OnLeftDown )
|
||||
EVT_LEFT_UP( C3D_MODEL_VIEWER::OnLeftUp )
|
||||
EVT_MIDDLE_UP( C3D_MODEL_VIEWER::OnMiddleUp )
|
||||
EVT_MIDDLE_DOWN(C3D_MODEL_VIEWER::OnMiddleDown)
|
||||
EVT_RIGHT_DOWN( C3D_MODEL_VIEWER::OnRightClick )
|
||||
EVT_MOUSEWHEEL( C3D_MODEL_VIEWER::OnMouseWheel )
|
||||
EVT_MOTION( C3D_MODEL_VIEWER::OnMouseMove )
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
EVT_MAGNIFY( C3D_MODEL_VIEWER::OnMagnify )
|
||||
#endif
|
||||
|
||||
// other events
|
||||
EVT_ERASE_BACKGROUND( C3D_MODEL_VIEWER::OnEraseBackground )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
// This defines the range that all coord will have to be rendered.
|
||||
// It will use this value to convert to a normalized value between
|
||||
// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||
#define RANGE_SCALE_3D 8.0f
|
||||
|
||||
|
||||
C3D_MODEL_VIEWER::C3D_MODEL_VIEWER(wxWindow *aParent,
|
||||
const int *aAttribList , S3D_CACHE *aCacheManager) :
|
||||
|
||||
HIDPI_GL_CANVAS( aParent,
|
||||
wxID_ANY,
|
||||
aAttribList,
|
||||
wxDefaultPosition,
|
||||
wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE ),
|
||||
m_trackBallCamera( RANGE_SCALE_3D * 2.0f ),
|
||||
m_cacheManager(aCacheManager)
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::C3D_MODEL_VIEWER" ) );
|
||||
|
||||
m_ogl_initialized = false;
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = NULL;
|
||||
m_3d_model = NULL;
|
||||
m_BiuTo3Dunits = 1.0;
|
||||
|
||||
m_glRC = NULL;
|
||||
}
|
||||
|
||||
|
||||
C3D_MODEL_VIEWER::~C3D_MODEL_VIEWER()
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::~C3D_MODEL_VIEWER" ) );
|
||||
|
||||
if( m_glRC )
|
||||
{
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
GL_CONTEXT_MANAGER::Get().DestroyCtx( m_glRC );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::Set3DModel( const S3DMODEL &a3DModel )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::Set3DModel with a S3DMODEL" ) );
|
||||
|
||||
// Validate a3DModel pointers
|
||||
wxASSERT( a3DModel.m_Materials != NULL );
|
||||
wxASSERT( a3DModel.m_Meshes != NULL );
|
||||
wxASSERT( a3DModel.m_MaterialsSize > 0 );
|
||||
wxASSERT( a3DModel.m_MeshesSize > 0 );
|
||||
|
||||
// Delete the old model
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
|
||||
m_3d_model = NULL;
|
||||
|
||||
if( (a3DModel.m_Materials != NULL) && (a3DModel.m_Meshes != NULL) &&
|
||||
(a3DModel.m_MaterialsSize > 0) && (a3DModel.m_MeshesSize > 0) )
|
||||
{
|
||||
m_3d_model = &a3DModel;
|
||||
m_reload_is_needed = true;
|
||||
}
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::Set3DModel(const wxString &aModelPathName)
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::Set3DModel with a wxString" ) );
|
||||
|
||||
if( m_cacheManager )
|
||||
{
|
||||
const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName );
|
||||
|
||||
if( model )
|
||||
Set3DModel( (const S3DMODEL &)*model );
|
||||
else
|
||||
Clear3DModel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::Clear3DModel()
|
||||
{
|
||||
// Delete the old model
|
||||
m_reload_is_needed = false;
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
|
||||
m_3d_model = NULL;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::ogl_initialize()
|
||||
{
|
||||
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
|
||||
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
||||
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
//glDepthFunc( GL_LEQUAL );
|
||||
glEnable( GL_CULL_FACE );
|
||||
glShadeModel( GL_SMOOTH );
|
||||
glEnable( GL_LINE_SMOOTH );
|
||||
glEnable( GL_NORMALIZE );
|
||||
|
||||
// Setup light
|
||||
// https://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
const GLfloat ambient[] = { 0.01f, 0.01f, 0.01f, 1.0f };
|
||||
const GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
const GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
||||
// defines a directional light that points along the negative z-axis
|
||||
const GLfloat position[] = { 0.0f, 0.0f, 2.0f * RANGE_SCALE_3D, 0.0f };
|
||||
|
||||
const GLfloat lmodel_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
|
||||
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
|
||||
glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
|
||||
glLightfv( GL_LIGHT0, GL_POSITION, position );
|
||||
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::ogl_set_arrow_material()
|
||||
{
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
|
||||
const SFVEC4F specular = SFVEC4F( 0.1f, 0.1f, 0.1f, 1.0f );
|
||||
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r );
|
||||
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 96.0f );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
||||
{
|
||||
wxPaintDC( this );
|
||||
|
||||
event.Skip( false );
|
||||
|
||||
// SwapBuffer requires the window to be shown before calling
|
||||
if( !IsShownOnScreen() )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnPaint !IsShown" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// "Makes the OpenGL state that is represented by the OpenGL rendering
|
||||
// context context current, i.e. it will be used by all subsequent OpenGL calls.
|
||||
// This function may only be called when the window is shown on screen"
|
||||
if( m_glRC == NULL )
|
||||
m_glRC = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
// 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.
|
||||
wxSize clientSize = GetClientSize();
|
||||
|
||||
if( !m_ogl_initialized )
|
||||
{
|
||||
m_ogl_initialized = true;
|
||||
ogl_initialize();
|
||||
}
|
||||
|
||||
if( m_reload_is_needed )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnPaint m_reload_is_needed" ) );
|
||||
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = new C_OGL_3DMODEL( *m_3d_model, MATERIAL_MODE_NORMAL );
|
||||
|
||||
// It convert a model as it was a board, so get the max size dimension of the board
|
||||
// and compute the conversion scale
|
||||
m_BiuTo3Dunits = (double)RANGE_SCALE_3D /
|
||||
( (double)m_ogl_3dmodel->GetBBox().GetMaxDimension() *
|
||||
UNITS3D_TO_UNITSPCB );
|
||||
}
|
||||
|
||||
glViewport( 0, 0, clientSize.x, clientSize.y );
|
||||
|
||||
m_trackBallCamera.SetCurWindowSize( clientSize );
|
||||
|
||||
// clear color and depth buffers
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
|
||||
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
|
||||
glClearDepth( 1.0f );
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
// Set projection and modelview matrixes
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetProjectionMatrix() ) );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetViewMatrix() ) );
|
||||
|
||||
glEnable( GL_LIGHTING );
|
||||
glEnable( GL_LIGHT0 );
|
||||
|
||||
// Render Model
|
||||
if( m_ogl_3dmodel )
|
||||
{
|
||||
glPushMatrix();
|
||||
|
||||
double modelunit_to_3d_units_factor = m_BiuTo3Dunits * UNITS3D_TO_UNITSPCB;
|
||||
|
||||
glScaled( modelunit_to_3d_units_factor,
|
||||
modelunit_to_3d_units_factor,
|
||||
modelunit_to_3d_units_factor );
|
||||
|
||||
// Center model in the render viewport
|
||||
const SFVEC3F model_center = m_ogl_3dmodel->GetBBox().GetCenter();
|
||||
|
||||
glTranslatef( -model_center.x, -model_center.y, -model_center.z );
|
||||
|
||||
m_ogl_3dmodel->Draw_opaque();
|
||||
m_ogl_3dmodel->Draw_transparent();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
// YxY squared view port
|
||||
glViewport( 0, 0, clientSize.y / 8 , clientSize.y / 8 );
|
||||
glClear( GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
gluPerspective( 45.0f, 1.0f, 0.01f, RANGE_SCALE_3D * 2.0f );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
|
||||
const glm::mat4 TranslationMatrix = glm::translate( glm::mat4(1.0f),
|
||||
SFVEC3F( 0.0f, 0.0f, -RANGE_SCALE_3D ) );
|
||||
|
||||
const glm::mat4 ViewMatrix = TranslationMatrix * m_trackBallCamera.GetRotationMatrix();
|
||||
|
||||
glLoadMatrixf( glm::value_ptr( ViewMatrix ) );
|
||||
|
||||
ogl_set_arrow_material();
|
||||
|
||||
glColor3f( 0.9f, 0.0f, 0.0f );
|
||||
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||
SFVEC3F( RANGE_SCALE_3D / 2.65f, 0.0f, 0.0f ),
|
||||
0.275f );
|
||||
|
||||
glColor3f( 0.0f, 0.9f, 0.0f );
|
||||
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||
SFVEC3F( 0.0f, RANGE_SCALE_3D / 2.65f, 0.0f ),
|
||||
0.275f );
|
||||
|
||||
glColor3f( 0.0f, 0.0f, 0.9f );
|
||||
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||
SFVEC3F( 0.0f, 0.0f, RANGE_SCALE_3D / 2.65f ),
|
||||
0.275f );
|
||||
|
||||
// "Swaps the double-buffer of this window, making the back-buffer the
|
||||
// front-buffer and vice versa, so that the output of the previous OpenGL
|
||||
// commands is displayed on the window."
|
||||
SwapBuffers();
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnEraseBackground( wxEraseEvent &event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnEraseBackground" ) );
|
||||
// Do nothing, to avoid flashing.
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMouseWheel( wxMouseEvent &event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnMouseWheel" ) );
|
||||
|
||||
if( event.ShiftDown() )
|
||||
{
|
||||
//if( event.GetWheelRotation() < 0 )
|
||||
//SetView3D( WXK_UP ); // move up
|
||||
//else
|
||||
//SetView3D( WXK_DOWN ); // move down
|
||||
}
|
||||
else if( event.ControlDown() )
|
||||
{
|
||||
//if( event.GetWheelRotation() > 0 )
|
||||
//SetView3D( WXK_RIGHT ); // move right
|
||||
//else
|
||||
//SetView3D( WXK_LEFT ); // move left
|
||||
}
|
||||
else
|
||||
{
|
||||
m_trackBallCamera.Zoom( event.GetWheelRotation() > 0 ? 1.1f : 1/1.1f );
|
||||
|
||||
//DisplayStatus();
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( event.GetPosition() );
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void C3D_MODEL_VIEWER::OnMagnify( wxMouseEvent& event )
|
||||
{
|
||||
/*
|
||||
double magnification = ( event.GetMagnification() + 1.0f );
|
||||
GetPrm3DVisu().m_Zoom /= magnification;
|
||||
if( GetPrm3DVisu().m_Zoom <= 0.01 )
|
||||
GetPrm3DVisu().m_Zoom = 0.01;
|
||||
DisplayStatus();
|
||||
Refresh( false );
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMouseMove( wxMouseEvent &event )
|
||||
{
|
||||
m_trackBallCamera.SetCurWindowSize( GetClientSize() );
|
||||
|
||||
if( event.Dragging() )
|
||||
{
|
||||
if( event.LeftIsDown() ) // Drag
|
||||
m_trackBallCamera.Drag( event.GetPosition() );
|
||||
//else if( event.MiddleIsDown() ) // Pan
|
||||
// m_trackBallCamera.Pan( event.GetPosition() );
|
||||
|
||||
// orientation has changed, redraw mesh
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( event.GetPosition() );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnLeftDown( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = true;
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnLeftUp( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = false;
|
||||
//Refresh( false );
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMiddleDown( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = true;
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMiddleUp( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = false;
|
||||
//Refresh( false );
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnRightClick( wxMouseEvent &event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_model_viewer.h
|
||||
* @brief Implements a model viewer canvas. The propose of model viewer is to
|
||||
* render 3d models that come in the original data from the files without any
|
||||
* transformations.
|
||||
*/
|
||||
|
||||
#ifndef _C3D_MODEL_VIEWER_H_
|
||||
#define _C3D_MODEL_VIEWER_H_
|
||||
|
||||
#include "3d_rendering/ctrack_ball.h"
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class C_OGL_3DMODEL;
|
||||
|
||||
/**
|
||||
* Class C3D_MODEL_VIEWER
|
||||
* Implement a canvas based on a wxGLCanvas
|
||||
*/
|
||||
class C3D_MODEL_VIEWER : public HIDPI_GL_CANVAS
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new 3D Canvas with a attribute list
|
||||
* @param aParent = the parent creator of this canvas
|
||||
* @param aAttribList = a list of openGL options created by
|
||||
* COGL_ATT_LIST::GetAttributesList
|
||||
*/
|
||||
C3D_MODEL_VIEWER( wxWindow *aParent,
|
||||
const int *aAttribList = 0,
|
||||
S3D_CACHE *aCacheManager = NULL );
|
||||
|
||||
~C3D_MODEL_VIEWER();
|
||||
|
||||
/**
|
||||
* @brief Set3DModel - Set this model to be displayed
|
||||
* @param a3DModel - 3d model data
|
||||
*/
|
||||
void Set3DModel( const S3DMODEL &a3DModel );
|
||||
|
||||
/**
|
||||
* @brief Set3DModel - Set this model to be displayed
|
||||
* @param aModelPathName - 3d model path name
|
||||
*/
|
||||
void Set3DModel( wxString const& aModelPathName );
|
||||
|
||||
/**
|
||||
* @brief Clear3DModel - Unloads the displayed 3d model
|
||||
*/
|
||||
void Clear3DModel();
|
||||
|
||||
private:
|
||||
void ogl_initialize();
|
||||
void ogl_set_arrow_material();
|
||||
|
||||
private:
|
||||
|
||||
void OnPaint( wxPaintEvent &event );
|
||||
|
||||
void OnEraseBackground( wxEraseEvent &event );
|
||||
|
||||
void OnMouseWheel( wxMouseEvent &event );
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
#endif
|
||||
|
||||
void OnMouseMove( wxMouseEvent &event );
|
||||
|
||||
void OnLeftDown( wxMouseEvent &event );
|
||||
|
||||
void OnLeftUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleDown( wxMouseEvent &event );
|
||||
|
||||
void OnRightClick( wxMouseEvent &event );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
|
||||
private:
|
||||
/// openGL context
|
||||
wxGLContext *m_glRC;
|
||||
|
||||
/// Camera used in this canvas
|
||||
CTRACK_BALL m_trackBallCamera;
|
||||
|
||||
/// Original 3d model data
|
||||
const S3DMODEL *m_3d_model;
|
||||
|
||||
/// Class holder for 3d model to display on openGL
|
||||
C_OGL_3DMODEL *m_ogl_3dmodel;
|
||||
|
||||
/// Flag that we have a new model and it need to be reloaded when the paint is called
|
||||
bool m_reload_is_needed;
|
||||
|
||||
/// Flag if open gl was initialized
|
||||
bool m_ogl_initialized;
|
||||
|
||||
/// factor to convert the model or any other items to keep it in relation to
|
||||
/// the +/-RANGE_SCALE_3D
|
||||
/// (it is named same as the board render for better understanding proposes)
|
||||
double m_BiuTo3Dunits;
|
||||
|
||||
/// Optional cache manager
|
||||
S3D_CACHE* m_cacheManager;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar *m_logTrace;
|
||||
};
|
||||
|
||||
#endif // _C3D_MODEL_VIEWER_H_
|
||||
@@ -1 +0,0 @@
|
||||
#define PLUGINDIR "@CMAKE_INSTALL_LIBDIR@"
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@gmail.com>
|
||||
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras@wanadoo.fr
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_read_mesh.cpp
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <common.h>
|
||||
#include <macros.h>
|
||||
#include <kicad_string.h>
|
||||
#include <pgm_base.h>
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
|
||||
#include <3d_viewer.h>
|
||||
#include <info3d_visu.h>
|
||||
#include "3d_struct.h"
|
||||
#include "modelparsers.h"
|
||||
|
||||
|
||||
S3D_MODEL_PARSER *S3D_MODEL_PARSER::Create( S3D_MASTER* aMaster,
|
||||
const wxString aExtension )
|
||||
{
|
||||
if ( aExtension == wxT( "x3d" ) )
|
||||
return new X3D_MODEL_PARSER( aMaster );
|
||||
else if ( aExtension == wxT( "wrl" ) )
|
||||
return new VRML_MODEL_PARSER( aMaster );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int S3D_MASTER::ReadData( S3D_MODEL_PARSER* aParser )
|
||||
{
|
||||
if( m_Shape3DFullFilename.IsEmpty() || aParser == NULL )
|
||||
return -1;
|
||||
|
||||
wxString filename = m_Shape3DFullFilename;
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
filename.Replace( wxT( "/" ), wxT( "\\" ) );
|
||||
#else
|
||||
filename.Replace( wxT( "\\" ), wxT( "/" ) );
|
||||
#endif
|
||||
|
||||
if( wxFileName::FileExists( filename ) )
|
||||
{
|
||||
wxFileName fn( filename );
|
||||
|
||||
if( aParser->Load( filename ) )
|
||||
{
|
||||
// Invalidate bounding boxes
|
||||
m_fastAABBox.Reset();
|
||||
m_BBox.Reset();
|
||||
|
||||
m_parser = aParser;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
wxLogDebug( wxT( "3D shape '%s' not found, even tried '%s' after env var substitution." ),
|
||||
GetChars( m_Shape3DName ),
|
||||
GetChars( filename ) );
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void S3D_MASTER::Render( bool aIsRenderingJustNonTransparentObjects,
|
||||
bool aIsRenderingJustTransparentObjects )
|
||||
{
|
||||
if( m_parser == NULL )
|
||||
return;
|
||||
|
||||
double aVrmlunits_to_3Dunits = g_Parm_3D_Visu.m_BiuTo3Dunits * UNITS3D_TO_UNITSPCB;
|
||||
|
||||
glScalef( aVrmlunits_to_3Dunits, aVrmlunits_to_3Dunits, aVrmlunits_to_3Dunits );
|
||||
|
||||
glTranslatef( m_MatPosition.x * SCALE_3D_CONV,
|
||||
m_MatPosition.y * SCALE_3D_CONV,
|
||||
m_MatPosition.z * SCALE_3D_CONV );
|
||||
|
||||
glRotatef( -m_MatRotation.z, 0.0f, 0.0f, 1.0f );
|
||||
glRotatef( -m_MatRotation.y, 0.0f, 1.0f, 0.0f );
|
||||
glRotatef( -m_MatRotation.x, 1.0f, 0.0f, 0.0f );
|
||||
|
||||
glScalef( m_MatScale.x, m_MatScale.y, m_MatScale.z );
|
||||
|
||||
for( unsigned int idx = 0; idx < m_parser->childs.size(); idx++ )
|
||||
m_parser->childs[idx]->openGL_RenderAllChilds( aIsRenderingJustNonTransparentObjects,
|
||||
aIsRenderingJustTransparentObjects );
|
||||
}
|
||||
|
||||
|
||||
CBBOX &S3D_MASTER::getBBox( )
|
||||
{
|
||||
if( !m_BBox.IsInitialized() )
|
||||
calcBBox();
|
||||
|
||||
return m_BBox;
|
||||
}
|
||||
|
||||
|
||||
CBBOX &S3D_MASTER::getFastAABBox( )
|
||||
{
|
||||
if( !m_fastAABBox.IsInitialized() )
|
||||
calcBBox();
|
||||
|
||||
return m_fastAABBox;
|
||||
}
|
||||
|
||||
|
||||
void S3D_MASTER::calcBBox()
|
||||
{
|
||||
if( m_parser == NULL )
|
||||
return;
|
||||
|
||||
bool firstBBox = true;
|
||||
|
||||
for( unsigned int idx = 0; idx < m_parser->childs.size(); idx++ )
|
||||
if( firstBBox )
|
||||
{
|
||||
firstBBox = false;
|
||||
m_BBox = m_parser->childs[idx]->getBBox();
|
||||
}
|
||||
else
|
||||
m_BBox.Union( m_parser->childs[idx]->getBBox() );
|
||||
|
||||
// Calc transformation matrix to apply in AABBox
|
||||
|
||||
float aVrmlunits_to_3Dunits = g_Parm_3D_Visu.m_BiuTo3Dunits * UNITS3D_TO_UNITSPCB;
|
||||
|
||||
glm::mat4 fullTransformMatrix;
|
||||
|
||||
fullTransformMatrix = glm::scale( glm::mat4(), S3D_VERTEX( aVrmlunits_to_3Dunits,
|
||||
aVrmlunits_to_3Dunits,
|
||||
aVrmlunits_to_3Dunits ) );
|
||||
|
||||
fullTransformMatrix = glm::translate( fullTransformMatrix, S3D_VERTEX( m_MatPosition.x * SCALE_3D_CONV,
|
||||
m_MatPosition.y * SCALE_3D_CONV,
|
||||
m_MatPosition.z * SCALE_3D_CONV) );
|
||||
|
||||
if( m_MatRotation.z != 0.0 )
|
||||
fullTransformMatrix = glm::rotate( fullTransformMatrix, glm::radians(-(float)m_MatRotation.z), S3D_VERTEX( 0.0f, 0.0f, 1.0f ) );
|
||||
if( m_MatRotation.y != 0.0 )
|
||||
fullTransformMatrix = glm::rotate( fullTransformMatrix, glm::radians(-(float)m_MatRotation.y), S3D_VERTEX( 0.0f, 1.0f, 0.0f ) );
|
||||
if( m_MatRotation.x != 0.0 )
|
||||
fullTransformMatrix = glm::rotate( fullTransformMatrix, glm::radians(-(float)m_MatRotation.x), S3D_VERTEX( 1.0f, 0.0f, 0.0f ) );
|
||||
|
||||
fullTransformMatrix = glm::scale( fullTransformMatrix, S3D_VERTEX( m_MatScale.x, m_MatScale.y, m_MatScale.z ) );
|
||||
|
||||
// Apply transformation
|
||||
m_fastAABBox = m_BBox;
|
||||
m_fastAABBox.ApplyTransformationAA( fullTransformMatrix );
|
||||
}
|
||||
@@ -1,982 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_render_createscene_ogl_legacy.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "c3d_render_ogl_legacy.h"
|
||||
#include "ogl_legacy_utils.h"
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include "../../3d_math.h"
|
||||
#include "../../3d_fastmath.h"
|
||||
#include <trigo.h>
|
||||
#include <project.h>
|
||||
#include <profile.h> // To use GetRunningMicroSecs or another profiling utility
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CFILLEDCIRCLE2D * aFilledCircle,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F ¢er = aFilledCircle->GetCenter();
|
||||
const float radius = aFilledCircle->GetRadius() *
|
||||
2.0f; // Double because the render triangle
|
||||
|
||||
// This is a small adjustment to the circle texture
|
||||
const float texture_factor = (8.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
|
||||
const float f = (sqrtf(2.0f) / 2.0f) * radius * texture_factor;
|
||||
|
||||
// Top and Bot segments ends are just triangle semi-circles, so need to add
|
||||
// it in duplicated
|
||||
aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, aZtop ),
|
||||
SFVEC3F( center.x - f, center.y, aZtop ),
|
||||
SFVEC3F( center.x,
|
||||
center.y - f, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, aZtop ),
|
||||
SFVEC3F( center.x + f, center.y, aZtop ),
|
||||
SFVEC3F( center.x,
|
||||
center.y + f, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, aZbot ),
|
||||
SFVEC3F( center.x + f, center.y, aZbot ),
|
||||
SFVEC3F( center.x,
|
||||
center.y - f, aZbot ) );
|
||||
|
||||
aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, aZbot ),
|
||||
SFVEC3F( center.x - f, center.y, aZbot ),
|
||||
SFVEC3F( center.x,
|
||||
center.y + f, aZbot ) );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CPOLYGON4PTS2D * aPoly,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F &v0 = aPoly->GetV0();
|
||||
const SFVEC2F &v1 = aPoly->GetV1();
|
||||
const SFVEC2F &v2 = aPoly->GetV2();
|
||||
const SFVEC2F &v3 = aPoly->GetV3();
|
||||
|
||||
add_triangle_top_bot( aDstLayer, v0, v2, v1, aZtop, aZbot );
|
||||
add_triangle_top_bot( aDstLayer, v2, v0, v3, aZtop, aZbot );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::generate_ring_contour( const SFVEC2F &aCenter,
|
||||
float aInnerRadius,
|
||||
float aOuterRadius,
|
||||
unsigned int aNr_sides_per_circle,
|
||||
std::vector< SFVEC2F > &aInnerContourResult,
|
||||
std::vector< SFVEC2F > &aOuterContourResult,
|
||||
bool aInvertOrder )
|
||||
{
|
||||
aInnerContourResult.clear();
|
||||
aInnerContourResult.reserve( aNr_sides_per_circle + 2 );
|
||||
|
||||
aOuterContourResult.clear();
|
||||
aOuterContourResult.reserve( aNr_sides_per_circle + 2 );
|
||||
|
||||
const int delta = 3600 / aNr_sides_per_circle;
|
||||
|
||||
for( int ii = 0; ii < 3600; ii += delta )
|
||||
{
|
||||
float angle = (float)( aInvertOrder ? ( 3600 - ii ) : ii )
|
||||
* 2.0f * glm::pi<float>() / 3600.0f;
|
||||
const SFVEC2F rotatedDir = SFVEC2F( cos( angle ), sin( angle ) );
|
||||
|
||||
aInnerContourResult.push_back( SFVEC2F( aCenter.x + rotatedDir.x * aInnerRadius,
|
||||
aCenter.y + rotatedDir.y * aInnerRadius ) );
|
||||
|
||||
aOuterContourResult.push_back( SFVEC2F( aCenter.x + rotatedDir.x * aOuterRadius,
|
||||
aCenter.y + rotatedDir.y * aOuterRadius ) );
|
||||
}
|
||||
|
||||
aInnerContourResult.push_back( aInnerContourResult[0] );
|
||||
aOuterContourResult.push_back( aOuterContourResult[0] );
|
||||
|
||||
wxASSERT( aInnerContourResult.size() == aOuterContourResult.size() );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CRING2D * aRing,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F ¢er = aRing->GetCenter();
|
||||
const float inner = aRing->GetInnerRadius();
|
||||
const float outer = aRing->GetOuterRadius();
|
||||
|
||||
std::vector< SFVEC2F > innerContour;
|
||||
std::vector< SFVEC2F > outerContour;
|
||||
|
||||
generate_ring_contour( center,
|
||||
inner,
|
||||
outer,
|
||||
m_settings.GetNrSegmentsCircle( outer * 2.0f ),
|
||||
innerContour,
|
||||
outerContour,
|
||||
false );
|
||||
|
||||
// This will add the top and bot quads that will form the approximated ring
|
||||
|
||||
for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
|
||||
{
|
||||
const SFVEC2F &vi0 = innerContour[i + 0];
|
||||
const SFVEC2F &vi1 = innerContour[i + 1];
|
||||
const SFVEC2F &vo0 = outerContour[i + 0];
|
||||
const SFVEC2F &vo1 = outerContour[i + 1];
|
||||
|
||||
aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZtop ),
|
||||
SFVEC3F( vi0.x, vi0.y, aZtop ),
|
||||
SFVEC3F( vo0.x, vo0.y, aZtop ),
|
||||
SFVEC3F( vo1.x, vo1.y, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZbot ),
|
||||
SFVEC3F( vo1.x, vo1.y, aZbot ),
|
||||
SFVEC3F( vo0.x, vo0.y, aZbot ),
|
||||
SFVEC3F( vi0.x, vi0.y, aZbot ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CTRIANGLE2D * aTri,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F &v1 = aTri->GetP1();
|
||||
const SFVEC2F &v2 = aTri->GetP2();
|
||||
const SFVEC2F &v3 = aTri->GetP3();
|
||||
|
||||
add_triangle_top_bot( aDstLayer, v1, v2, v3, aZtop, aZbot );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CROUNDSEGMENT2D * aSeg,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F leftStart = aSeg->GetLeftStar();
|
||||
const SFVEC2F leftEnd = aSeg->GetLeftEnd();
|
||||
const SFVEC2F leftDir = aSeg->GetLeftDir();
|
||||
|
||||
const SFVEC2F rightStart = aSeg->GetRightStar();
|
||||
const SFVEC2F rightEnd = aSeg->GetRightEnd();
|
||||
const SFVEC2F rightDir = aSeg->GetRightDir();
|
||||
const float radius = aSeg->GetRadius();
|
||||
|
||||
const SFVEC2F start = aSeg->GetStart();
|
||||
const SFVEC2F end = aSeg->GetEnd();
|
||||
|
||||
const float texture_factor = (12.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
|
||||
const float texture_factorF= ( 6.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
|
||||
|
||||
const float radius_of_the_square = sqrtf( aSeg->GetRadiusSquared() * 2.0f );
|
||||
const float radius_triangle_factor = (radius_of_the_square - radius) / radius;
|
||||
|
||||
const SFVEC2F factorS = SFVEC2F( -rightDir.y * radius * radius_triangle_factor,
|
||||
rightDir.x * radius * radius_triangle_factor );
|
||||
|
||||
const SFVEC2F factorE = SFVEC2F( -leftDir.y * radius * radius_triangle_factor,
|
||||
leftDir.x * radius * radius_triangle_factor );
|
||||
|
||||
// Top end segment triangles (semi-circles)
|
||||
aDstLayer->m_layer_top_segment_ends->AddTriangle(
|
||||
SFVEC3F( rightEnd.x + texture_factor * factorS.x,
|
||||
rightEnd.y + texture_factor * factorS.y,
|
||||
aZtop ),
|
||||
SFVEC3F( leftStart.x + texture_factor * factorE.x,
|
||||
leftStart.y + texture_factor * factorE.y,
|
||||
aZtop ),
|
||||
SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ),
|
||||
start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ),
|
||||
aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_top_segment_ends->AddTriangle(
|
||||
SFVEC3F( leftEnd.x + texture_factor * factorE.x,
|
||||
leftEnd.y + texture_factor * factorE.y, aZtop ),
|
||||
SFVEC3F( rightStart.x + texture_factor * factorS.x,
|
||||
rightStart.y + texture_factor * factorS.y, aZtop ),
|
||||
SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ),
|
||||
end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ),
|
||||
aZtop ) );
|
||||
|
||||
// Bot end segment triangles (semi-circles)
|
||||
aDstLayer->m_layer_bot_segment_ends->AddTriangle(
|
||||
SFVEC3F( leftStart.x + texture_factor * factorE.x,
|
||||
leftStart.y + texture_factor * factorE.y,
|
||||
aZbot ),
|
||||
SFVEC3F( rightEnd.x + texture_factor * factorS.x,
|
||||
rightEnd.y + texture_factor * factorS.y,
|
||||
aZbot ),
|
||||
SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ),
|
||||
start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ),
|
||||
aZbot ) );
|
||||
|
||||
aDstLayer->m_layer_bot_segment_ends->AddTriangle(
|
||||
SFVEC3F( rightStart.x + texture_factor * factorS.x,
|
||||
rightStart.y + texture_factor * factorS.y, aZbot ),
|
||||
SFVEC3F( leftEnd.x + texture_factor * factorE.x,
|
||||
leftEnd.y + texture_factor * factorE.y, aZbot ),
|
||||
SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ),
|
||||
end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ),
|
||||
aZbot ) );
|
||||
|
||||
// Segment top and bot planes
|
||||
aDstLayer->m_layer_top_triangles->AddQuad(
|
||||
SFVEC3F( rightEnd.x, rightEnd.y, aZtop ),
|
||||
SFVEC3F( rightStart.x, rightStart.y, aZtop ),
|
||||
SFVEC3F( leftEnd.x, leftEnd.y, aZtop ),
|
||||
SFVEC3F( leftStart.x, leftStart.y, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_bot_triangles->AddQuad(
|
||||
SFVEC3F( rightEnd.x, rightEnd.y, aZbot ),
|
||||
SFVEC3F( leftStart.x, leftStart.y, aZbot ),
|
||||
SFVEC3F( leftEnd.x, leftEnd.y, aZbot ),
|
||||
SFVEC3F( rightStart.x, rightStart.y, aZbot ) );
|
||||
}
|
||||
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS *C3D_RENDER_OGL_LEGACY::generate_holes_display_list(
|
||||
const LIST_OBJECT2D &aListHolesObject2d,
|
||||
const SHAPE_POLY_SET &aPoly,
|
||||
float aZtop,
|
||||
float aZbot,
|
||||
bool aInvertFaces )
|
||||
{
|
||||
CLAYERS_OGL_DISP_LISTS *ret = NULL;
|
||||
|
||||
if( aListHolesObject2d.size() > 0 )
|
||||
{
|
||||
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( aListHolesObject2d.size() * 2 );
|
||||
|
||||
// Convert the list of objects(filled circles) to triangle layer structure
|
||||
for( LIST_OBJECT2D::const_iterator itemOnLayer = aListHolesObject2d.begin();
|
||||
itemOnLayer != aListHolesObject2d.end();
|
||||
++itemOnLayer )
|
||||
{
|
||||
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||
|
||||
wxASSERT( (object2d_A->GetObjectType() == OBJ2D_FILLED_CIRCLE) ||
|
||||
(object2d_A->GetObjectType() == OBJ2D_ROUNDSEG) );
|
||||
|
||||
switch( object2d_A->GetObjectType() )
|
||||
{
|
||||
case OBJ2D_FILLED_CIRCLE:
|
||||
add_object_to_triangle_layer( (const CFILLEDCIRCLE2D *)object2d_A,
|
||||
layerTriangles,
|
||||
aZtop, aZbot );
|
||||
break;
|
||||
|
||||
case OBJ2D_ROUNDSEG:
|
||||
add_object_to_triangle_layer( (const CROUNDSEGMENT2D *) object2d_A,
|
||||
layerTriangles,
|
||||
aZtop, aZbot );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG("C3D_RENDER_OGL_LEGACY::generate_holes_display_list: Object type is not implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: he can have a aListHolesObject2d whith holes but without countours
|
||||
// eg: when there are only NPTH on the list and the contours were not
|
||||
// added
|
||||
|
||||
if( aPoly.OutlineCount() > 0 )
|
||||
{
|
||||
layerTriangles->AddToMiddleContourns( aPoly,
|
||||
aZbot,
|
||||
aZtop,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
aInvertFaces );
|
||||
}
|
||||
|
||||
ret = new CLAYERS_OGL_DISP_LISTS( *layerTriangles,
|
||||
m_ogl_circle_texture,
|
||||
aZbot,
|
||||
aZtop );
|
||||
|
||||
delete layerTriangles;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::reload( REPORTER *aStatusTextReporter )
|
||||
{
|
||||
m_reloadRequested = false;
|
||||
|
||||
ogl_free_all_display_lists();
|
||||
|
||||
COBJECT2D_STATS::Instance().ResetStats();
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
printf("InitSettings...\n");
|
||||
#endif
|
||||
|
||||
unsigned stats_startReloadTime = GetRunningMicroSecs();
|
||||
|
||||
m_settings.InitSettings( aStatusTextReporter );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_endReloadTime = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
SFVEC3F camera_pos = m_settings.GetBoardCenter3DU();
|
||||
m_settings.CameraGet().SetBoardLookAtPos( camera_pos );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_start_OpenGL_Load_Time = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Load OpenGL: board" ) );
|
||||
|
||||
// Create Board
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CCONTAINER2D boardContainer;
|
||||
SHAPE_POLY_SET tmpBoard = m_settings.GetBoardPoly();
|
||||
Convert_shape_line_polygon_to_triangles( tmpBoard,
|
||||
boardContainer,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
(const BOARD_ITEM &)*m_settings.GetBoard() );
|
||||
|
||||
const LIST_OBJECT2D &listBoardObject2d = boardContainer.GetList();
|
||||
|
||||
if( listBoardObject2d.size() > 0 )
|
||||
{
|
||||
// We will set a unitary Z so it will in future used with transformations
|
||||
// since the board poly will be used not only to draw itself but also the
|
||||
// solder mask layers.
|
||||
const float layer_z_top = 1.0f;
|
||||
const float layer_z_bot = 0.0f;
|
||||
|
||||
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( listBoardObject2d.size() );
|
||||
|
||||
// Convert the list of objects(triangles) to triangle layer structure
|
||||
for( LIST_OBJECT2D::const_iterator itemOnLayer = listBoardObject2d.begin();
|
||||
itemOnLayer != listBoardObject2d.end();
|
||||
++itemOnLayer )
|
||||
{
|
||||
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||
|
||||
wxASSERT( object2d_A->GetObjectType() == OBJ2D_TRIANGLE );
|
||||
|
||||
const CTRIANGLE2D *tri = (const CTRIANGLE2D *)object2d_A;
|
||||
|
||||
const SFVEC2F &v1 = tri->GetP1();
|
||||
const SFVEC2F &v2 = tri->GetP2();
|
||||
const SFVEC2F &v3 = tri->GetP3();
|
||||
|
||||
add_triangle_top_bot( layerTriangles,
|
||||
v1,
|
||||
v2,
|
||||
v3,
|
||||
layer_z_top,
|
||||
layer_z_bot );
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET &boardPoly = m_settings.GetBoardPoly();
|
||||
|
||||
wxASSERT( boardPoly.OutlineCount() > 0 );
|
||||
|
||||
if( boardPoly.OutlineCount() > 0 )
|
||||
{
|
||||
layerTriangles->AddToMiddleContourns( boardPoly,
|
||||
layer_z_bot,
|
||||
layer_z_top,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
false );
|
||||
|
||||
m_ogl_disp_list_board = new CLAYERS_OGL_DISP_LISTS( *layerTriangles,
|
||||
m_ogl_circle_texture,
|
||||
layer_z_top,
|
||||
layer_z_top );
|
||||
}
|
||||
|
||||
delete layerTriangles;
|
||||
}
|
||||
|
||||
// Create Through Holes and vias
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Load OpenGL: holes and vias" ) );
|
||||
|
||||
m_ogl_disp_list_through_holes_outer = generate_holes_display_list(
|
||||
m_settings.GetThroughHole_Outer().GetList(),
|
||||
m_settings.GetThroughHole_Outer_poly(),
|
||||
1.0f,
|
||||
0.0f,
|
||||
false );
|
||||
|
||||
SHAPE_POLY_SET bodyHoles = m_settings.GetThroughHole_Outer_poly();
|
||||
|
||||
bodyHoles.BooleanAdd( m_settings.GetThroughHole_Outer_poly_NPTH(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
m_ogl_disp_list_through_holes_outer_with_npth = generate_holes_display_list(
|
||||
m_settings.GetThroughHole_Outer().GetList(),
|
||||
bodyHoles,
|
||||
1.0f,
|
||||
0.0f,
|
||||
false );
|
||||
|
||||
m_ogl_disp_list_through_holes_inner = generate_holes_display_list(
|
||||
m_settings.GetThroughHole_Inner().GetList(),
|
||||
m_settings.GetThroughHole_Inner_poly(),
|
||||
1.0f,
|
||||
0.0f,
|
||||
true );
|
||||
|
||||
|
||||
m_ogl_disp_list_through_holes_vias_outer = generate_holes_display_list(
|
||||
m_settings.GetThroughHole_Vias_Outer().GetList(),
|
||||
m_settings.GetThroughHole_Vias_Outer_poly(),
|
||||
1.0f,
|
||||
0.0f,
|
||||
false );
|
||||
|
||||
// Not in use
|
||||
//m_ogl_disp_list_through_holes_vias_inner = generate_holes_display_list(
|
||||
// m_settings.GetThroughHole_Vias_Inner().GetList(),
|
||||
// m_settings.GetThroughHole_Vias_Inner_poly(),
|
||||
// 1.0f, 0.0f,
|
||||
// false );
|
||||
|
||||
const MAP_POLY & innerMapHoles = m_settings.GetPolyMapHoles_Inner();
|
||||
const MAP_POLY & outerMapHoles = m_settings.GetPolyMapHoles_Outer();
|
||||
|
||||
wxASSERT( innerMapHoles.size() == outerMapHoles.size() );
|
||||
|
||||
const MAP_CONTAINER_2D &map_holes = m_settings.GetMapLayersHoles();
|
||||
|
||||
if( outerMapHoles.size() > 0 )
|
||||
{
|
||||
float layer_z_bot = 0.0f;
|
||||
float layer_z_top = 0.0f;
|
||||
|
||||
for( MAP_POLY::const_iterator ii = outerMapHoles.begin();
|
||||
ii != outerMapHoles.end();
|
||||
++ii )
|
||||
{
|
||||
PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
|
||||
const SHAPE_POLY_SET *poly = static_cast<const SHAPE_POLY_SET *>(ii->second);
|
||||
const CBVHCONTAINER2D *container = map_holes.at( layer_id );
|
||||
|
||||
get_layer_z_pos( layer_id, layer_z_top, layer_z_bot );
|
||||
|
||||
m_ogl_disp_lists_layers_holes_outer[layer_id] = generate_holes_display_list(
|
||||
container->GetList(),
|
||||
*poly,
|
||||
layer_z_top,
|
||||
layer_z_bot,
|
||||
false );
|
||||
}
|
||||
|
||||
for( MAP_POLY::const_iterator ii = innerMapHoles.begin();
|
||||
ii != innerMapHoles.end();
|
||||
++ii )
|
||||
{
|
||||
PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
|
||||
const SHAPE_POLY_SET *poly = static_cast<const SHAPE_POLY_SET *>(ii->second);
|
||||
const CBVHCONTAINER2D *container = map_holes.at( layer_id );
|
||||
|
||||
get_layer_z_pos( layer_id, layer_z_top, layer_z_bot );
|
||||
|
||||
m_ogl_disp_lists_layers_holes_inner[layer_id] = generate_holes_display_list(
|
||||
container->GetList(),
|
||||
*poly,
|
||||
layer_z_top,
|
||||
layer_z_bot,
|
||||
false );
|
||||
}
|
||||
}
|
||||
|
||||
// Generate vertical cylinders of vias and pads (copper)
|
||||
generate_3D_Vias_and_Pads();
|
||||
|
||||
// Add layers maps
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Load OpenGL: layers" ) );
|
||||
|
||||
for( MAP_CONTAINER_2D::const_iterator ii = m_settings.GetMapLayers().begin();
|
||||
ii != m_settings.GetMapLayers().end();
|
||||
++ii )
|
||||
{
|
||||
PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
|
||||
|
||||
if( !m_settings.Is3DLayerEnabled( layer_id ) )
|
||||
continue;
|
||||
|
||||
const CBVHCONTAINER2D *container2d = static_cast<const CBVHCONTAINER2D *>(ii->second);
|
||||
const LIST_OBJECT2D &listObject2d = container2d->GetList();
|
||||
|
||||
if( listObject2d.size() == 0 )
|
||||
continue;
|
||||
|
||||
float layer_z_bot = 0.0f;
|
||||
float layer_z_top = 0.0f;
|
||||
|
||||
get_layer_z_pos( layer_id, layer_z_top, layer_z_bot );
|
||||
|
||||
// Calculate an estimation for the nr of triangles based on the nr of objects
|
||||
unsigned int nrTrianglesEstimation = listObject2d.size() * 8;
|
||||
|
||||
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( nrTrianglesEstimation );
|
||||
|
||||
m_triangles[layer_id] = layerTriangles;
|
||||
|
||||
// Load the 2D (X,Y axis) component of shapes
|
||||
for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin();
|
||||
itemOnLayer != listObject2d.end();
|
||||
++itemOnLayer )
|
||||
{
|
||||
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||
|
||||
switch( object2d_A->GetObjectType() )
|
||||
{
|
||||
case OBJ2D_FILLED_CIRCLE:
|
||||
add_object_to_triangle_layer( (const CFILLEDCIRCLE2D *)object2d_A,
|
||||
layerTriangles,
|
||||
layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
case OBJ2D_POLYGON4PT:
|
||||
add_object_to_triangle_layer( (const CPOLYGON4PTS2D *)object2d_A,
|
||||
layerTriangles,
|
||||
layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
case OBJ2D_RING:
|
||||
add_object_to_triangle_layer( (const CRING2D *)object2d_A,
|
||||
layerTriangles,
|
||||
layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
case OBJ2D_TRIANGLE:
|
||||
add_object_to_triangle_layer( (const CTRIANGLE2D *)object2d_A,
|
||||
layerTriangles,
|
||||
layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
case OBJ2D_ROUNDSEG:
|
||||
add_object_to_triangle_layer( (const CROUNDSEGMENT2D *) object2d_A,
|
||||
layerTriangles,
|
||||
layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG("C3D_RENDER_OGL_LEGACY: Object type is not implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const MAP_POLY &map_poly = m_settings.GetPolyMap();
|
||||
|
||||
// Load the vertical (Z axis) component of shapes
|
||||
if( map_poly.find( layer_id ) != map_poly.end() )
|
||||
{
|
||||
const SHAPE_POLY_SET *polyList = map_poly.at( layer_id );
|
||||
|
||||
if( polyList->OutlineCount() > 0 )
|
||||
layerTriangles->AddToMiddleContourns( *polyList, layer_z_bot, layer_z_top,
|
||||
m_settings.BiuTo3Dunits(), false );
|
||||
}
|
||||
|
||||
// Create display list
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
m_ogl_disp_lists_layers[layer_id] = new CLAYERS_OGL_DISP_LISTS( *layerTriangles,
|
||||
m_ogl_circle_texture,
|
||||
layer_z_bot,
|
||||
layer_z_top );
|
||||
}// for each layer on map
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_end_OpenGL_Load_Time = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
// Load 3D models
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_start_models_Load_Time = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Loading 3D models" ) );
|
||||
|
||||
load_3D_models( aStatusTextReporter );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_end_models_Load_Time = GetRunningMicroSecs();
|
||||
|
||||
|
||||
printf( "C3D_RENDER_OGL_LEGACY::reload times:\n" );
|
||||
printf( " Reload board: %.3f ms\n",
|
||||
(float)( stats_endReloadTime - stats_startReloadTime ) / 1000.0f );
|
||||
printf( " Loading to openGL: %.3f ms\n",
|
||||
(float)( stats_end_OpenGL_Load_Time - stats_start_OpenGL_Load_Time ) / 1000.0f );
|
||||
printf( " Loading 3D models: %.3f ms\n",
|
||||
(float)( stats_end_models_Load_Time - stats_start_models_Load_Time ) / 1000.0f );
|
||||
COBJECT2D_STATS::Instance().PrintStats();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
{
|
||||
// Calculation time in seconds
|
||||
const double calculation_time = (double)( GetRunningMicroSecs() -
|
||||
stats_startReloadTime) / 1e6;
|
||||
|
||||
aStatusTextReporter->Report( wxString::Format( _( "Reload time %.3f s" ),
|
||||
calculation_time ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_triangle_top_bot( CLAYER_TRIANGLES *aDst,
|
||||
const SFVEC2F &v0,
|
||||
const SFVEC2F &v1,
|
||||
const SFVEC2F &v2,
|
||||
float top,
|
||||
float bot )
|
||||
{
|
||||
aDst->m_layer_bot_triangles->AddTriangle( SFVEC3F( v0.x, v0.y, bot ),
|
||||
SFVEC3F( v1.x, v1.y, bot ),
|
||||
SFVEC3F( v2.x, v2.y, bot ) );
|
||||
|
||||
aDst->m_layer_top_triangles->AddTriangle( SFVEC3F( v2.x, v2.y, top ),
|
||||
SFVEC3F( v1.x, v1.y, top ),
|
||||
SFVEC3F( v0.x, v0.y, top ) );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::get_layer_z_pos ( PCB_LAYER_ID aLayerID,
|
||||
float &aOutZtop,
|
||||
float &aOutZbot ) const
|
||||
{
|
||||
aOutZbot = m_settings.GetLayerBottomZpos3DU( aLayerID );
|
||||
aOutZtop = m_settings.GetLayerTopZpos3DU( aLayerID );
|
||||
|
||||
if( aOutZtop < aOutZbot )
|
||||
{
|
||||
float tmpFloat = aOutZbot;
|
||||
aOutZbot = aOutZtop;
|
||||
aOutZtop = tmpFloat;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::generate_cylinder( const SFVEC2F &aCenter,
|
||||
float aInnerRadius,
|
||||
float aOuterRadius,
|
||||
float aZtop,
|
||||
float aZbot,
|
||||
unsigned int aNr_sides_per_circle,
|
||||
CLAYER_TRIANGLES *aDstLayer )
|
||||
{
|
||||
std::vector< SFVEC2F > innerContour;
|
||||
std::vector< SFVEC2F > outerContour;
|
||||
|
||||
generate_ring_contour( aCenter,
|
||||
aInnerRadius,
|
||||
aOuterRadius,
|
||||
aNr_sides_per_circle,
|
||||
innerContour,
|
||||
outerContour,
|
||||
false );
|
||||
|
||||
for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
|
||||
{
|
||||
const SFVEC2F &vi0 = innerContour[i + 0];
|
||||
const SFVEC2F &vi1 = innerContour[i + 1];
|
||||
const SFVEC2F &vo0 = outerContour[i + 0];
|
||||
const SFVEC2F &vo1 = outerContour[i + 1];
|
||||
|
||||
aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZtop ),
|
||||
SFVEC3F( vi0.x, vi0.y, aZtop ),
|
||||
SFVEC3F( vo0.x, vo0.y, aZtop ),
|
||||
SFVEC3F( vo1.x, vo1.y, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZbot ),
|
||||
SFVEC3F( vo1.x, vo1.y, aZbot ),
|
||||
SFVEC3F( vo0.x, vo0.y, aZbot ),
|
||||
SFVEC3F( vi0.x, vi0.y, aZbot ) );
|
||||
}
|
||||
|
||||
aDstLayer->AddToMiddleContourns( outerContour, aZbot, aZtop, true );
|
||||
aDstLayer->AddToMiddleContourns( innerContour, aZbot, aZtop, false );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::generate_3D_Vias_and_Pads()
|
||||
{
|
||||
if( m_settings.GetStats_Nr_Vias() )
|
||||
{
|
||||
const unsigned int reserve_nr_triangles_estimation =
|
||||
m_settings.GetNrSegmentsCircle( m_settings.GetStats_Med_Via_Hole_Diameter3DU() ) *
|
||||
8 *
|
||||
m_settings.GetStats_Nr_Vias();
|
||||
|
||||
CLAYER_TRIANGLES *layerTriangleVIA = new CLAYER_TRIANGLES( reserve_nr_triangles_estimation );
|
||||
|
||||
// Insert plated vertical holes inside the board
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Insert vias holes (vertical cylinders)
|
||||
for( const TRACK* track = m_settings.GetBoard()->m_Track;
|
||||
track;
|
||||
track = track->Next() )
|
||||
{
|
||||
if( track->Type() == PCB_VIA_T )
|
||||
{
|
||||
const VIA *via = static_cast<const VIA*>(track);
|
||||
|
||||
const float holediameter = via->GetDrillValue() * m_settings.BiuTo3Dunits();
|
||||
const float thickness = m_settings.GetCopperThickness3DU();
|
||||
const int nrSegments = m_settings.GetNrSegmentsCircle( via->GetDrillValue() );
|
||||
const double correctionFactor = m_settings.GetCircleCorrectionFactor( nrSegments );
|
||||
const float hole_inner_radius = ( holediameter / 2.0f ) * correctionFactor;
|
||||
|
||||
const SFVEC2F via_center( via->GetStart().x * m_settings.BiuTo3Dunits(),
|
||||
-via->GetStart().y * m_settings.BiuTo3Dunits() );
|
||||
|
||||
PCB_LAYER_ID top_layer, bottom_layer;
|
||||
via->LayerPair( &top_layer, &bottom_layer );
|
||||
|
||||
float ztop, zbot, dummy;
|
||||
|
||||
get_layer_z_pos( top_layer, ztop, dummy );
|
||||
get_layer_z_pos( bottom_layer, dummy, zbot );
|
||||
|
||||
wxASSERT( zbot < ztop );
|
||||
|
||||
generate_cylinder( via_center,
|
||||
hole_inner_radius,
|
||||
hole_inner_radius + thickness,
|
||||
ztop,
|
||||
zbot,
|
||||
nrSegments,
|
||||
layerTriangleVIA );
|
||||
}
|
||||
}
|
||||
|
||||
m_ogl_disp_list_via = new CLAYERS_OGL_DISP_LISTS( *layerTriangleVIA,
|
||||
0,
|
||||
0.0f,
|
||||
0.0f );
|
||||
|
||||
delete layerTriangleVIA;
|
||||
}
|
||||
|
||||
|
||||
if( m_settings.GetStats_Nr_Holes() > 0 )
|
||||
{
|
||||
SHAPE_POLY_SET tht_outer_holes_poly; // Stores the outer poly of the copper holes (the pad)
|
||||
SHAPE_POLY_SET tht_inner_holes_poly; // Stores the inner poly of the copper holes (the hole)
|
||||
|
||||
tht_outer_holes_poly.RemoveAllContours();
|
||||
tht_inner_holes_poly.RemoveAllContours();
|
||||
|
||||
// Insert pads holes (vertical cylinders)
|
||||
for( const MODULE* module = m_settings.GetBoard()->m_Modules;
|
||||
module;
|
||||
module = module->Next() )
|
||||
{
|
||||
for( const D_PAD* pad = module->PadsList(); pad; pad = pad->Next() )
|
||||
{
|
||||
if( pad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED )
|
||||
{
|
||||
const wxSize drillsize = pad->GetDrillSize();
|
||||
const bool hasHole = drillsize.x && drillsize.y;
|
||||
|
||||
if( !hasHole )
|
||||
continue;
|
||||
|
||||
// we use the hole diameter to calculate the seg count.
|
||||
// for round holes, drillsize.x == drillsize.y
|
||||
// for slots, the diameter is the smaller of (drillsize.x, drillsize.y)
|
||||
int copperThickness = m_settings.GetCopperThicknessBIU();
|
||||
int radius = std::min( drillsize.x, drillsize.y ) / 2 + copperThickness;
|
||||
int nrSegments = m_settings.GetNrSegmentsCircle( radius * 2 );
|
||||
double correctionFactor = m_settings.GetCircleCorrectionFactor( nrSegments );
|
||||
int correction = radius * ( correctionFactor - 1 );
|
||||
|
||||
pad->BuildPadDrillShapePolygon( tht_outer_holes_poly,
|
||||
copperThickness + correction,
|
||||
nrSegments );
|
||||
|
||||
pad->BuildPadDrillShapePolygon( tht_inner_holes_poly,
|
||||
correction,
|
||||
nrSegments );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Subtract the holes
|
||||
tht_outer_holes_poly.BooleanSubtract( tht_inner_holes_poly, SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
|
||||
CCONTAINER2D holesContainer;
|
||||
|
||||
Convert_shape_line_polygon_to_triangles( tht_outer_holes_poly,
|
||||
holesContainer,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
(const BOARD_ITEM &)*m_settings.GetBoard() );
|
||||
|
||||
const LIST_OBJECT2D &listHolesObject2d = holesContainer.GetList();
|
||||
|
||||
if( listHolesObject2d.size() > 0 )
|
||||
{
|
||||
float layer_z_top, layer_z_bot, dummy;
|
||||
|
||||
get_layer_z_pos( F_Cu, layer_z_top, dummy );
|
||||
get_layer_z_pos( B_Cu, dummy, layer_z_bot );
|
||||
|
||||
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( listHolesObject2d.size() );
|
||||
|
||||
// Convert the list of objects(triangles) to triangle layer structure
|
||||
for( LIST_OBJECT2D::const_iterator itemOnLayer = listHolesObject2d.begin();
|
||||
itemOnLayer != listHolesObject2d.end();
|
||||
++itemOnLayer )
|
||||
{
|
||||
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||
|
||||
wxASSERT( object2d_A->GetObjectType() == OBJ2D_TRIANGLE );
|
||||
|
||||
const CTRIANGLE2D *tri = (const CTRIANGLE2D *)object2d_A;
|
||||
|
||||
const SFVEC2F &v1 = tri->GetP1();
|
||||
const SFVEC2F &v2 = tri->GetP2();
|
||||
const SFVEC2F &v3 = tri->GetP3();
|
||||
|
||||
add_triangle_top_bot( layerTriangles,
|
||||
v1,
|
||||
v2,
|
||||
v3,
|
||||
layer_z_top,
|
||||
layer_z_bot );
|
||||
}
|
||||
|
||||
wxASSERT( tht_outer_holes_poly.OutlineCount() > 0 );
|
||||
|
||||
if( tht_outer_holes_poly.OutlineCount() > 0 )
|
||||
{
|
||||
layerTriangles->AddToMiddleContourns( tht_outer_holes_poly,
|
||||
layer_z_bot,
|
||||
layer_z_top,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
false );
|
||||
|
||||
m_ogl_disp_list_pads_holes = new CLAYERS_OGL_DISP_LISTS(
|
||||
*layerTriangles,
|
||||
m_ogl_circle_texture, // not need
|
||||
layer_z_top,
|
||||
layer_z_top );
|
||||
}
|
||||
|
||||
delete layerTriangles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function will get models from the cache and load it to openGL lists
|
||||
* in the form of C_OGL_3DMODEL. So this map of models will work as a local
|
||||
* cache for this render. (cache based on C_OGL_3DMODEL with associated
|
||||
* openGL lists in GPU memory)
|
||||
*/
|
||||
void C3D_RENDER_OGL_LEGACY::load_3D_models( REPORTER *aStatusTextReporter )
|
||||
{
|
||||
if( (!m_settings.GetFlag( FL_MODULE_ATTRIBUTES_NORMAL )) &&
|
||||
(!m_settings.GetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT )) &&
|
||||
(!m_settings.GetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL )) )
|
||||
return;
|
||||
|
||||
// Go for all modules
|
||||
for( const MODULE* module = m_settings.GetBoard()->m_Modules;
|
||||
module;
|
||||
module = module->Next() )
|
||||
{
|
||||
if( !module->Models().empty() )
|
||||
{
|
||||
// Get the list of model files for this model
|
||||
auto sM = module->Models().begin();
|
||||
auto eM = module->Models().end();
|
||||
|
||||
while( sM != eM )
|
||||
{
|
||||
if( !sM->m_Filename.empty() )
|
||||
{
|
||||
if( aStatusTextReporter )
|
||||
{
|
||||
// Display the short filename of the 3D model loaded:
|
||||
// (the full name is usually too long to be displayed)
|
||||
wxFileName fn( sM->m_Filename );
|
||||
wxString msg;
|
||||
msg.Printf( _( "Loading %s" ), fn.GetFullName() );
|
||||
aStatusTextReporter->Report( msg );
|
||||
}
|
||||
|
||||
// Check if the model is not present in our cache map
|
||||
// (Not already loaded in memory)
|
||||
if( m_3dmodel_map.find( sM->m_Filename ) == m_3dmodel_map.end() )
|
||||
{
|
||||
// It is not present, try get it from cache
|
||||
const S3DMODEL *modelPtr =
|
||||
m_settings.Get3DCacheManager()->GetModel( sM->m_Filename );
|
||||
|
||||
// only add it if the return is not NULL
|
||||
if( modelPtr )
|
||||
{
|
||||
C_OGL_3DMODEL* ogl_model =
|
||||
new C_OGL_3DMODEL( *modelPtr,
|
||||
m_settings.MaterialModeGet() );
|
||||
|
||||
if( ogl_model )
|
||||
m_3dmodel_map[ sM->m_Filename ] = ogl_model;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++sM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_render_ogl_legacy.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef C3D_RENDER_OGL_LEGACY_H_
|
||||
#define C3D_RENDER_OGL_LEGACY_H_
|
||||
|
||||
#include "../c3d_render_base.h"
|
||||
#include "clayer_triangles.h"
|
||||
|
||||
#include "../3d_render_raytracing/shapes2D/cpolygon2d.h"
|
||||
#include "../3d_render_raytracing/shapes2D/ctriangle2d.h"
|
||||
#include "../3d_render_raytracing/shapes2D/cpolygon4pts2d.h"
|
||||
#include "../3d_render_raytracing/shapes2D/cfilledcircle2d.h"
|
||||
#include "../3d_render_raytracing/shapes2D/cring2d.h"
|
||||
#include "../3d_render_raytracing/shapes2D/croundsegment2d.h"
|
||||
|
||||
#include "c_ogl_3dmodel.h"
|
||||
|
||||
#include "3d_cache/3d_info.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
typedef std::map< PCB_LAYER_ID, CLAYERS_OGL_DISP_LISTS* > MAP_OGL_DISP_LISTS;
|
||||
typedef std::map< PCB_LAYER_ID, CLAYER_TRIANGLES * > MAP_TRIANGLES;
|
||||
typedef std::map< wxString, C_OGL_3DMODEL * > MAP_3DMODEL;
|
||||
|
||||
#define SIZE_OF_CIRCLE_TEXTURE 1024
|
||||
|
||||
/**
|
||||
* @brief The C3D_RENDER_OGL_LEGACY class render the board using openGL legacy mode
|
||||
*/
|
||||
class C3D_RENDER_OGL_LEGACY : public C3D_RENDER_BASE
|
||||
{
|
||||
public:
|
||||
explicit C3D_RENDER_OGL_LEGACY( CINFO3D_VISU &aSettings );
|
||||
|
||||
~C3D_RENDER_OGL_LEGACY();
|
||||
|
||||
// Imported from C3D_RENDER_BASE
|
||||
void SetCurWindowSize( const wxSize &aSize ) override;
|
||||
bool Redraw( bool aIsMoving, REPORTER *aStatusTextReporter ) override;
|
||||
|
||||
int GetWaitForEditingTimeOut() override;
|
||||
|
||||
private:
|
||||
bool initializeOpenGL();
|
||||
void reload( REPORTER *aStatusTextReporter );
|
||||
|
||||
void ogl_set_arrow_material();
|
||||
|
||||
void ogl_free_all_display_lists();
|
||||
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers;
|
||||
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers_holes_outer;
|
||||
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers_holes_inner;
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_board;
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_through_holes_outer;
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_through_holes_inner;
|
||||
|
||||
// User for body render
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_through_holes_outer_with_npth;
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_through_holes_vias_outer;
|
||||
//CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_through_holes_vias_inner; // Not in use
|
||||
|
||||
// This is for pads holes of the modules
|
||||
//CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_vias_and_pad_holes_inner_contourn_and_caps;
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_vias_and_pad_holes_outer_contourn_and_caps;
|
||||
|
||||
MAP_TRIANGLES m_triangles;
|
||||
|
||||
GLuint m_ogl_circle_texture;
|
||||
|
||||
GLuint m_ogl_disp_list_grid; ///< oGL list that stores current grid
|
||||
|
||||
GRID3D_TYPE m_last_grid_type; ///< Stores the last grid computed
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_via;
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_pads_holes;
|
||||
|
||||
MAP_3DMODEL m_3dmodel_map;
|
||||
|
||||
private:
|
||||
void generate_through_outer_holes();
|
||||
void generate_through_inner_holes();
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS *generate_holes_display_list( const LIST_OBJECT2D &aListHolesObject2d,
|
||||
const SHAPE_POLY_SET &aPoly,
|
||||
float aZtop,
|
||||
float aZbot,
|
||||
bool aInvertFaces );
|
||||
|
||||
void add_triangle_top_bot( CLAYER_TRIANGLES *aDst,
|
||||
const SFVEC2F &v0,
|
||||
const SFVEC2F &v1,
|
||||
const SFVEC2F &v2,
|
||||
float top,
|
||||
float bot );
|
||||
|
||||
void add_object_to_triangle_layer( const CRING2D *aRing,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot );
|
||||
|
||||
void add_object_to_triangle_layer( const CPOLYGON4PTS2D *aPoly,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot );
|
||||
|
||||
void add_object_to_triangle_layer( const CFILLEDCIRCLE2D *aFilledCircle,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot );
|
||||
|
||||
void add_object_to_triangle_layer( const CTRIANGLE2D *aTri,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot );
|
||||
|
||||
void add_object_to_triangle_layer( const CROUNDSEGMENT2D *aSeg,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot );
|
||||
|
||||
void render_solder_mask_layer( PCB_LAYER_ID aLayerID,
|
||||
float aZPosition,
|
||||
bool aIsRenderingOnPreviewMode );
|
||||
|
||||
void get_layer_z_pos( PCB_LAYER_ID aLayerID,
|
||||
float &aOutZtop,
|
||||
float &aOutZbot ) const;
|
||||
|
||||
void generate_ring_contour( const SFVEC2F &aCenter,
|
||||
float aInnerRadius,
|
||||
float aOuterRadius,
|
||||
unsigned int aNr_sides_per_circle,
|
||||
std::vector< SFVEC2F > &aInnerContourResult,
|
||||
std::vector< SFVEC2F > &aOuterContourResult,
|
||||
bool aInvertOrder );
|
||||
|
||||
void generate_cylinder( const SFVEC2F &aCenter,
|
||||
float aInnerRadius,
|
||||
float aOuterRadius,
|
||||
float aZtop,
|
||||
float aZbot,
|
||||
unsigned int aNr_sides_per_circle,
|
||||
CLAYER_TRIANGLES *aDstLayer );
|
||||
|
||||
void generate_3D_Vias_and_Pads();
|
||||
|
||||
void load_3D_models( REPORTER *aStatusTextReporter );
|
||||
|
||||
/**
|
||||
* @brief render_3D_models
|
||||
* @param aRenderTopOrBot - true will render Top, false will render bottom
|
||||
* @param aRenderTransparentOnly - true will render only the transparent
|
||||
* objects, false will render opaque
|
||||
*/
|
||||
void render_3D_models( bool aRenderTopOrBot, bool aRenderTransparentOnly );
|
||||
|
||||
void render_3D_module( const MODULE* module, bool aRenderTransparentOnly );
|
||||
|
||||
void setLight_Front( bool enabled );
|
||||
void setLight_Top( bool enabled );
|
||||
void setLight_Bottom( bool enabled );
|
||||
|
||||
void render_3D_arrows();
|
||||
|
||||
void generate_new_3DGrid( GRID3D_TYPE aGridType );
|
||||
|
||||
// Materials
|
||||
void setupMaterials();
|
||||
|
||||
struct
|
||||
{
|
||||
SMATERIAL m_Paste;
|
||||
SMATERIAL m_SilkS;
|
||||
SMATERIAL m_SolderMask;
|
||||
SMATERIAL m_EpoxyBoard;
|
||||
SMATERIAL m_Copper;
|
||||
SMATERIAL m_Plastic;
|
||||
SMATERIAL m_GrayMaterial;
|
||||
}m_materials;
|
||||
|
||||
void set_layer_material( PCB_LAYER_ID aLayerID );
|
||||
SFVEC3F get_layer_color( PCB_LAYER_ID aLayerID );
|
||||
|
||||
public:
|
||||
const MAP_OGL_DISP_LISTS &GetLayerDispListMap() const { return m_ogl_disp_lists_layers; }
|
||||
const CLAYERS_OGL_DISP_LISTS *GetLayerDispList( PCB_LAYER_ID aLayerId ) const { return m_ogl_disp_lists_layers.at( aLayerId ); }
|
||||
const CLAYERS_OGL_DISP_LISTS *GetBoardDispList() const { return m_ogl_disp_list_board; }
|
||||
};
|
||||
|
||||
#endif // C3D_RENDER_OGL_LEGACY_H_
|
||||
|
||||
@@ -1,383 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c_ogl_3dmodel.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "c_ogl_3dmodel.h"
|
||||
#include "ogl_legacy_utils.h"
|
||||
#include "../common_ogl/ogl_utils.h"
|
||||
#include "../3d_math.h"
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
||||
C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel,
|
||||
MATERIAL_MODE aMaterialMode )
|
||||
{
|
||||
m_ogl_idx_list_meshes = 0;
|
||||
m_ogl_idx_list_opaque = 0;
|
||||
m_ogl_idx_list_transparent = 0;
|
||||
m_nr_meshes = 0;
|
||||
m_meshs_bbox = NULL;
|
||||
|
||||
// Validate a3DModel pointers
|
||||
wxASSERT( a3DModel.m_Materials != NULL );
|
||||
wxASSERT( a3DModel.m_Meshes != NULL );
|
||||
wxASSERT( a3DModel.m_MaterialsSize > 0 );
|
||||
wxASSERT( a3DModel.m_MeshesSize > 0 );
|
||||
|
||||
if( (a3DModel.m_Materials != NULL) && (a3DModel.m_Meshes != NULL) &&
|
||||
(a3DModel.m_MaterialsSize > 0) && (a3DModel.m_MeshesSize > 0) )
|
||||
{
|
||||
m_nr_meshes = a3DModel.m_MeshesSize;
|
||||
|
||||
m_meshs_bbox = new CBBOX[a3DModel.m_MeshesSize];
|
||||
|
||||
// Generate m_MeshesSize auxiliar lists to render the meshes
|
||||
m_ogl_idx_list_meshes = glGenLists( a3DModel.m_MeshesSize );
|
||||
|
||||
// Render each mesh of the model
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||
{
|
||||
if( glIsList( m_ogl_idx_list_meshes + mesh_i ) )
|
||||
{
|
||||
const SMESH &mesh = a3DModel.m_Meshes[mesh_i];
|
||||
|
||||
// Validate the mesh pointers
|
||||
wxASSERT( mesh.m_Positions != NULL );
|
||||
wxASSERT( mesh.m_FaceIdx != NULL );
|
||||
wxASSERT( mesh.m_Normals != NULL );
|
||||
|
||||
if( (mesh.m_Positions != NULL) &&
|
||||
(mesh.m_Normals != NULL) &&
|
||||
(mesh.m_FaceIdx != NULL) &&
|
||||
(mesh.m_FaceIdxSize > 0) && (mesh.m_VertexSize > 0) )
|
||||
{
|
||||
SFVEC4F *pColorRGBA = NULL;
|
||||
|
||||
// Create the bbox for this mesh
|
||||
// /////////////////////////////////////////////////////////
|
||||
m_meshs_bbox[mesh_i].Reset();
|
||||
|
||||
for( unsigned int vertex_i = 0;
|
||||
vertex_i < mesh.m_VertexSize;
|
||||
++vertex_i )
|
||||
{
|
||||
m_meshs_bbox[mesh_i].Union( mesh.m_Positions[vertex_i] );
|
||||
}
|
||||
|
||||
// Make sure we start with client state disabled
|
||||
// /////////////////////////////////////////////////////////
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
|
||||
|
||||
// Enable arrays client states
|
||||
// /////////////////////////////////////////////////////////
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_NORMAL_ARRAY );
|
||||
|
||||
glVertexPointer( 3, GL_FLOAT, 0, mesh.m_Positions );
|
||||
glNormalPointer( GL_FLOAT, 0, mesh.m_Normals );
|
||||
|
||||
if( mesh.m_Color != NULL )
|
||||
{
|
||||
glEnableClientState( GL_COLOR_ARRAY );
|
||||
|
||||
float transparency = 0.0f;
|
||||
|
||||
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||
transparency = a3DModel.m_Materials[mesh.m_MaterialIdx].m_Transparency;
|
||||
|
||||
if( (transparency > FLT_EPSILON) &&
|
||||
(aMaterialMode == MATERIAL_MODE_NORMAL) )
|
||||
{
|
||||
// Create a new array of RGBA colors
|
||||
pColorRGBA = new SFVEC4F[mesh.m_VertexSize];
|
||||
|
||||
// Copy RGB array and add the Alpha value
|
||||
for( unsigned int i = 0; i < mesh.m_VertexSize; ++i )
|
||||
pColorRGBA[i] = SFVEC4F( mesh.m_Color[i],
|
||||
1.0f - transparency );
|
||||
|
||||
// Load an RGBA array
|
||||
glColorPointer( 4, GL_FLOAT, 0, pColorRGBA );
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( aMaterialMode )
|
||||
{
|
||||
case MATERIAL_MODE_NORMAL:
|
||||
case MATERIAL_MODE_DIFFUSE_ONLY:
|
||||
// load the original RGB color array
|
||||
glColorPointer( 3, GL_FLOAT, 0, mesh.m_Color );
|
||||
break;
|
||||
case MATERIAL_MODE_CAD_MODE:
|
||||
// Create a new array of RGBA colors
|
||||
pColorRGBA = new SFVEC4F[mesh.m_VertexSize];
|
||||
|
||||
// Copy RGB array and add the Alpha value
|
||||
for( unsigned int i = 0; i < mesh.m_VertexSize; ++i )
|
||||
{
|
||||
pColorRGBA[i] =
|
||||
SFVEC4F( MaterialDiffuseToColorCAD( mesh.m_Color[i] ),
|
||||
1.0f );
|
||||
}
|
||||
|
||||
// Load an RGBA array
|
||||
glColorPointer( 4, GL_FLOAT, 0, pColorRGBA );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( mesh.m_Texcoords != NULL )
|
||||
{
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glTexCoordPointer( 2, GL_FLOAT, 0, mesh.m_Texcoords );
|
||||
}
|
||||
|
||||
// Compile the display list to store triangles
|
||||
// /////////////////////////////////////////////////////////
|
||||
glNewList( m_ogl_idx_list_meshes + mesh_i, GL_COMPILE );
|
||||
|
||||
// Set material properties
|
||||
// /////////////////////////////////////////////////////////
|
||||
|
||||
if( mesh.m_Color != NULL )
|
||||
{
|
||||
// This enables the use of the Color Pointer information
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
}
|
||||
|
||||
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||
{
|
||||
switch( aMaterialMode )
|
||||
{
|
||||
case MATERIAL_MODE_NORMAL:
|
||||
OGL_SetMaterial( a3DModel.m_Materials[mesh.m_MaterialIdx] );
|
||||
break;
|
||||
case MATERIAL_MODE_DIFFUSE_ONLY:
|
||||
OGL_SetDiffuseOnlyMaterial(
|
||||
a3DModel.m_Materials[mesh.m_MaterialIdx].m_Diffuse );
|
||||
break;
|
||||
case MATERIAL_MODE_CAD_MODE:
|
||||
OGL_SetDiffuseOnlyMaterial(
|
||||
MaterialDiffuseToColorCAD(
|
||||
a3DModel.m_Materials[mesh.m_MaterialIdx].m_Diffuse ) );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw mesh
|
||||
// /////////////////////////////////////////////////////////
|
||||
glDrawElements( GL_TRIANGLES, mesh.m_FaceIdxSize,
|
||||
GL_UNSIGNED_INT, mesh.m_FaceIdx );
|
||||
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
|
||||
glEndList();
|
||||
|
||||
// Disable arrays client states
|
||||
// /////////////////////////////////////////////////////////
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glDisableClientState( GL_NORMAL_ARRAY );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
glFlush();
|
||||
|
||||
delete [] pColorRGBA;
|
||||
}
|
||||
}
|
||||
}// for each mesh
|
||||
|
||||
|
||||
m_ogl_idx_list_opaque = glGenLists( 1 );
|
||||
|
||||
// Check if the generated list is valid
|
||||
if( glIsList( m_ogl_idx_list_opaque ) )
|
||||
{
|
||||
bool have_opaque_meshes = false;
|
||||
bool have_transparent_meshes = false;
|
||||
|
||||
// Compile the model display list
|
||||
glNewList( m_ogl_idx_list_opaque, GL_COMPILE );
|
||||
|
||||
// Render each mesh display list (opaque first)
|
||||
// /////////////////////////////////////////////////////////////////
|
||||
for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||
{
|
||||
const SMESH &mesh = a3DModel.m_Meshes[mesh_i];
|
||||
|
||||
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||
{
|
||||
const SMATERIAL &material = a3DModel.m_Materials[mesh.m_MaterialIdx];
|
||||
|
||||
if( material.m_Transparency == 0.0f )
|
||||
{
|
||||
have_opaque_meshes = true; // Flag that we have at least one opaque mesh
|
||||
glCallList( m_ogl_idx_list_meshes + mesh_i );
|
||||
}
|
||||
else
|
||||
{
|
||||
have_transparent_meshes = true; // Flag that we found a transparent mesh
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glEndList();
|
||||
|
||||
if( !have_opaque_meshes )
|
||||
{
|
||||
// If we dont have opaque meshes, we can free the list
|
||||
glDeleteLists( m_ogl_idx_list_opaque, 1 );
|
||||
m_ogl_idx_list_opaque = 0;
|
||||
}
|
||||
|
||||
if( have_transparent_meshes )
|
||||
{
|
||||
m_ogl_idx_list_transparent = glGenLists( 1 );
|
||||
|
||||
// Check if the generated list is valid
|
||||
if( glIsList( m_ogl_idx_list_transparent ) )
|
||||
{
|
||||
// Compile the model display list
|
||||
glNewList( m_ogl_idx_list_transparent, GL_COMPILE );
|
||||
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
// Render each mesh display list
|
||||
// /////////////////////////////////////////////////////////
|
||||
for( unsigned mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||
{
|
||||
const SMESH &mesh = a3DModel.m_Meshes[mesh_i];
|
||||
|
||||
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||
{
|
||||
const SMATERIAL &material = a3DModel.m_Materials[mesh.m_MaterialIdx];
|
||||
|
||||
// Render the transparent mesh if it have a transparency value
|
||||
if( material.m_Transparency != 0.0f )
|
||||
glCallList( m_ogl_idx_list_meshes + mesh_i );
|
||||
}
|
||||
}
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
|
||||
glEndList();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ogl_idx_list_transparent = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ogl_idx_list_opaque = 0;
|
||||
}
|
||||
|
||||
// Create the main bbox
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
m_model_bbox.Reset();
|
||||
|
||||
for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||
m_model_bbox.Union( m_meshs_bbox[mesh_i] );
|
||||
|
||||
glFlush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C_OGL_3DMODEL::Draw_opaque() const
|
||||
{
|
||||
if( glIsList( m_ogl_idx_list_opaque ) )
|
||||
glCallList( m_ogl_idx_list_opaque );
|
||||
}
|
||||
|
||||
|
||||
void C_OGL_3DMODEL::Draw_transparent() const
|
||||
{
|
||||
if( glIsList( m_ogl_idx_list_transparent ) )
|
||||
glCallList( m_ogl_idx_list_transparent );
|
||||
}
|
||||
|
||||
|
||||
C_OGL_3DMODEL::~C_OGL_3DMODEL()
|
||||
{
|
||||
if( glIsList( m_ogl_idx_list_opaque ) )
|
||||
glDeleteLists( m_ogl_idx_list_opaque, 1 );
|
||||
|
||||
if( glIsList( m_ogl_idx_list_transparent ) )
|
||||
glDeleteLists( m_ogl_idx_list_transparent, 1 );
|
||||
|
||||
if( glIsList( m_ogl_idx_list_meshes ) )
|
||||
glDeleteLists( m_ogl_idx_list_meshes, m_nr_meshes );
|
||||
|
||||
m_ogl_idx_list_meshes = 0;
|
||||
m_ogl_idx_list_opaque = 0;
|
||||
m_ogl_idx_list_transparent = 0;
|
||||
|
||||
delete[] m_meshs_bbox;
|
||||
m_meshs_bbox = NULL;
|
||||
}
|
||||
|
||||
|
||||
void C_OGL_3DMODEL::Draw_bbox() const
|
||||
{
|
||||
OGL_draw_bbox( m_model_bbox );
|
||||
}
|
||||
|
||||
|
||||
void C_OGL_3DMODEL::Draw_bboxes() const
|
||||
{
|
||||
for( unsigned int mesh_i = 0; mesh_i < m_nr_meshes; ++mesh_i )
|
||||
OGL_draw_bbox( m_meshs_bbox[mesh_i] );
|
||||
}
|
||||
|
||||
|
||||
bool C_OGL_3DMODEL::Have_opaque() const
|
||||
{
|
||||
return glIsList( m_ogl_idx_list_opaque );
|
||||
}
|
||||
|
||||
|
||||
bool C_OGL_3DMODEL::Have_transparent() const
|
||||
{
|
||||
return glIsList( m_ogl_idx_list_transparent );
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c_ogl_3dmodel.h
|
||||
* @brief implement a legacy 3dmodel render
|
||||
*/
|
||||
|
||||
#ifndef _C_OGL_3DMODEL_H_
|
||||
#define _C_OGL_3DMODEL_H_
|
||||
|
||||
#include <plugins/3dapi/c3dmodel.h>
|
||||
#include "../../common_ogl/openGL_includes.h"
|
||||
#include "../3d_render_raytracing/shapes3D/cbbox.h"
|
||||
#include "../../3d_enums.h"
|
||||
|
||||
///
|
||||
class C_OGL_3DMODEL
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief C_OGL_3DMODEL - Load a 3d model. This must be called inside a gl context
|
||||
* @param a3DModel: a 3d model data to load.
|
||||
* @param aMaterialMode: a mode to render the materials of the model
|
||||
*/
|
||||
C_OGL_3DMODEL( const S3DMODEL &a3DModel, MATERIAL_MODE aMaterialMode );
|
||||
|
||||
~C_OGL_3DMODEL();
|
||||
|
||||
/**
|
||||
* @brief Draw_opaque - render the model into the current context
|
||||
*/
|
||||
void Draw_opaque() const;
|
||||
|
||||
/**
|
||||
* @brief Draw_transparent - render the model into the current context
|
||||
*/
|
||||
void Draw_transparent() const;
|
||||
|
||||
/**
|
||||
* @brief Have_opaque - return true if have opaque meshs to render
|
||||
*/
|
||||
bool Have_opaque() const;
|
||||
|
||||
/**
|
||||
* @brief Have_transparent - return true if have transparent meshs to render
|
||||
*/
|
||||
bool Have_transparent() const;
|
||||
|
||||
/**
|
||||
* @brief Draw_bbox - draw main bounding box of the model
|
||||
*/
|
||||
void Draw_bbox() const;
|
||||
|
||||
/**
|
||||
* @brief Draw_bboxes - draw individual bounding boxes of each mesh
|
||||
*/
|
||||
void Draw_bboxes() const;
|
||||
|
||||
/**
|
||||
* @brief GetBBox - Get main bbox
|
||||
* @return the main model bbox
|
||||
*/
|
||||
const CBBOX &GetBBox() const { return m_model_bbox; }
|
||||
|
||||
private:
|
||||
GLuint m_ogl_idx_list_opaque; ///< display list for rendering opaque meshes
|
||||
GLuint m_ogl_idx_list_transparent; ///< display list for rendering transparent meshes
|
||||
GLuint m_ogl_idx_list_meshes; ///< display lists for all meshes.
|
||||
unsigned int m_nr_meshes; ///< number of meshes of this model
|
||||
|
||||
CBBOX m_model_bbox; ///< global bounding box for this model
|
||||
CBBOX *m_meshs_bbox; ///< individual bbox for each mesh
|
||||
};
|
||||
|
||||
#endif // _C_OGL_3DMODEL_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user