3D Viewer: complete refactor of the 3D viewer.
* Split and rewrite the preview window and canvas. * Create a new class for handling the board information. * Adds new render targets: openGL, legacy, and ray tracing. * Render targets take full advantage of the new 3D plugins system and 3D cache for a fast 3D model loading. * Faster board loading. * New OpenGL render is faster than the old one. * New ray tracing render target with a post processing shader. * Use of new 3D plugins (WRL, X3D, STEP and IGES) and 3D model caching. * Preview of 3D model while browsing the file name. * 3D preview of the footprint while adding / align 3D shapes. * Render of 3D models according to attributes: Normal, Normal+Insert, Virtual. * Pivot rotation centered in one point over the PCB board. * Shortcuts keys improved for XYZ orientation.. * Animated camera.
This commit is contained in:
parent
fd42d76e2f
commit
d8eab321f7
|
@ -1,233 +0,0 @@
|
|||
/*
|
||||
* 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 );
|
||||
}
|
|
@ -224,10 +224,10 @@ SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCach
|
|||
if( mi != m_CacheMap.end() )
|
||||
{
|
||||
wxFileName fname( full3Dpath );
|
||||
bool reload = false;
|
||||
|
||||
if( fname.FileExists() )
|
||||
{
|
||||
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 )
|
||||
|
@ -242,20 +242,20 @@ SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCach
|
|||
reload = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( reload )
|
||||
{
|
||||
if( NULL != mi->second->sceneData )
|
||||
if( reload )
|
||||
{
|
||||
S3D::DestroyNode( mi->second->sceneData );
|
||||
mi->second->sceneData = NULL;
|
||||
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 != mi->second->renderData )
|
||||
S3D::Destroy3DModel( &mi->second->renderData );
|
||||
|
||||
mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath, mi->second->pluginInfo );
|
||||
}
|
||||
|
||||
if( NULL != aCachePtr )
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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@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.
|
||||
|
@ -39,14 +39,10 @@
|
|||
|
||||
struct S3D_INFO
|
||||
{
|
||||
SGPOINT scale; ///< scaling factors for the 3D footprint shape
|
||||
SGPOINT rotation; ///< an X,Y,Z rotation (unit = degrees) for the 3D shape
|
||||
SGPOINT offset; ///< an offset (unit = inch) for the 3D shape
|
||||
// note: the models are treated in a peculiar fashion since it is the
|
||||
// SCALE which is applied first, followed by the ROTATION and finally
|
||||
// the TRANSLATION/Offset (S-R-T). The usual order of operations is T-R-S.
|
||||
|
||||
wxString filename; ///< The 3D shape filename in 3D library
|
||||
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,6 +1,7 @@
|
|||
/*
|
||||
* 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>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -27,8 +28,9 @@
|
|||
#include "project.h"
|
||||
#include "3d_cache/3d_info.h"
|
||||
#include "3d_cache/3d_cache.h"
|
||||
#include "3d_cache/dialogs/panel_prev_model.h"
|
||||
#include "3d_cache_dialogs.h"
|
||||
#include <3d_model_viewer/c3d_model_viewer.h>
|
||||
#include <common_ogl/cogl_att_list.h>
|
||||
|
||||
#define ID_FILE_TREE ( wxID_LAST + 1 )
|
||||
#define ID_SET_DIR ( ID_FILE_TREE + 1 )
|
||||
|
@ -60,15 +62,13 @@ DLG_SELECT_3DMODEL::DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheMana
|
|||
|
||||
wxBoxSizer* bSizer0 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bSizer1;
|
||||
bSizer1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* bSizer1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxBoxSizer* bSizer2;
|
||||
bSizer2 = new wxBoxSizer( wxVERTICAL );
|
||||
wxBoxSizer* bSizer2 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
// set to NULL to avoid segfaults when m_FileTree is instantiated
|
||||
// and wxGenericDirCtrl events are posted
|
||||
m_preview = NULL;
|
||||
m_modelViewer = NULL;
|
||||
dirChoices = NULL;
|
||||
|
||||
m_FileTree = new wxGenericDirCtrl( this, ID_FILE_TREE, prevModelSelectDir, wxDefaultPosition,
|
||||
|
@ -83,14 +83,12 @@ DLG_SELECT_3DMODEL::DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheMana
|
|||
bSizer2->Add( m_FileTree, 1, wxEXPAND | wxALL, 5 );
|
||||
bSizer1->Add( bSizer2, 1, wxEXPAND, 5 );
|
||||
|
||||
// m_preview must me instantiated after m_FileTree or else it will not
|
||||
// function as desired due to the constructor depending on the existence
|
||||
// of m_FileTree to determine the previewer's configuration
|
||||
wxBoxSizer* previewSizer;
|
||||
previewSizer = new wxBoxSizer( wxVERTICAL );
|
||||
m_preview = new PANEL_PREV_3D( this, m_cache );
|
||||
previewSizer->Add( m_preview, 1, wxEXPAND | wxALL, 5 );
|
||||
bSizer1->Add( previewSizer, 0, wxEXPAND, 5 );
|
||||
m_modelViewer = new C3D_MODEL_VIEWER( this,
|
||||
COGL_ATT_LIST::GetAttributesList( true ),
|
||||
m_cache );
|
||||
m_modelViewer->SetMinSize( wxSize( 512, 384 ) );
|
||||
|
||||
bSizer1->Add( m_modelViewer, 0, wxCENTER, 5 );
|
||||
|
||||
// create the filter list
|
||||
if( NULL != m_cache )
|
||||
|
@ -133,8 +131,7 @@ DLG_SELECT_3DMODEL::DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheMana
|
|||
|
||||
// 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 = new wxChoice( this, ID_SET_DIR, wxDefaultPosition, wxSize( 320, 20 ) );
|
||||
dirChoices->SetMinSize( wxSize( 320, 12 ) );
|
||||
|
||||
wxStaticText* stDirChoice = new wxStaticText( this, -1, _( "Paths:" ) );
|
||||
|
@ -150,6 +147,7 @@ DLG_SELECT_3DMODEL::DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheMana
|
|||
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 );
|
||||
|
@ -159,6 +157,9 @@ DLG_SELECT_3DMODEL::DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheMana
|
|||
this->SetSizerAndFit( bSizer0 );
|
||||
this->Layout();
|
||||
this->Centre( wxBOTH );
|
||||
|
||||
m_modelViewer->Refresh();
|
||||
m_modelViewer->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
|
@ -167,26 +168,30 @@ bool DLG_SELECT_3DMODEL::TransferDataFromWindow()
|
|||
if( NULL == m_model || NULL == m_FileTree )
|
||||
return true;
|
||||
|
||||
m_model->scale.x = 1.0;
|
||||
m_model->scale.y = 1.0;
|
||||
m_model->scale.z = 1.0;
|
||||
m_model->m_Scale.x = 1.0;
|
||||
m_model->m_Scale.y = 1.0;
|
||||
m_model->m_Scale.z = 1.0;
|
||||
|
||||
m_model->rotation.x = 0.0;
|
||||
m_model->rotation.y = 0.0;
|
||||
m_model->rotation.z = 0.0;
|
||||
m_model->m_Rotation.x = 0.0;
|
||||
m_model->m_Rotation.y = 0.0;
|
||||
m_model->m_Rotation.z = 0.0;
|
||||
|
||||
m_model->offset = m_model->rotation;
|
||||
m_model->filename.clear();
|
||||
m_model->m_Offset = m_model->m_Rotation;
|
||||
m_model->m_Filename.clear();
|
||||
|
||||
wxString fname = m_FileTree->GetFilePath();
|
||||
wxString name = m_FileTree->GetFilePath();
|
||||
|
||||
if( fname.empty() )
|
||||
if( name.empty() )
|
||||
return true;
|
||||
|
||||
m_previousDir = m_FileTree->GetPath();
|
||||
m_previousFilterIndex = m_FileTree->GetFilterIndex();
|
||||
|
||||
m_preview->GetModelData( m_model );
|
||||
// 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;
|
||||
}
|
||||
|
@ -194,8 +199,8 @@ bool DLG_SELECT_3DMODEL::TransferDataFromWindow()
|
|||
|
||||
void DLG_SELECT_3DMODEL::OnSelectionChanged( wxTreeEvent& event )
|
||||
{
|
||||
if( NULL != m_preview )
|
||||
m_preview->UpdateModelName( m_FileTree->GetFilePath() );
|
||||
if( m_modelViewer )
|
||||
m_modelViewer->Set3DModel( m_FileTree->GetFilePath() );
|
||||
|
||||
event.Skip();
|
||||
return;
|
||||
|
@ -204,8 +209,8 @@ void DLG_SELECT_3DMODEL::OnSelectionChanged( wxTreeEvent& event )
|
|||
|
||||
void DLG_SELECT_3DMODEL::OnFileActivated( wxTreeEvent& event )
|
||||
{
|
||||
if( NULL != m_preview )
|
||||
m_preview->UpdateModelName( m_FileTree->GetFilePath() );
|
||||
if( m_modelViewer )
|
||||
m_modelViewer->Set3DModel( m_FileTree->GetFilePath() );
|
||||
|
||||
event.Skip();
|
||||
SetEscapeId( wxID_OK );
|
||||
|
@ -217,10 +222,8 @@ void DLG_SELECT_3DMODEL::OnFileActivated( wxTreeEvent& event )
|
|||
|
||||
void DLG_SELECT_3DMODEL::SetRootDir( wxCommandEvent& event )
|
||||
{
|
||||
if( !m_FileTree )
|
||||
return;
|
||||
|
||||
m_FileTree->SetPath( dirChoices->GetString( dirChoices->GetSelection() ) );
|
||||
if( m_FileTree )
|
||||
m_FileTree->SetPath( dirChoices->GetString( dirChoices->GetSelection() ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
struct S3D_INFO;
|
||||
class S3D_CACHE;
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
class PANEL_PREV_3D;
|
||||
class C3D_MODEL_VIEWER;
|
||||
//class wxGenericDirCtrl;
|
||||
|
||||
class DLG_SELECT_3DMODEL : public wxDialog
|
||||
|
@ -55,7 +55,7 @@ private:
|
|||
int& m_previousFilterIndex;
|
||||
|
||||
wxGenericDirCtrl* m_FileTree;
|
||||
PANEL_PREV_3D* m_preview;
|
||||
C3D_MODEL_VIEWER* m_modelViewer;
|
||||
wxChoice* dirChoices;
|
||||
|
||||
void updateDirChoiceList( void );
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* 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>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -21,29 +22,26 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <3d_model_viewer/c3d_model_viewer.h>
|
||||
#include <3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h>
|
||||
/**
|
||||
* @file panel_prev_model.cpp
|
||||
*/
|
||||
|
||||
#include <3d_canvas/eda_3d_canvas.h>
|
||||
#include <common_ogl/cogl_att_list.h>
|
||||
#include <cstdlib>
|
||||
#include <wx/log.h>
|
||||
#include <wx/sizer.h>
|
||||
|
||||
#include <wx/valnum.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/glcanvas.h>
|
||||
#include <wx/dirctrl.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/ext.hpp>
|
||||
#include <wx/tglbtn.h>
|
||||
|
||||
#include "project.h"
|
||||
#include "3d_cache.h"
|
||||
#include "3d_info.h"
|
||||
#include "3d_filename_resolver.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
#include "panel_prev_model.h"
|
||||
#include <class_board.h>
|
||||
|
||||
|
||||
// ensure -360 < rotation < 360
|
||||
/**
|
||||
* @brief checkRotation - ensure -360 < rotation < 360
|
||||
* @param rot: in out parameter
|
||||
*/
|
||||
static void checkRotation( double& rot )
|
||||
{
|
||||
if( rot >= 360.0 )
|
||||
|
@ -62,7 +60,7 @@ static void checkRotation( double& rot )
|
|||
|
||||
|
||||
enum {
|
||||
ID_SCALEX = wxID_LAST + 1,
|
||||
ID_SCALEX = ID_KICAD_PANEL_PREV_MODEL_START,
|
||||
ID_SCALEY,
|
||||
ID_SCALEZ,
|
||||
ID_ROTX,
|
||||
|
@ -78,20 +76,23 @@ enum {
|
|||
ID_3D_FRONT,
|
||||
ID_3D_BACK,
|
||||
ID_3D_TOP,
|
||||
ID_3D_BOTTOM
|
||||
ID_3D_BOTTOM,
|
||||
ID_3D_END = ID_KICAD_PANEL_PREV_MODEL_END
|
||||
};
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE( PANEL_PREV_3D, wxPanel)
|
||||
EVT_TEXT_ENTER( ID_SCALEX, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT_ENTER( ID_SCALEY, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT_ENTER( ID_SCALEZ, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT_ENTER( ID_ROTX, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT_ENTER( ID_ROTY, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT_ENTER( ID_ROTZ, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT_ENTER( ID_OFFX, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT_ENTER( ID_OFFY, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT_ENTER( ID_OFFZ, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_BUTTON( ID_3D_ISO, PANEL_PREV_3D::View3DISO )
|
||||
EVT_TEXT( ID_SCALEX, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT( ID_SCALEY, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT( ID_SCALEZ, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT( ID_ROTX, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT( ID_ROTY, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT( ID_ROTZ, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT( ID_OFFX, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT( ID_OFFY, PANEL_PREV_3D::updateOrientation )
|
||||
EVT_TEXT( ID_OFFZ, PANEL_PREV_3D::updateOrientation )
|
||||
|
||||
EVT_TOGGLEBUTTON( ID_3D_ISO, PANEL_PREV_3D::View3DISO )
|
||||
EVT_BUTTON( ID_3D_UPDATE, PANEL_PREV_3D::View3DUpdate )
|
||||
EVT_BUTTON( ID_3D_LEFT, PANEL_PREV_3D::View3DLeft )
|
||||
EVT_BUTTON( ID_3D_RIGHT, PANEL_PREV_3D::View3DRight )
|
||||
|
@ -99,19 +100,24 @@ wxBEGIN_EVENT_TABLE( PANEL_PREV_3D, wxPanel)
|
|||
EVT_BUTTON( ID_3D_BACK, PANEL_PREV_3D::View3DBack )
|
||||
EVT_BUTTON( ID_3D_TOP, PANEL_PREV_3D::View3DTop )
|
||||
EVT_BUTTON( ID_3D_BOTTOM, PANEL_PREV_3D::View3DBottom )
|
||||
EVT_CLOSE( PANEL_PREV_3D::OnCloseWindow )
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, S3D_CACHE* aCacheManager ) :
|
||||
wxPanel( aParent, -1 ), m_ModelManager( aCacheManager )
|
||||
PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent,
|
||||
S3D_CACHE* aCacheManager,
|
||||
MODULE* aModuleCopy,
|
||||
std::vector<S3D_INFO> *aParentInfoList ) :
|
||||
wxPanel( aParent, -1 )
|
||||
{
|
||||
if( NULL != m_ModelManager )
|
||||
m_resolver = m_ModelManager->GetResolver();
|
||||
if( NULL != aCacheManager )
|
||||
m_resolver = aCacheManager->GetResolver();
|
||||
else
|
||||
m_resolver = NULL;
|
||||
|
||||
canvas = NULL;
|
||||
model = NULL;
|
||||
m_currentSelectedIdx = -1;
|
||||
m_parentInfoList = aParentInfoList;
|
||||
m_previewPane = NULL;
|
||||
xscale = NULL;
|
||||
yscale = NULL;
|
||||
zscale = NULL;
|
||||
|
@ -121,54 +127,55 @@ PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, S3D_CACHE* aCacheManager ) :
|
|||
xoff = NULL;
|
||||
yoff = NULL;
|
||||
zoff = NULL;
|
||||
currentModelFile.clear();
|
||||
|
||||
wxBoxSizer* mainBox = new wxBoxSizer( wxVERTICAL );
|
||||
wxStaticBoxSizer* vbox = new wxStaticBoxSizer( wxVERTICAL, this, _( "3D Preview" ) );
|
||||
m_FileTree = NULL;
|
||||
|
||||
if( NULL != aParent )
|
||||
m_FileTree = (wxGenericDirCtrl*)
|
||||
aParent->FindWindowByLabel( wxT( "3D_MODEL_SELECTOR" ), aParent );
|
||||
|
||||
wxFloatingPointValidator< float > valScale( 4 );
|
||||
valScale.SetRange( 0.0001, 9999.0 );
|
||||
valScale.SetRange( 0.0001f, 9999.0f );
|
||||
wxFloatingPointValidator< float > valRotate( 2 );
|
||||
valRotate.SetRange( -180.0, 180.0 );
|
||||
valRotate.SetRange( -180.0f, 180.0f );
|
||||
wxFloatingPointValidator< float > valOffset( 4 );
|
||||
valOffset.SetRange( -9999.0, 9999.0 );
|
||||
valOffset.SetRange( -9999.0f, 9999.0f );
|
||||
|
||||
wxStaticBoxSizer* vbScale = new wxStaticBoxSizer( wxVERTICAL, this, _( "Scale" ) );
|
||||
wxStaticBoxSizer* vbRotate = new wxStaticBoxSizer( wxVERTICAL, this, _( "Rotation" ) );
|
||||
wxStaticBoxSizer* vbOffset = new wxStaticBoxSizer( wxVERTICAL, this, _( "Offset (inches)" ) );
|
||||
wxStaticBoxSizer* vbScale = new wxStaticBoxSizer( wxVERTICAL, this, _( "Scale" ) );
|
||||
wxStaticBoxSizer* vbRotate = new wxStaticBoxSizer( wxVERTICAL, this, _( "Rotation (degrees)" ) );
|
||||
|
||||
wxStaticBox* modScale = vbScale->GetStaticBox();
|
||||
const wxString offsetString = _( "Offset " ) + "(" + GetUnitsLabel( g_UserUnit ) + ")";
|
||||
wxStaticBoxSizer* vbOffset = new wxStaticBoxSizer( wxVERTICAL, this, offsetString );
|
||||
|
||||
wxStaticBox* modScale = vbScale->GetStaticBox();
|
||||
wxStaticBox* modRotate = vbRotate->GetStaticBox();
|
||||
wxStaticBox* modOffset = vbOffset->GetStaticBox();
|
||||
|
||||
wxBoxSizer* hbS1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hbS2 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hbS3 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxStaticText* txtS1 = new wxStaticText( modScale, -1, wxT( "X:" ) );
|
||||
wxStaticText* txtS2 = new wxStaticText( modScale, -1, wxT( "Y:" ) );
|
||||
wxStaticText* txtS3 = new wxStaticText( modScale, -1, wxT( "Z:" ) );
|
||||
|
||||
xscale = new wxTextCtrl( modScale, ID_SCALEX, "1.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER, valScale );
|
||||
yscale = new wxTextCtrl( modScale, ID_SCALEY, "1.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER, valScale );
|
||||
zscale = new wxTextCtrl( modScale, ID_SCALEZ, "1.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER, valScale );
|
||||
|
||||
xscale->SetMaxLength( 9 );
|
||||
yscale->SetMaxLength( 9 );
|
||||
zscale->SetMaxLength( 9 );
|
||||
hbS1->Add( txtS1, 0, wxALL, 2 );
|
||||
hbS1->Add( xscale, 0, wxALL, 2 );
|
||||
hbS2->Add( txtS2, 0, wxALL, 2 );
|
||||
hbS2->Add( yscale, 0, wxALL, 2 );
|
||||
hbS3->Add( txtS3, 0, wxALL, 2 );
|
||||
hbS3->Add( zscale, 0, wxALL, 2 );
|
||||
vbScale->Add( hbS1, 0, wxEXPAND | wxALL, 0 );
|
||||
vbScale->Add( hbS2, 0, wxEXPAND | wxALL, 0 );
|
||||
vbScale->Add( hbS3, 0, wxEXPAND | wxALL, 0 );
|
||||
hbS1->Add( txtS1, 0, wxALIGN_CENTER, 2 );
|
||||
hbS1->Add( xscale, 0, wxEXPAND | wxLEFT | wxRIGHT, 2 );
|
||||
hbS2->Add( txtS2, 0, wxALIGN_CENTER, 2 );
|
||||
hbS2->Add( yscale, 0, wxEXPAND | wxLEFT | wxRIGHT, 2 );
|
||||
hbS3->Add( txtS3, 0, wxALIGN_CENTER, 2 );
|
||||
hbS3->Add( zscale, 0, wxEXPAND | wxLEFT | wxRIGHT, 2 );
|
||||
vbScale->Add( hbS1, 1, wxEXPAND | wxLEFT | wxRIGHT, 6 );
|
||||
vbScale->Add( hbS2, 1, wxEXPAND | wxLEFT | wxRIGHT, 6 );
|
||||
vbScale->Add( hbS3, 1, wxEXPAND | wxLEFT | wxRIGHT, 6 );
|
||||
|
||||
wxBoxSizer* hbR1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hbR2 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
@ -176,24 +183,26 @@ PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, S3D_CACHE* aCacheManager ) :
|
|||
wxStaticText* txtR1 = new wxStaticText( modRotate, -1, wxT( "X:" ) );
|
||||
wxStaticText* txtR2 = new wxStaticText( modRotate, -1, wxT( "Y:" ) );
|
||||
wxStaticText* txtR3 = new wxStaticText( modRotate, -1, wxT( "Z:" ) );
|
||||
|
||||
xrot = new wxTextCtrl( modRotate, ID_ROTX, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER, valRotate );
|
||||
wxTE_PROCESS_ENTER, valRotate );
|
||||
yrot = new wxTextCtrl( modRotate, ID_ROTY, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER, valRotate );
|
||||
wxTE_PROCESS_ENTER, valRotate );
|
||||
zrot = new wxTextCtrl( modRotate, ID_ROTZ, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER, valRotate );
|
||||
wxTE_PROCESS_ENTER, valRotate );
|
||||
|
||||
xrot->SetMaxLength( 9 );
|
||||
yrot->SetMaxLength( 9 );
|
||||
zrot->SetMaxLength( 9 );
|
||||
hbR1->Add( txtR1, 0, wxALL, 2 );
|
||||
hbR1->Add( xrot, 0, wxALL, 2 );
|
||||
hbR2->Add( txtR2, 0, wxALL, 2 );
|
||||
hbR2->Add( yrot, 0, wxALL, 2 );
|
||||
hbR3->Add( txtR3, 0, wxALL, 2 );
|
||||
hbR3->Add( zrot, 0, wxALL, 2 );
|
||||
vbRotate->Add( hbR1, 0, wxEXPAND | wxALL, 0 );
|
||||
vbRotate->Add( hbR2, 0, wxEXPAND | wxALL, 0 );
|
||||
vbRotate->Add( hbR3, 0, wxEXPAND | wxALL, 0 );
|
||||
hbR1->Add( txtR1, 1, wxALIGN_CENTER, 2 );
|
||||
hbR1->Add( xrot, 0, wxEXPAND | wxLEFT | wxRIGHT, 2 );
|
||||
hbR2->Add( txtR2, 1, wxALIGN_CENTER, 2 );
|
||||
hbR2->Add( yrot, 0, wxEXPAND | wxLEFT | wxRIGHT, 2 );
|
||||
hbR3->Add( txtR3, 1, wxALIGN_CENTER, 2 );
|
||||
hbR3->Add( zrot, 0, wxEXPAND | wxLEFT | wxRIGHT, 2 );
|
||||
vbRotate->Add( hbR1, 1, wxEXPAND | wxLEFT | wxRIGHT, 6 );
|
||||
vbRotate->Add( hbR2, 1, wxEXPAND | wxLEFT | wxRIGHT, 6 );
|
||||
vbRotate->Add( hbR3, 1, wxEXPAND | wxLEFT | wxRIGHT, 6 );
|
||||
|
||||
wxBoxSizer* hbO1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hbO2 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
@ -201,24 +210,25 @@ PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, S3D_CACHE* aCacheManager ) :
|
|||
wxStaticText* txtO1 = new wxStaticText( modOffset, -1, wxT( "X:" ) );
|
||||
wxStaticText* txtO2 = new wxStaticText( modOffset, -1, wxT( "Y:" ) );
|
||||
wxStaticText* txtO3 = new wxStaticText( modOffset, -1, wxT( "Z:" ) );
|
||||
|
||||
xoff = new wxTextCtrl( modOffset, ID_OFFX, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER, valOffset );
|
||||
wxTE_PROCESS_ENTER, valOffset );
|
||||
yoff = new wxTextCtrl( modOffset, ID_OFFY, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER, valOffset );
|
||||
wxTE_PROCESS_ENTER, valOffset );
|
||||
zoff = new wxTextCtrl( modOffset, ID_OFFZ, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER, valOffset );
|
||||
wxTE_PROCESS_ENTER, valOffset );
|
||||
xoff->SetMaxLength( 10 );
|
||||
yoff->SetMaxLength( 10 );
|
||||
zoff->SetMaxLength( 10 );
|
||||
hbO1->Add( txtO1, 0, wxALL, 2 );
|
||||
hbO1->Add( xoff, 0, wxALL, 2 );
|
||||
hbO2->Add( txtO2, 0, wxALL, 2 );
|
||||
hbO2->Add( yoff, 0, wxALL, 2 );
|
||||
hbO3->Add( txtO3, 0, wxALL, 2 );
|
||||
hbO3->Add( zoff, 0, wxALL, 2 );
|
||||
vbOffset->Add( hbO1, 0, wxEXPAND | wxALL, 0 );
|
||||
vbOffset->Add( hbO2, 0, wxEXPAND | wxALL, 0 );
|
||||
vbOffset->Add( hbO3, 0, wxEXPAND | wxALL, 0 );
|
||||
hbO1->Add( txtO1, 0, wxALIGN_CENTER, 2 );
|
||||
hbO1->Add( xoff, 0, wxEXPAND | wxLEFT | wxRIGHT, 2 );
|
||||
hbO2->Add( txtO2, 0, wxALIGN_CENTER, 2 );
|
||||
hbO2->Add( yoff, 0, wxEXPAND | wxLEFT | wxRIGHT, 2 );
|
||||
hbO3->Add( txtO3, 0, wxALIGN_CENTER, 2 );
|
||||
hbO3->Add( zoff, 0, wxEXPAND | wxLEFT | wxRIGHT, 2 );
|
||||
vbOffset->Add( hbO1, 1, wxEXPAND | wxLEFT | wxRIGHT, 6 );
|
||||
vbOffset->Add( hbO2, 1, wxEXPAND | wxLEFT | wxRIGHT, 6 );
|
||||
vbOffset->Add( hbO3, 1, wxEXPAND | wxLEFT | wxRIGHT, 6 );
|
||||
|
||||
// hbox holding orientation data and preview
|
||||
wxBoxSizer* hbox = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
@ -227,215 +237,290 @@ PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, S3D_CACHE* aCacheManager ) :
|
|||
// vbox holding the preview and view buttons
|
||||
wxBoxSizer* vboxPrev = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
vboxOrient->Add( vbScale, 0, wxEXPAND | wxALL, 1 );
|
||||
vboxOrient->Add( vbRotate, 0, wxEXPAND | wxALL, 1 );
|
||||
vboxOrient->Add( vbOffset, 0, wxEXPAND | wxALL, 1 );
|
||||
vboxOrient->Add( vbScale, 1, wxEXPAND | wxLEFT | wxRIGHT, 2 );
|
||||
vboxOrient->Add( vbRotate, 1, wxEXPAND | wxLEFT | wxRIGHT, 2 );
|
||||
vboxOrient->Add( vbOffset, 1, wxEXPAND | wxLEFT | wxRIGHT, 2 );
|
||||
|
||||
// add preview items
|
||||
preview = new wxPanel( this, -1 );
|
||||
wxPanel*preview = new wxPanel( this, -1 );
|
||||
preview->SetMinSize( wxSize( 400, 250 ) );
|
||||
preview->SetBackgroundColour( wxColor( 0, 0, 0 ));
|
||||
vboxPrev->Add( preview, 1, wxEXPAND | wxLEFT | wxRIGHT, 5 );
|
||||
vboxPrev->Add( preview, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
// buttons:
|
||||
wxButton* vFront = new wxButton( this, ID_3D_FRONT, wxT( "F" ) );
|
||||
wxButton* vBack = new wxButton( this, ID_3D_BACK, wxT( "B" ) );
|
||||
wxButton* vLeft = new wxButton( this, ID_3D_LEFT, wxT( "L" ) );
|
||||
wxButton* vRight = new wxButton( this, ID_3D_RIGHT, wxT( "R" ) );
|
||||
wxButton* vTop = new wxButton( this, ID_3D_TOP, wxT( "T" ) );
|
||||
wxButton* vBottom = new wxButton( this, ID_3D_BOTTOM, wxT( "B" ) );
|
||||
wxButton* vISO = new wxButton( this, ID_3D_ISO, wxT( "I" ) );
|
||||
wxButton* vUpdate = new wxButton( this, ID_3D_UPDATE, wxT( "U" ) );
|
||||
wxBoxSizer* hbBT = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hbBB = new wxBoxSizer( wxHORIZONTAL );
|
||||
hbBT->Add( vISO, 0, wxCENTER | wxALL, 3 );
|
||||
hbBT->Add( vLeft, 0, wxCENTER | wxALL, 3 );
|
||||
hbBT->Add( vFront, 0, wxCENTER | wxALL, 3 );
|
||||
hbBT->Add( vTop, 0, wxCENTER | wxALL, 3 );
|
||||
hbBT->AddSpacer( 17 );
|
||||
hbBB->Add( vUpdate, 0, wxCENTER | wxALL, 3 );
|
||||
hbBB->Add( vRight, 0, wxCENTER | wxALL, 3 );
|
||||
hbBB->Add( vBack, 0, wxCENTER | wxALL, 3 );
|
||||
hbBB->Add( vBottom, 0, wxCENTER | wxALL, 3 );
|
||||
hbBB->AddSpacer( 17 );
|
||||
wxButton* vFront = new wxButton( this, ID_3D_FRONT );
|
||||
vFront->SetBitmap( KiBitmap( axis3d_front_xpm ) );
|
||||
|
||||
wxButton* vBack = new wxButton( this, ID_3D_BACK );
|
||||
vBack->SetBitmap( KiBitmap( axis3d_back_xpm ) );
|
||||
|
||||
wxButton* vLeft = new wxButton( this, ID_3D_LEFT );
|
||||
vLeft->SetBitmap( KiBitmap( axis3d_left_xpm ) );
|
||||
|
||||
wxButton* vRight = new wxButton( this, ID_3D_RIGHT );
|
||||
vRight->SetBitmap( KiBitmap( axis3d_right_xpm ) );
|
||||
|
||||
wxButton* vTop = new wxButton( this, ID_3D_TOP );
|
||||
vTop->SetBitmap( KiBitmap( axis3d_top_xpm ) );
|
||||
|
||||
wxButton* vBottom = new wxButton( this, ID_3D_BOTTOM );
|
||||
vBottom->SetBitmap( KiBitmap( axis3d_bottom_xpm ) );
|
||||
|
||||
wxToggleButton* vISO = new wxToggleButton( this, ID_3D_ISO, wxT("") );
|
||||
vISO->SetBitmap( KiBitmap( ortho_xpm ) );
|
||||
vISO->SetToolTip( _("Change to isometric perspective") );
|
||||
|
||||
wxButton* vUpdate = new wxButton( this, ID_3D_UPDATE );
|
||||
vUpdate->SetBitmap( KiBitmap( reload_xpm ) );
|
||||
vUpdate->SetToolTip( _("Reload board and 3D models") );
|
||||
|
||||
wxGridSizer* gridSizer = new wxGridSizer( 2, 4, 0, 0 );
|
||||
|
||||
gridSizer->Add( vISO, 0, wxEXPAND, 3 );
|
||||
gridSizer->Add( vLeft, 0, wxEXPAND, 3 );
|
||||
gridSizer->Add( vFront, 0, wxEXPAND, 3 );
|
||||
gridSizer->Add( vTop, 0, wxEXPAND, 3 );
|
||||
|
||||
gridSizer->Add( vUpdate, 0, wxEXPAND, 3 );
|
||||
gridSizer->Add( vRight, 0, wxEXPAND, 3 );
|
||||
gridSizer->Add( vBack, 0, wxEXPAND, 3 );
|
||||
gridSizer->Add( vBottom, 0, wxEXPAND, 3 );
|
||||
|
||||
vboxPrev->AddSpacer( 7 );
|
||||
vboxPrev->Add( hbBT, 0 );
|
||||
vboxPrev->Add( hbBB, 0 );
|
||||
vboxPrev->Add( gridSizer, 0, wxCENTER, 0 );
|
||||
|
||||
// XXX - Suppress the buttons until the Renderer code is ready.
|
||||
// vboxPrev->Hide( preview, true );
|
||||
vboxPrev->Hide( hbBT, true );
|
||||
vboxPrev->Hide( hbBB, true );
|
||||
|
||||
hbox->Add( vboxOrient, 0, wxEXPAND | wxALL, 0 );
|
||||
hbox->Add( vboxOrient, 0, 0, 2 );
|
||||
hbox->Add( vboxPrev, 1, wxEXPAND | wxALL, 12 );
|
||||
vbox->Add( hbox, 1, wxEXPAND );
|
||||
vbox->Add( hbox, 1, wxEXPAND | wxALL, 0 );
|
||||
|
||||
mainBox->Add( vbox, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
if( NULL != m_FileTree )
|
||||
{
|
||||
// NOTE: if/when the File Selector preview is implemented
|
||||
// we may need to hide the orientation boxes to ensure the
|
||||
// users have sufficient display area for the browser.
|
||||
// hbox->Hide( vboxOrient, true );
|
||||
// XXX -
|
||||
// NOTE: for now we always suppress the preview and model orientation
|
||||
// panels while in the file selector
|
||||
//mainBox->Hide( vbox, true );
|
||||
|
||||
hbox->Hide( vboxOrient, true );
|
||||
vboxPrev->Hide( hbBT, true );
|
||||
vboxPrev->Hide( hbBB, true );
|
||||
}
|
||||
|
||||
SetSizerAndFit( mainBox );
|
||||
|
||||
return;
|
||||
// Create a dummy board
|
||||
m_dummyBoard = new BOARD();
|
||||
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( preview,
|
||||
COGL_ATT_LIST::GetAttributesList( true ),
|
||||
m_dummyBoard,
|
||||
*m_settings3Dviewer,
|
||||
aCacheManager );
|
||||
|
||||
wxSizer* ws = new wxBoxSizer( wxHORIZONTAL );
|
||||
ws->Add( m_previewPane, 1, wxEXPAND );
|
||||
preview->SetSizer( ws );
|
||||
preview->Layout();
|
||||
ws->FitInside( preview );
|
||||
|
||||
m_previewPane->SetFocus(); // Need to catch mouse and keyboard events
|
||||
}
|
||||
|
||||
|
||||
PANEL_PREV_3D::~PANEL_PREV_3D()
|
||||
{
|
||||
if( NULL != canvas )
|
||||
{
|
||||
canvas->Clear3DModel();
|
||||
canvas->Refresh();
|
||||
canvas->Update();
|
||||
}
|
||||
delete m_settings3Dviewer;
|
||||
m_settings3Dviewer = NULL;
|
||||
|
||||
model = NULL;
|
||||
delete m_dummyBoard;
|
||||
m_dummyBoard = NULL;
|
||||
|
||||
return;
|
||||
delete m_previewPane;
|
||||
m_previewPane = NULL;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::OnCloseWindow( wxCloseEvent &event )
|
||||
{
|
||||
if( m_previewPane )
|
||||
m_previewPane->Close();
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DISO( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
// std::cout << "Switch to Isometric View\n";
|
||||
return;
|
||||
if( m_settings3Dviewer )
|
||||
{
|
||||
m_settings3Dviewer->CameraGet().ToggleProjection();
|
||||
m_previewPane->Refresh();
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DUpdate( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
// std::cout << "Update 3D View\n";
|
||||
|
||||
// update the model filename if appropriate
|
||||
if( NULL != m_FileTree )
|
||||
if( m_previewPane )
|
||||
{
|
||||
wxString modelName = m_FileTree->GetFilePath();
|
||||
UpdateModelName( modelName );
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Refresh();
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DLeft( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
// std::cout << "Switch to Left View\n";
|
||||
return;
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->SetView3D( 'X' );
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DRight( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
// std::cout << "Switch to Right View\n";
|
||||
return;
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->SetView3D( 'x' );
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DFront( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
// std::cout << "Switch to Front View\n";
|
||||
return;
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->SetView3D( 'Y' );
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DBack( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
// std::cout << "Switch to Back View\n";
|
||||
return;
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->SetView3D( 'y' );
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DTop( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
// std::cout << "Switch to Top View\n";
|
||||
return;
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->SetView3D( 'z' );
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DBottom( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
// std::cout << "Switch to Bottom View\n";
|
||||
return;
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->SetView3D( 'Z' );
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::GetModelData( S3D_INFO* aModel )
|
||||
void PANEL_PREV_3D::SetModelDataIdx( int idx, bool aReloadPreviewModule )
|
||||
{
|
||||
if( NULL == aModel )
|
||||
return;
|
||||
wxASSERT( m_parentInfoList != NULL );
|
||||
|
||||
// XXX - due to cross-platform differences in wxWidgets, extracting
|
||||
// scale/rotation/offset only works as expected when the preview
|
||||
// panel is not embedded in a file selector dialog. This conditional
|
||||
// execution should be removed once the cross-platform issues are
|
||||
// fixed.
|
||||
if( NULL == m_FileTree )
|
||||
if( m_parentInfoList && (idx >= 0) )
|
||||
{
|
||||
SGPOINT scale;
|
||||
SGPOINT rotation;
|
||||
SGPOINT offset;
|
||||
wxASSERT( (unsigned int)idx < (*m_parentInfoList).size() );
|
||||
|
||||
getOrientationVars( scale, rotation, offset );
|
||||
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
|
||||
|
||||
aModel->scale = scale;
|
||||
aModel->offset = offset;
|
||||
aModel->rotation = rotation;
|
||||
const S3D_INFO *aModel = (const S3D_INFO *)&((*m_parentInfoList)[idx]);
|
||||
|
||||
xscale->SetValue( wxString::FromDouble( aModel->m_Scale.x ) );
|
||||
yscale->SetValue( wxString::FromDouble( aModel->m_Scale.y ) );
|
||||
zscale->SetValue( wxString::FromDouble( aModel->m_Scale.z ) );
|
||||
|
||||
xrot->SetValue( wxString::FromDouble( aModel->m_Rotation.x ) );
|
||||
yrot->SetValue( wxString::FromDouble( aModel->m_Rotation.y ) );
|
||||
zrot->SetValue( wxString::FromDouble( aModel->m_Rotation.z ) );
|
||||
|
||||
switch( g_UserUnit )
|
||||
{
|
||||
case MILLIMETRES:
|
||||
xoff->SetValue( wxString::FromDouble( aModel->m_Offset.x * 25.4 ) );
|
||||
yoff->SetValue( wxString::FromDouble( aModel->m_Offset.y * 25.4 ) );
|
||||
zoff->SetValue( wxString::FromDouble( aModel->m_Offset.z * 25.4 ) );
|
||||
break;
|
||||
|
||||
case INCHES:
|
||||
xoff->SetValue( wxString::FromDouble( aModel->m_Offset.x ) );
|
||||
yoff->SetValue( wxString::FromDouble( aModel->m_Offset.y ) );
|
||||
zoff->SetValue( wxString::FromDouble( aModel->m_Offset.z ) );
|
||||
break;
|
||||
|
||||
case DEGREES:
|
||||
case UNSCALED_UNITS:
|
||||
default:
|
||||
wxASSERT(0);
|
||||
}
|
||||
|
||||
UpdateModelName( aModel->m_Filename );
|
||||
|
||||
if( aReloadPreviewModule && m_previewPane )
|
||||
{
|
||||
updateListOnModelCopy();
|
||||
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Request_refresh();
|
||||
}
|
||||
|
||||
m_currentSelectedIdx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
// return if we are not in file selection mode
|
||||
if( NULL == m_FileTree )
|
||||
return;
|
||||
|
||||
// file selection mode: retrieve the filename and specify a
|
||||
// path relative to one of the config paths
|
||||
wxFileName fname = m_FileTree->GetFilePath();
|
||||
fname.Normalize();
|
||||
aModel->filename = m_resolver->ShortenPath( fname.GetFullPath() );
|
||||
if( m_previewPane )
|
||||
m_previewPane->SetFocus();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::SetModelData( S3D_INFO const* aModel )
|
||||
void PANEL_PREV_3D::ResetModelData( bool aReloadPreviewModule )
|
||||
{
|
||||
xscale->SetValue( wxString::FromDouble( aModel->scale.x ) );
|
||||
yscale->SetValue( wxString::FromDouble( aModel->scale.y ) );
|
||||
zscale->SetValue( wxString::FromDouble( aModel->scale.z ) );
|
||||
m_currentSelectedIdx = -1;
|
||||
|
||||
xrot->SetValue( wxString::FromDouble( aModel->rotation.x ) );
|
||||
yrot->SetValue( wxString::FromDouble( aModel->rotation.y ) );
|
||||
zrot->SetValue( wxString::FromDouble( aModel->rotation.z ) );
|
||||
xscale->SetValue( wxString::FromDouble( 1.0 ) );
|
||||
yscale->SetValue( wxString::FromDouble( 1.0 ) );
|
||||
zscale->SetValue( wxString::FromDouble( 1.0 ) );
|
||||
|
||||
xoff->SetValue( wxString::FromDouble( aModel->offset.x ) );
|
||||
yoff->SetValue( wxString::FromDouble( aModel->offset.y ) );
|
||||
zoff->SetValue( wxString::FromDouble( aModel->offset.z ) );
|
||||
xrot->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
yrot->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
zrot->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
|
||||
UpdateModelName( aModel->filename );
|
||||
xoff->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
yoff->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
zoff->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
|
||||
return;
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -443,102 +528,48 @@ void PANEL_PREV_3D::UpdateModelName( wxString const& aModelName )
|
|||
{
|
||||
bool newModel = false;
|
||||
|
||||
modelInfo.filename = aModelName;
|
||||
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();
|
||||
modelInfo.filename.clear();
|
||||
m_modelInfo.m_Filename.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString newModelFile;
|
||||
newModelFile = m_resolver->ResolvePath( aModelName );
|
||||
|
||||
if( m_resolver )
|
||||
newModelFile = m_resolver->ResolvePath( aModelName );
|
||||
|
||||
if( !newModelFile.empty() && newModelFile.Cmp( currentModelFile ) )
|
||||
newModel = true;
|
||||
|
||||
currentModelFile = newModelFile;
|
||||
modelInfo.filename = currentModelFile;
|
||||
}
|
||||
|
||||
if( currentModelFile.empty() || newModel )
|
||||
{
|
||||
if( NULL != canvas )
|
||||
{
|
||||
canvas->Clear3DModel();
|
||||
canvas->Refresh();
|
||||
canvas->Update();
|
||||
}
|
||||
updateListOnModelCopy();
|
||||
|
||||
model = NULL;
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
if( currentModelFile.empty() )
|
||||
return;
|
||||
}
|
||||
|
||||
if( NULL != m_ModelManager )
|
||||
model = m_ModelManager->GetModel( modelInfo.filename );
|
||||
else
|
||||
model = NULL;
|
||||
|
||||
if( NULL == model )
|
||||
{
|
||||
if( NULL != canvas )
|
||||
{
|
||||
canvas->Refresh();
|
||||
canvas->Update();
|
||||
}
|
||||
|
||||
return;
|
||||
if( m_previewPane )
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
if( NULL == canvas )
|
||||
{
|
||||
canvas = new C3D_MODEL_VIEWER( preview,
|
||||
COGL_ATT_LIST::GetAttributesList( true ) );
|
||||
|
||||
wxSizer* ws = new wxBoxSizer( wxHORIZONTAL );
|
||||
canvas->Set3DModel( *model );
|
||||
ws->Add( canvas, 1, wxEXPAND );
|
||||
preview->SetSizer( ws );
|
||||
preview->Layout();
|
||||
ws->FitInside( preview );
|
||||
|
||||
// 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.
|
||||
canvas->SetFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
canvas->Set3DModel( *model );
|
||||
canvas->Refresh();
|
||||
canvas->Update();
|
||||
canvas->SetFocus();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::UpdateWindowUI( long flags )
|
||||
{
|
||||
/*
|
||||
XXX -
|
||||
NOTE: until we figure out how to ensure that a Paint Event is
|
||||
generated for the File Selector's UI, we cannot display any
|
||||
preview within the file browser.
|
||||
if( wxUPDATE_UI_RECURSE == flags && m_FileDlg && m_ModelManager )
|
||||
{
|
||||
// check for a change in the current model file
|
||||
S3D_INFO info;
|
||||
modelInfo = info;
|
||||
UpdateModelName( m_FileDlg->GetCurrentlySelectedFilename() );
|
||||
}
|
||||
// */
|
||||
|
||||
wxPanel::UpdateWindowUI( flags );
|
||||
if( m_previewPane )
|
||||
m_previewPane->SetFocus();
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -546,33 +577,41 @@ void PANEL_PREV_3D::UpdateWindowUI( long flags )
|
|||
|
||||
void PANEL_PREV_3D::updateOrientation( wxCommandEvent &event )
|
||||
{
|
||||
// note: process even if the canvas is NULL since the user may
|
||||
// edit the filename to provide a valid file
|
||||
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 );
|
||||
|
||||
modelInfo.scale = scale;
|
||||
modelInfo.offset = offset;
|
||||
modelInfo.rotation = rotation;
|
||||
m_modelInfo.m_Scale = scale;
|
||||
m_modelInfo.m_Offset = offset;
|
||||
m_modelInfo.m_Rotation = rotation;
|
||||
|
||||
if( NULL == canvas )
|
||||
return;
|
||||
|
||||
canvas->Clear3DModel();
|
||||
|
||||
if( NULL != m_ModelManager )
|
||||
model = m_ModelManager->GetModel( modelInfo.filename );
|
||||
else
|
||||
model = NULL;
|
||||
|
||||
if( model )
|
||||
if( m_currentSelectedIdx >= 0 )
|
||||
{
|
||||
canvas->Set3DModel( *model );
|
||||
canvas->Refresh();
|
||||
canvas->Update();
|
||||
// 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();
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
|
@ -580,7 +619,7 @@ void PANEL_PREV_3D::updateOrientation( wxCommandEvent &event )
|
|||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::getOrientationVars( SGPOINT& scale, SGPOINT& rotation, SGPOINT& 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
|
||||
|
@ -589,30 +628,74 @@ void PANEL_PREV_3D::getOrientationVars( SGPOINT& scale, SGPOINT& rotation, SGPOI
|
|||
return;
|
||||
}
|
||||
|
||||
xscale->GetValue().ToDouble( &scale.x );
|
||||
yscale->GetValue().ToDouble( &scale.y );
|
||||
zscale->GetValue().ToDouble( &scale.z );
|
||||
xscale->GetValue().ToDouble( &aScale.x );
|
||||
yscale->GetValue().ToDouble( &aScale.y );
|
||||
zscale->GetValue().ToDouble( &aScale.z );
|
||||
|
||||
if( 0.0001 > scale.x || 0.0001 > scale.y || 0.0001 > scale.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 );
|
||||
|
||||
switch( g_UserUnit )
|
||||
{
|
||||
wxString errmsg = _("[INFO] invalid scale values; setting all to 1.0");
|
||||
wxLogMessage( "%s", errmsg.ToUTF8() );
|
||||
case MILLIMETRES:
|
||||
// Convert to Inches. Offset is stored in inches.
|
||||
aOffset.x = aOffset.x / 25.4;
|
||||
aOffset.y = aOffset.y / 25.4;
|
||||
aOffset.z = aOffset.z / 25.4;
|
||||
break;
|
||||
|
||||
scale.x = 1.0;
|
||||
scale.y = 1.0;
|
||||
scale.z = 1.0;
|
||||
case INCHES:
|
||||
// It is already in Inches
|
||||
break;
|
||||
|
||||
case DEGREES:
|
||||
case UNSCALED_UNITS:
|
||||
default:
|
||||
wxASSERT(0);
|
||||
}
|
||||
|
||||
xrot->GetValue().ToDouble( &rotation.x );
|
||||
yrot->GetValue().ToDouble( &rotation.y );
|
||||
zrot->GetValue().ToDouble( &rotation.z );
|
||||
checkRotation( rotation.x );
|
||||
checkRotation( rotation.y );
|
||||
checkRotation( rotation.z );
|
||||
|
||||
xoff->GetValue().ToDouble( &offset.x );
|
||||
yoff->GetValue().ToDouble( &offset.y );
|
||||
zoff->GetValue().ToDouble( &offset.z );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::updateListOnModelCopy()
|
||||
{
|
||||
bool gotAnInvalidScale = false;
|
||||
|
||||
for( unsigned int idx = 0; idx < m_parentInfoList->size(); ++idx )
|
||||
{
|
||||
SGPOINT scale = (*m_parentInfoList)[idx].m_Scale;
|
||||
|
||||
gotAnInvalidScale |= ( 0.0001 > scale.x || 0.0001 > scale.y || 0.0001 > scale.z );
|
||||
|
||||
if( 0.0001 > scale.x )
|
||||
scale.x = 1.0;
|
||||
|
||||
if( 0.0001 > scale.y )
|
||||
scale.y = 1.0;
|
||||
|
||||
if( 0.0001 > scale.y )
|
||||
scale.y = 1.0;
|
||||
|
||||
(*m_parentInfoList)[idx].m_Scale = scale;
|
||||
}
|
||||
|
||||
if( gotAnInvalidScale )
|
||||
{
|
||||
wxString errmsg = _("[INFO] invalid scale values; setting invalid to 1.0");
|
||||
wxLogMessage( "%s", errmsg.ToUTF8() );
|
||||
}
|
||||
|
||||
std::list<S3D_INFO>* draw3D = &m_copyModule->Models();
|
||||
draw3D->clear();
|
||||
draw3D->insert( draw3D->end(), m_parentInfoList->begin(), m_parentInfoList->end() );
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* 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>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -23,35 +24,51 @@
|
|||
|
||||
/**
|
||||
* @file panel_prev_model.h
|
||||
* defines a panel which is to be added to a wxFileDialog via SetExtraControl();
|
||||
* the panel shows a preview of the model being browsed (if preview is supported
|
||||
* by a plugin) and provides controls to set the offset/rotation/scale of the
|
||||
* model 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.
|
||||
* @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 <wx/panel.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include "../3d_info.h"
|
||||
#include <vector>
|
||||
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
#include "3d_cache/3d_info.h"
|
||||
|
||||
// Declared classes to create pointers
|
||||
class S3D_CACHE;
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
class C3D_MODEL_VIEWER;
|
||||
class wxGenericDirCtrl;
|
||||
class EDA_3D_CANVAS;
|
||||
class BOARD;
|
||||
class CINFO3D_VISU;
|
||||
class MODULE;
|
||||
|
||||
|
||||
class PANEL_PREV_3D : public wxPanel
|
||||
{
|
||||
public:
|
||||
PANEL_PREV_3D( wxWindow* aParent, S3D_CACHE* aCacheManager );
|
||||
|
||||
/**
|
||||
* @brief PANEL_PREV_3D - Creator
|
||||
* @param aParent: the parent windows (or object)
|
||||
* @param aCacheManager: the cache manager to use to resolve the 3D model files
|
||||
* @param aModule: a copy of the original module that is edited. this is for preview propose and
|
||||
* it will be changes, so dont use the original one.
|
||||
* @param aParentInfoList: a pointer to the Info list managed by the parent. This list will be
|
||||
* passed o the aModuleCopy so it will have the updated 3d model shapes list.
|
||||
*/
|
||||
PANEL_PREV_3D( wxWindow* aParent,
|
||||
S3D_CACHE* aCacheManager,
|
||||
MODULE* aModuleCopy,
|
||||
std::vector<S3D_INFO> *aParentInfoList = NULL );
|
||||
|
||||
~PANEL_PREV_3D();
|
||||
|
||||
// 3D views
|
||||
// 3D views buttons
|
||||
void View3DISO( wxCommandEvent& event );
|
||||
void View3DUpdate( wxCommandEvent& event );
|
||||
void View3DLeft( wxCommandEvent& event );
|
||||
|
@ -60,18 +77,28 @@ public:
|
|||
void View3DBack( wxCommandEvent& event );
|
||||
void View3DTop( wxCommandEvent& event );
|
||||
void View3DBottom( wxCommandEvent& event );
|
||||
// Set / Retrieve model data
|
||||
void SetModelData( S3D_INFO const* aModel );
|
||||
void GetModelData( S3D_INFO* aModel );
|
||||
|
||||
/**
|
||||
* @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 );
|
||||
// Update on change of FileDlg selection
|
||||
virtual void UpdateWindowUI( long flags = wxUPDATE_UI_NONE );
|
||||
|
||||
private:
|
||||
wxString currentModelFile;
|
||||
S3D_CACHE* m_ModelManager;
|
||||
S3D_FILENAME_RESOLVER* m_resolver;
|
||||
wxGenericDirCtrl* m_FileTree;
|
||||
wxString currentModelFile; ///< Used to check if the model file was changed
|
||||
S3D_FILENAME_RESOLVER *m_resolver; ///< Used to get the full path name
|
||||
|
||||
// Parameters
|
||||
wxTextCtrl* xscale;
|
||||
wxTextCtrl* yscale;
|
||||
wxTextCtrl* zscale;
|
||||
|
@ -81,16 +108,54 @@ private:
|
|||
wxTextCtrl* xoff;
|
||||
wxTextCtrl* yoff;
|
||||
wxTextCtrl* zoff;
|
||||
wxPanel* preview;
|
||||
C3D_MODEL_VIEWER* canvas;
|
||||
S3DMODEL* model;
|
||||
S3D_INFO modelInfo;
|
||||
|
||||
EDA_3D_CANVAS *m_previewPane;
|
||||
|
||||
/// The settings that will be used for this 3D viewer canvas
|
||||
CINFO3D_VISU *m_settings3Dviewer;
|
||||
|
||||
/// A dummy board used to store the copy moduled
|
||||
BOARD *m_dummyBoard;
|
||||
|
||||
/// A pointer to a new copy of the original module
|
||||
MODULE *m_copyModule;
|
||||
|
||||
/// A pointer to the parent S3D_INFO list that we will use to copy to the preview module
|
||||
std::vector<S3D_INFO> *m_parentInfoList;
|
||||
|
||||
/// The current selected index of the S3D_INFO list
|
||||
int m_currentSelectedIdx;
|
||||
|
||||
/// Current S3D_INFO that is being edited
|
||||
S3D_INFO m_modelInfo;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief updateOrientation - it will receive the events from editing the fields
|
||||
* @param event
|
||||
*/
|
||||
void updateOrientation( wxCommandEvent &event );
|
||||
|
||||
void getOrientationVars( SGPOINT& scale, SGPOINT& rotation, SGPOINT& offset );
|
||||
/**
|
||||
* @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();
|
||||
|
||||
/**
|
||||
* @brief OnCloseWindow - called when the frame is closed
|
||||
* @param event
|
||||
*/
|
||||
void OnCloseWindow( wxCloseEvent &event );
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
|
|
@ -1,739 +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 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 <gl_context_mgr.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 )
|
||||
#if wxCHECK_VERSION( 3, 1, 0 ) || defined( 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 = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
|
||||
|
||||
DisplayStatus();
|
||||
}
|
||||
|
||||
|
||||
EDA_3D_CANVAS::~EDA_3D_CANVAS()
|
||||
{
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
ClearLists();
|
||||
m_init = false;
|
||||
|
||||
// Free the list of parsers list
|
||||
for( unsigned int i = 0; i < m_model_parsers_list.size(); i++ )
|
||||
delete m_model_parsers_list[i];
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
GL_CONTEXT_MANAGER::Get().DestroyCtx( m_glRC );
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
#if wxCHECK_VERSION( 3, 1, 0 ) || defined( 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_3d( 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_3d.SetData( pixelbuffer );
|
||||
image_3d.SetAlpha( alphabuffer );
|
||||
image_3d = image_3d.Mirror( false );
|
||||
wxBitmap bitmap( image_3d );
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -1,375 +0,0 @@
|
|||
/*
|
||||
* 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 "3d_rendering/3d_render_raytracing/shapes3D/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 );
|
||||
#if wxCHECK_VERSION( 3, 1, 0 ) || defined( 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_ */
|
|
@ -0,0 +1,567 @@
|
|||
/*
|
||||
* 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 <colors_selection.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();
|
||||
|
||||
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( LAYER_ID aLayer ) const
|
||||
{
|
||||
wxASSERT( aLayer < 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;
|
||||
}
|
||||
|
||||
// Constant factors used for number of segments approximation calcs
|
||||
#define MIN_SEG_PER_CIRCLE 12
|
||||
#define MAX_SEG_PER_CIRCLE 48
|
||||
|
||||
#define SEG_MIN_FACTOR_BIU ( 0.10f * IU_PER_MM )
|
||||
#define SEG_MAX_FACTOR_BIU ( 6.00f * IU_PER_MM )
|
||||
|
||||
|
||||
unsigned int CINFO3D_VISU::GetNrSegmentsCircle( float aDiameter3DU ) const
|
||||
{
|
||||
wxASSERT( aDiameter3DU > 0.0f );
|
||||
|
||||
unsigned int result = mapf( aDiameter3DU,
|
||||
m_calc_seg_min_factor3DU, m_calc_seg_max_factor3DU,
|
||||
(float)MIN_SEG_PER_CIRCLE, (float)MAX_SEG_PER_CIRCLE );
|
||||
wxASSERT( result > 1 );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
unsigned int CINFO3D_VISU::GetNrSegmentsCircle( int aDiameterBUI ) const
|
||||
{
|
||||
wxASSERT( aDiameterBUI > 0 );
|
||||
|
||||
unsigned int result = mapf( (float)aDiameterBUI,
|
||||
(float)SEG_MIN_FACTOR_BIU, (float)SEG_MAX_FACTOR_BIU,
|
||||
(float)MIN_SEG_PER_CIRCLE, (float)MAX_SEG_PER_CIRCLE );
|
||||
wxASSERT( result > 1 );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
double CINFO3D_VISU::GetCircleCorrectionFactor( int aNrSides ) const
|
||||
{
|
||||
wxASSERT( aNrSides >= 3 );
|
||||
|
||||
return 1.0 / cos( M_PI / ( (double)aNrSides * 2.0 ) );
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
|
||||
// Calculate factors for cicle segment approximation
|
||||
m_calc_seg_min_factor3DU = (float)( SEG_MIN_FACTOR_BIU * m_biuTo3Dunits );
|
||||
m_calc_seg_max_factor3DU = (float)( SEG_MAX_FACTOR_BIU * m_biuTo3Dunits );
|
||||
|
||||
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 < 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();
|
||||
|
||||
// Create board outlines and board holes
|
||||
SHAPE_POLY_SET allLayerHoles;
|
||||
|
||||
wxString errmsg;
|
||||
|
||||
if( !m_board->GetBoardPolygonOutlines( m_board_poly, allLayerHoles, &errmsg ) )
|
||||
{
|
||||
errmsg.append( wxT( "\n\n" ) );
|
||||
errmsg.append( _( "Unable to calculate the board outlines." ) );
|
||||
errmsg.append( wxT( "\n" ) );
|
||||
errmsg.append( _( "Therefore use the board boundary box." ) );
|
||||
wxLogMessage( "%s", errmsg.ToUTF8() );
|
||||
}
|
||||
|
||||
m_board_poly.BooleanSubtract( allLayerHoles, SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
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( LAYER_ID aLayerId ) const
|
||||
{
|
||||
wxASSERT( aLayerId < LAYER_ID_COUNT );
|
||||
|
||||
const EDA_COLOR_T color = g_ColorsSettings.GetLayerColor( aLayerId );
|
||||
const StructColors &colordata = g_ColorRefs[ColorGetBase( color )];
|
||||
|
||||
static const float inv_255 = 1.0f / 255.0f;
|
||||
|
||||
const float red = colordata.m_Red * inv_255;
|
||||
const float green = colordata.m_Green * inv_255;
|
||||
const float blue = colordata.m_Blue * inv_255;
|
||||
|
||||
return SFVEC3F( red, green, blue );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetItemColor( int aItemId ) const
|
||||
{
|
||||
return GetColor( g_ColorsSettings.GetItemColor( aItemId ) );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetColor( EDA_COLOR_T aColor ) const
|
||||
{
|
||||
const StructColors &colordata = g_ColorRefs[ColorGetBase( aColor )];
|
||||
|
||||
static const float inv_255 = 1.0f / 255.0f;
|
||||
|
||||
const float red = colordata.m_Red * inv_255;
|
||||
const float green = colordata.m_Green * inv_255;
|
||||
const float blue = colordata.m_Blue * inv_255;
|
||||
|
||||
return SFVEC3F( red, green, blue );
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -36,63 +36,25 @@
|
|||
#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 <wxBasePcbFrame.h>
|
||||
#include <clipper.hpp>
|
||||
#include <class_pcb_text.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_zone.h>
|
||||
|
||||
|
||||
/**
|
||||
* Flags used in rendering options
|
||||
*/
|
||||
enum DISPLAY3D_FLG {
|
||||
FL_AXIS=0, FL_MODULE, FL_ZONE,
|
||||
FL_ADHESIVE, FL_SILKSCREEN, FL_SOLDERMASK, FL_SOLDERPASTE,
|
||||
FL_COMMENTS, FL_ECO,
|
||||
FL_USE_COPPER_THICKNESS,
|
||||
FL_SHOW_BOARD_BODY,
|
||||
FL_USE_REALISTIC_MODE,
|
||||
FL_RENDER_SHADOWS,
|
||||
FL_RENDER_SHOW_HOLES_IN_ZONES,
|
||||
FL_RENDER_TEXTURES,
|
||||
FL_RENDER_SMOOTH_NORMALS,
|
||||
FL_RENDER_USE_MODEL_NORMALS,
|
||||
FL_RENDER_MATERIAL,
|
||||
FL_RENDER_SHOW_MODEL_BBOX,
|
||||
FL_LAST
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Camera types
|
||||
*/
|
||||
enum CAMERA_TYPE
|
||||
{
|
||||
CAMERA_TRACKBALL
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Grid types
|
||||
*/
|
||||
enum GRID3D_TYPE
|
||||
{
|
||||
GRID3D_NONE,
|
||||
GRID3D_1MM,
|
||||
GRID3D_2P5MM,
|
||||
GRID3D_5MM,
|
||||
GRID3D_10MM
|
||||
};
|
||||
|
||||
#include <class_module.h>
|
||||
#include <reporter.h>
|
||||
|
||||
/// A type that stores a container of 2d objects for each layer id
|
||||
typedef std::map< LAYER_ID, CBVHCONTAINER2D *> MAP_CONTAINER_2D;
|
||||
|
||||
/// A type that stores polysets for each layer id
|
||||
typedef std::map< 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
|
||||
|
@ -112,6 +74,18 @@ class 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
|
||||
|
@ -133,6 +107,13 @@ class CINFO3D_VISU
|
|||
*/
|
||||
bool Is3DLayerEnabled( 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
|
||||
|
@ -148,18 +129,19 @@ class CINFO3D_VISU
|
|||
/**
|
||||
* @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();
|
||||
void InitSettings( REPORTER *aStatusTextReporter );
|
||||
|
||||
/**
|
||||
* Function BiuTo3Dunits
|
||||
* @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
|
||||
* @return the board bbox in 3d units
|
||||
*/
|
||||
const CBBOX &GetBBox3DU() const { return m_boardBoudingBox; }
|
||||
|
||||
|
@ -167,19 +149,19 @@ class CINFO3D_VISU
|
|||
* @brief GetEpoxyThickness3DU - Get the current epoxy thickness
|
||||
* @return thickness in 3d unities
|
||||
*/
|
||||
float GetEpoxyThickness3DU() const { return m_epoxyThickness; }
|
||||
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_nonCopperLayerThickness; }
|
||||
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_copperThickness; }
|
||||
float GetCopperThickness3DU() const { return m_copperThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetCopperThicknessBIU - Get the current copper layer thickness
|
||||
|
@ -188,26 +170,35 @@ class CINFO3D_VISU
|
|||
int GetCopperThicknessBIU() const;
|
||||
|
||||
/**
|
||||
* @brief GetBoardSize3DU - Get the board size
|
||||
* @return size in 3D unities
|
||||
* @brief GetBoardSizeBIU - Get the board size
|
||||
* @return size in BIU unities
|
||||
*/
|
||||
wxSize GetBoardSize3DU() const { return m_boardSize; }
|
||||
wxSize GetBoardSizeBIU() const { return m_boardSize; }
|
||||
|
||||
/**
|
||||
* Function GetBoardCenter
|
||||
* @return board center in 3d units
|
||||
* @brief GetBoardPosBIU - Get the board size
|
||||
* @return size in BIU unities
|
||||
*/
|
||||
SFVEC3F &GetBoardCenter3DU() { return m_boardCenter; }
|
||||
wxPoint GetBoardPosBIU() const { return m_boardPos; }
|
||||
|
||||
/**
|
||||
* @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 Units
|
||||
* @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 ;
|
||||
|
||||
/**
|
||||
* @param aCameraType: camera type to use in this canvas
|
||||
* @brief CameraSetType - Set the camera type to use
|
||||
* @param aCameraType: camera type to use in this canvas
|
||||
*/
|
||||
void CameraSetType( CAMERA_TYPE aCameraType );
|
||||
|
||||
|
@ -218,22 +209,46 @@ class CINFO3D_VISU
|
|||
CCAMERA &CameraGet() const { return m_currentCamera; }
|
||||
|
||||
/**
|
||||
* Function GridGet
|
||||
* @return space type of the grid
|
||||
* @brief GridGet - get the current grid
|
||||
* @return space type of the grid
|
||||
*/
|
||||
GRID3D_TYPE GridGet() const { return m_3D_Grid_type; }
|
||||
GRID3D_TYPE GridGet() const { return m_3D_grid_type; }
|
||||
|
||||
/**
|
||||
* Function GridSet
|
||||
* @param aGridType = the type space of the grid
|
||||
* @brief GridSet - set the current grid
|
||||
* @param aGridType = the type space of the grid
|
||||
*/
|
||||
void GridSet( GRID3D_TYPE aGridType ) { m_3D_Grid_type = aGridType; }
|
||||
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_boardPoly; }
|
||||
const SHAPE_POLY_SET &GetBoardPoly() const { return m_board_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetLayerColor - get the technical color of a layer
|
||||
|
@ -249,6 +264,13 @@ class CINFO3D_VISU
|
|||
*/
|
||||
SFVEC3F GetItemColor( int aItemId ) const;
|
||||
|
||||
/**
|
||||
* @brief GetColor
|
||||
* @param aColor: the color mapped
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetColor( EDA_COLOR_T aColor ) const;
|
||||
|
||||
/**
|
||||
* @brief GetLayerTopZpos3DU - Get the top z position
|
||||
* @param aLayerId: layer id
|
||||
|
@ -276,90 +298,365 @@ class CINFO3D_VISU
|
|||
const MAP_CONTAINER_2D &GetMapLayersHoles() const { return m_layers_holes2D; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Inflated - Get the inflated ThroughHole container
|
||||
* @brief GetThroughHole_Outer - Get the inflated ThroughHole container
|
||||
* @return a container with holes
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Inflated() const { return m_throughHoles_inflated; }
|
||||
const CBVHCONTAINER2D &GetThroughHole_Outer() const { return m_through_holes_outer; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole - Get the ThroughHole container
|
||||
* @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() const { return m_throughHoles; }
|
||||
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 aDiameter: diameter in 3DU
|
||||
* @return number of sides that should be used in that circle
|
||||
*/
|
||||
unsigned int GetNrSegmentsCircle( float aDiameter3DU ) const;
|
||||
|
||||
/**
|
||||
* @brief GetNrSegmentsCircle
|
||||
* @param aDiameterBUI: diameter in board unities
|
||||
* @return number of sides that should be used in that circle
|
||||
*/
|
||||
unsigned int GetNrSegmentsCircle( int aDiameterBUI ) 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();
|
||||
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, const wxSize &aInflateValue ) const;
|
||||
void createNewPadWithClearance( const D_PAD* aPad, CGENERICCONTAINER2D *aDstContainer, int aClearanceValue ) const;
|
||||
COBJECT2D *createNewPadDrill(const D_PAD* aPad, int aInflateValue);
|
||||
void AddPadsShapesWithClearanceToContainer( const MODULE* aModule, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId, int aInflateValue, bool aSkipNPTHPadsWihNoCopper );
|
||||
void AddGraphicsShapesWithClearanceToContainer( const MODULE* aModule, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId, int aInflateValue );
|
||||
void AddShapeWithClearanceToContainer( const TEXTE_PCB* aTextPCB, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId, int aClearanceValue );
|
||||
void AddShapeWithClearanceToContainer(const DRAWSEGMENT* aDrawSegment, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId, int aClearanceValue );
|
||||
void AddSolidAreasShapesToContainer( const ZONE_CONTAINER* aZoneContainer, CGENERICCONTAINER2D *aDstContainer, 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);
|
||||
|
||||
void createNewPad( const D_PAD* aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
const wxSize &aInflateValue ) const;
|
||||
|
||||
void createNewPadWithClearance( const D_PAD *aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
int aClearanceValue ) const;
|
||||
|
||||
COBJECT2D *createNewPadDrill( const D_PAD* aPad, int aInflateValue );
|
||||
|
||||
void AddPadsShapesWithClearanceToContainer( const MODULE *aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
LAYER_ID aLayerId,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper );
|
||||
|
||||
void AddGraphicsShapesWithClearanceToContainer( const MODULE *aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
LAYER_ID aLayerId,
|
||||
int aInflateValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const TEXTE_PCB *aTextPCB,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const DRAWSEGMENT *aDrawSegment,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddSolidAreasShapesToContainer( const ZONE_CONTAINER *aZoneContainer,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
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,
|
||||
LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper) const;
|
||||
|
||||
void transformGraphicModuleEdgeToPolygonSet( const MODULE *aModule,
|
||||
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:
|
||||
wxColour m_BgColor;
|
||||
wxColour m_BgColor_Top;
|
||||
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
|
||||
std::vector< bool > m_drawFlags; ///< options flags to render the board
|
||||
GRID3D_TYPE m_3D_Grid_type; ///< Stores the current grid type
|
||||
|
||||
/// 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
|
||||
wxPoint m_boardPos; ///< center board actual position in board units
|
||||
wxSize m_boardSize; ///< board actual size in board units
|
||||
SFVEC3F m_boardCenter; ///< 3d center position of the pcb board in 3d units
|
||||
|
||||
/// 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
|
||||
CBBOX m_boardBoudingBox; ///< 3d bouding box of the pcb board in 3d units
|
||||
CBBOX2D m_board2dBBox3DU; ///< 2d bouding box of the pcb board in 3d units
|
||||
|
||||
SHAPE_POLY_SET m_boardPoly; ///< PCB board outline polygon
|
||||
/// 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
|
||||
MAP_CONTAINER_2D m_layers_container2D; ///< It contains the 2d elements of each layer
|
||||
MAP_CONTAINER_2D m_layers_holes2D; ///< It contains the holes per each layer
|
||||
CBVHCONTAINER2D m_throughHoles_inflated; ///< It contains the list of throughHoles of the board, the radius of the hole is inflated with the copper tickness
|
||||
CBVHCONTAINER2D m_throughHoles; ///< It contains the list of throughHoles of the board, the radius of the hole is inflated with the copper tickness
|
||||
|
||||
/// 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
|
||||
unsigned int m_copperLayersCount; ///< Number of copper layers actually used by the board
|
||||
double m_biuTo3Dunits; ///< Normalization scale to convert board internal units to 3D units to normalize 3D units between -1.0 and +1.0
|
||||
float m_layerZcoordTop[LAYER_ID_COUNT]; ///< Top (End) Z position of each layer (normalized)
|
||||
float m_layerZcoordBottom[LAYER_ID_COUNT]; ///< Bottom (Start) Z position of each layer (normalized)
|
||||
float m_copperThickness; ///< Copper thickness (normalized)
|
||||
float m_epoxyThickness; ///< Epoxy thickness (normalized)
|
||||
float m_nonCopperLayerThickness; ///< Non copper layers thickness
|
||||
|
||||
/// 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[LAYER_ID_COUNT];
|
||||
|
||||
/// Bottom (Start) Z position of each layer (normalized)
|
||||
float m_layerZcoordBottom[LAYER_ID_COUNT];
|
||||
|
||||
/// Copper thickness (normalized)
|
||||
float m_copperThickness3DU;
|
||||
|
||||
/// Epoxy thickness (normalized)
|
||||
float m_epoxyThickness3DU;
|
||||
|
||||
/// Non copper layers thickness
|
||||
float m_nonCopperLayerThickness3DU;
|
||||
|
||||
|
||||
// Cameras
|
||||
CCAMERA &m_currentCamera; ///< Holds a pointer to current camera in use.
|
||||
|
||||
/// 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;
|
||||
unsigned int m_stats_nr_vias; ///< Nr of vias
|
||||
float m_stats_via_med_hole_diameter; ///< Computed medium diameter of the via holes in 3dunits
|
||||
|
||||
/// 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;
|
||||
float m_stats_hole_med_diameter; ///< Computed medium diameter of the holes in 3dunits
|
||||
|
||||
/// 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.
|
||||
|
@ -371,6 +668,7 @@ class CINFO3D_VISU
|
|||
|
||||
};
|
||||
|
||||
/// This is a dummy visualization configuration
|
||||
extern CINFO3D_VISU G_null_CINFO3D_VISU;
|
||||
|
||||
#endif // CINFO3D_VISU_H
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* 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:
|
||||
aPad->TransformShapeWithClearanceToPolygon( aCornerBuffer, aInflateValue.x,
|
||||
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;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( wxT( "CINFO3D_VISU::buildPadShapePolygon: found a not implemented pad shape (new shape?)" ) );
|
||||
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, 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,
|
||||
LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer ) const
|
||||
{
|
||||
for( const EDA_ITEM* item = aModule->GraphicalItems();
|
||||
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
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* 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 <wx/clipbrd.h>
|
||||
#include <wx/dataobj.h>
|
||||
#include <wx/glcanvas.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/statusbr.h>
|
||||
#include <wxBasePcbFrame.h>
|
||||
|
||||
|
||||
/**
|
||||
* Class EDA_3D_CANVAS
|
||||
* Implement a canvas based on a wxGLCanvas
|
||||
*/
|
||||
class EDA_3D_CANVAS : public wxGLCanvas
|
||||
{
|
||||
|
||||
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 keycode: ascii key commands
|
||||
*/
|
||||
void SetView3D( int keycode );
|
||||
|
||||
/**
|
||||
* @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 );
|
||||
|
||||
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 OnKeyEvent( wxKeyEvent& event );
|
||||
|
||||
void OnTimerTimeout_Editing( wxTimerEvent& event );
|
||||
|
||||
/**
|
||||
* @brief OnCloseWindow - called when the frame is closed
|
||||
* @param event
|
||||
*/
|
||||
void OnCloseWindow( wxCloseEvent &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
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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 )
|
||||
{
|
||||
if( !aText.IsEmpty() )
|
||||
m_hasMessage = true;
|
||||
|
||||
if( m_parentStatusBar )
|
||||
m_parentStatusBar->SetStatusText( aText, m_position );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HasMessage() const { return m_hasMessage; }
|
||||
};
|
||||
|
||||
|
||||
#endif // STATUS_TEXT_REPORTER_H_
|
|
@ -1,181 +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 3d_class.cpp
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
|
||||
#include "3d_viewer.h"
|
||||
#include "3d_struct.h"
|
||||
#include "common.h"
|
||||
#include "modelparsers.h"
|
||||
#include <kiway.h>
|
||||
#include <3d_cache.h>
|
||||
#include <3d_filename_resolver.h>
|
||||
|
||||
extern KIWAY* TheKiway;
|
||||
|
||||
|
||||
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_Shape3DName.StartsWith( wxT("$(") ) )
|
||||
m_Shape3DFullFilename = ExpandEnvVarSubstitutions( m_Shape3DName );
|
||||
else
|
||||
m_Shape3DFullFilename = m_Shape3DName;
|
||||
|
||||
if( NULL != TheKiway )
|
||||
{
|
||||
m_Shape3DFullFilename = TheKiway->Prj().Get3DCacheManager()->GetResolver()
|
||||
->ResolvePath( 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
|
@ -1,426 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* 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_
|
|
@ -1,640 +0,0 @@
|
|||
/*
|
||||
* 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 <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 polygonsCalcMode = 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
|
||||
SHAPE_POLY_SET::POLYGON_MODE polygonsCalcMode = SHAPE_POLY_SET::PM_FAST;
|
||||
|
||||
/* 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( polygonsCalcMode );
|
||||
}
|
||||
|
||||
|
||||
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( polygonsCalcMode );
|
||||
bufferPolys.BooleanSubtract( currLayerHoles, polygonsCalcMode );
|
||||
}
|
||||
else
|
||||
bufferPolys.BooleanSubtract( allLayerHoles, polygonsCalcMode );
|
||||
|
||||
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, polygonsCalcMode );
|
||||
|
||||
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 item 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( polygonsCalcMode );
|
||||
|
||||
bufferPolys.BooleanSubtract( cuts, polygonsCalcMode );
|
||||
}
|
||||
// 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, polygonsCalcMode );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
|
@ -1,493 +0,0 @@
|
|||
/*
|
||||
* 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 thickness
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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,
|
||||
FL_RENDER_SHOW_HOLES_IN_ZONES,
|
||||
|
||||
// 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_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_
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -47,6 +47,14 @@
|
|||
#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
|
||||
|
@ -85,54 +93,84 @@
|
|||
|
||||
|
||||
// Global Inline Functions
|
||||
inline uint32_t FloatToBits(float f) {
|
||||
inline uint32_t FloatToBits( float f )
|
||||
{
|
||||
uint32_t ui;
|
||||
memcpy(&ui, &f, sizeof(float));
|
||||
|
||||
memcpy( &ui, &f, sizeof( float ) );
|
||||
|
||||
return ui;
|
||||
}
|
||||
|
||||
inline float BitsToFloat(uint32_t ui) {
|
||||
|
||||
inline float BitsToFloat( uint32_t ui )
|
||||
{
|
||||
float f;
|
||||
memcpy(&f, &ui, sizeof(uint32_t));
|
||||
|
||||
memcpy( &f, &ui, sizeof (uint32_t ) );
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
inline uint64_t FloatToBits(double f) {
|
||||
|
||||
inline uint64_t FloatToBits( double f )
|
||||
{
|
||||
uint64_t ui;
|
||||
memcpy(&ui, &f, sizeof(double));
|
||||
|
||||
memcpy( &ui, &f, sizeof( double ) );
|
||||
|
||||
return ui;
|
||||
}
|
||||
|
||||
inline double BitsToFloat(uint64_t ui) {
|
||||
|
||||
inline double BitsToFloat( uint64_t ui )
|
||||
{
|
||||
double f;
|
||||
memcpy(&f, &ui, sizeof(uint64_t));
|
||||
|
||||
memcpy( &f, &ui, sizeof( uint64_t ) );
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
inline float NextFloatUp(float v) {
|
||||
|
||||
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;
|
||||
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.)
|
||||
uint32_t ui = FloatToBits( v );
|
||||
|
||||
if( v >= 0. )
|
||||
++ui;
|
||||
else
|
||||
--ui;
|
||||
return BitsToFloat(ui);
|
||||
|
||||
return BitsToFloat( ui );
|
||||
}
|
||||
|
||||
inline float NextFloatDown(float v) {
|
||||
|
||||
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.)
|
||||
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);
|
||||
|
||||
return BitsToFloat( ui );
|
||||
}
|
||||
|
||||
#endif // 3D_FASTMATH_H
|
|
@ -1,913 +0,0 @@
|
|||
/**
|
||||
* @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, VIEWER3D_FRAMENAME )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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 );
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* 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 <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
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -30,8 +30,8 @@
|
|||
#ifndef _3D_MATH_H
|
||||
#define _3D_MATH_H
|
||||
|
||||
#include "plugins/3dapi/xv3d_types.h"
|
||||
|
||||
#include <plugins/3dapi/xv3d_types.h>
|
||||
#include "3d_fastmath.h"
|
||||
|
||||
// https://en.wikipedia.org/wiki/Spherical_coordinate_system
|
||||
/**
|
||||
|
@ -53,13 +53,21 @@ inline SFVEC3F SphericalToCartesian( float aInclination, float aAzimuth )
|
|||
// !TODO: this is not correct because it is not a gaussian random
|
||||
inline SFVEC3F UniformRandomHemisphereDirection( )
|
||||
{
|
||||
SFVEC3F b( (rand()/(float)RAND_MAX) - 0.5f, (rand()/(float)RAND_MAX) - 0.5f, (rand()/(float)RAND_MAX) - 0.5f);
|
||||
// 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( SFVEC3F n )
|
||||
inline SFVEC3F CosWeightedRandomHemisphereDirection( const SFVEC3F &n )
|
||||
{
|
||||
const float Xi1 = (float)rand() / (float)RAND_MAX;
|
||||
const float Xi2 = (float)rand() / (float)RAND_MAX;
|
||||
|
@ -74,9 +82,9 @@ inline SFVEC3F CosWeightedRandomHemisphereDirection( SFVEC3F n )
|
|||
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 ) )
|
||||
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))
|
||||
else if( fabs( h.y ) <= fabs( h.x ) && fabs( h.y ) <= fabs( h.z ) )
|
||||
h.y= 1.0f;
|
||||
else
|
||||
h.z= 1.0f;
|
||||
|
@ -92,15 +100,20 @@ inline SFVEC3F CosWeightedRandomHemisphereDirection( SFVEC3F n )
|
|||
|
||||
/**
|
||||
* @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
|
||||
* 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 )
|
||||
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 );
|
||||
|
@ -111,15 +124,66 @@ inline bool Refract( const SFVEC3F &aInVector, const SFVEC3F &aNormal, float aRi
|
|||
return false;
|
||||
|
||||
float cosThetaT = sqrtf( 1.0f - sin2ThetaT );
|
||||
aOutVector = glm::normalize( aRin_over_Rout * aInVector + ( aRin_over_Rout * cosThetaI - cosThetaT ) * aNormal );
|
||||
|
||||
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)
|
||||
|
||||
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 SFVEC3F MaterialDiffuseToColorCAD( const SFVEC3F &aDiffuseColor )
|
||||
{
|
||||
// convert to a discret scale of grays
|
||||
const float luminance = glm::min( (((float)((unsigned int) ( 4.0f *
|
||||
(aDiffuseColor.r * 0.2126f +
|
||||
aDiffuseColor.g * 0.7152f +
|
||||
aDiffuseColor.b * 0.0722f))) + 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
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* 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 <vector>
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <glm/glm.hpp>
|
||||
#include "3d_struct.h"
|
||||
#include "3d_material.h"
|
||||
#include "3d_rendering/3d_render_raytracing/shapes3D/cbbox.h"
|
||||
|
||||
|
||||
class S3D_MESH;
|
||||
|
||||
/** A smart pointer to an S3D_MESH object */
|
||||
typedef std::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,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -30,13 +30,18 @@
|
|||
*/
|
||||
|
||||
#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_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 "convert_to_biu.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)
|
||||
|
||||
/**
|
||||
|
@ -69,14 +74,14 @@ BEGIN_EVENT_TABLE( C3D_MODEL_VIEWER, wxGLCanvas )
|
|||
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)
|
||||
// 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 ) :
|
||||
C3D_MODEL_VIEWER::C3D_MODEL_VIEWER(wxWindow *aParent,
|
||||
const int *aAttribList , S3D_CACHE *aCacheManager) :
|
||||
|
||||
wxGLCanvas( aParent,
|
||||
wxID_ANY,
|
||||
|
@ -84,7 +89,8 @@ C3D_MODEL_VIEWER::C3D_MODEL_VIEWER( wxWindow *aParent,
|
|||
wxDefaultPosition,
|
||||
wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE ),
|
||||
m_trackBallCamera( RANGE_SCALE_3D * 2.0f )
|
||||
m_trackBallCamera( RANGE_SCALE_3D * 2.0f ),
|
||||
m_cacheManager(aCacheManager)
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::C3D_MODEL_VIEWER" ) );
|
||||
|
||||
|
@ -94,28 +100,30 @@ C3D_MODEL_VIEWER::C3D_MODEL_VIEWER( wxWindow *aParent,
|
|||
m_3d_model = NULL;
|
||||
m_BiuTo3Dunits = 1.0;
|
||||
|
||||
// Explicitly create a new rendering context instance for this canvas.
|
||||
m_glRC = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
|
||||
m_glRC = NULL;
|
||||
}
|
||||
|
||||
|
||||
C3D_MODEL_VIEWER::~C3D_MODEL_VIEWER()
|
||||
{
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::~C3D_MODEL_VIEWER" ) );
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
if( m_glRC )
|
||||
{
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
GL_CONTEXT_MANAGER::Get().DestroyCtx( m_glRC );
|
||||
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" ) );
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::Set3DModel with a S3DMODEL" ) );
|
||||
|
||||
// Validate a3DModel pointers
|
||||
wxASSERT( a3DModel.m_Materials != NULL );
|
||||
|
@ -135,16 +143,38 @@ void C3D_MODEL_VIEWER::Set3DModel( const S3DMODEL &a3DModel )
|
|||
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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -168,7 +198,10 @@ void C3D_MODEL_VIEWER::ogl_initialize()
|
|||
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 };
|
||||
const GLfloat position[] = { 0.0f, 0.0f, 2.0f * RANGE_SCALE_3D, 0.0f }; // defines a directional light that points along the negative z-axis
|
||||
|
||||
// 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 );
|
||||
|
@ -195,6 +228,8 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
|||
{
|
||||
wxPaintDC( this );
|
||||
|
||||
event.Skip( false );
|
||||
|
||||
// SwapBuffer requires the window to be shown before calling
|
||||
if( !IsShownOnScreen() )
|
||||
{
|
||||
|
@ -205,6 +240,9 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
|||
// "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.
|
||||
|
@ -226,11 +264,13 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
|||
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 );
|
||||
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);
|
||||
m_BiuTo3Dunits = (double)RANGE_SCALE_3D /
|
||||
( (double)m_ogl_3dmodel->GetBBox().GetMaxDimension() *
|
||||
UNITS3D_TO_UNITSPCB );
|
||||
}
|
||||
|
||||
glViewport( 0, 0, clientSize.x, clientSize.y );
|
||||
|
@ -253,8 +293,8 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
|||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetViewMatrix() ) );
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable( GL_LIGHTING );
|
||||
glEnable( GL_LIGHT0 );
|
||||
|
||||
// Render Model
|
||||
if( m_ogl_3dmodel )
|
||||
|
@ -263,22 +303,24 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
|||
|
||||
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);
|
||||
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 );
|
||||
|
||||
// !TODO: draw transparent models
|
||||
m_ogl_3dmodel->Draw_opaque();
|
||||
m_ogl_3dmodel->Draw_transparent();
|
||||
//m_ogl_3dmodel->Draw_bboxes();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
glViewport( 0, 0, clientSize.y / 8 , clientSize.y / 8 ); // YxY squared view port
|
||||
// YxY squared view port
|
||||
glViewport( 0, 0, clientSize.y / 8 , clientSize.y / 8 );
|
||||
glClear( GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
|
@ -288,7 +330,9 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
|||
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 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 ) );
|
||||
|
@ -314,9 +358,8 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
|||
// 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 );
|
||||
|
||||
event.Skip();
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
}
|
||||
|
||||
|
||||
|
@ -432,3 +475,4 @@ void C3D_MODEL_VIEWER::OnRightClick( wxMouseEvent &event )
|
|||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -32,10 +32,11 @@
|
|||
#ifndef _C3D_MODEL_VIEWER_H_
|
||||
#define _C3D_MODEL_VIEWER_H_
|
||||
|
||||
#include "3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h"
|
||||
#include "3d_rendering/ctrack_ball.h"
|
||||
#include <wx/glcanvas.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class C_OGL_3DMODEL;
|
||||
|
||||
/**
|
||||
* Class C3D_MODEL_VIEWER
|
||||
|
@ -50,10 +51,12 @@ 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
|
||||
* @param aAttribList = a list of openGL options created by
|
||||
* COGL_ATT_LIST::GetAttributesList
|
||||
*/
|
||||
C3D_MODEL_VIEWER( wxWindow *aParent,
|
||||
const int *aAttribList = 0 );
|
||||
const int *aAttribList = 0,
|
||||
S3D_CACHE *aCacheManager = NULL );
|
||||
|
||||
~C3D_MODEL_VIEWER();
|
||||
|
||||
|
@ -63,6 +66,12 @@ public:
|
|||
*/
|
||||
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
|
||||
*/
|
||||
|
@ -91,6 +100,7 @@ private:
|
|||
void OnLeftUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleDown( wxMouseEvent &event );
|
||||
|
||||
void OnRightClick( wxMouseEvent &event );
|
||||
|
@ -117,10 +127,14 @@ private:
|
|||
/// 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
|
||||
/// 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
|
||||
|
|
|
@ -1,173 +0,0 @@
|
|||
/*
|
||||
* 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 <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;
|
||||
|
||||
m_BBox.Reset();
|
||||
|
||||
for( unsigned int idx = 0; idx < m_parser->childs.size(); idx++ )
|
||||
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 );
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -32,13 +32,26 @@
|
|||
|
||||
#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< LAYER_ID, CLAYERS_OGL_DISP_LISTS* > MAP_OGL_DISP_LISTS;
|
||||
typedef std::map< LAYER_ID, CLAYER_TRIANGLES * > MAP_TRIANGLES;
|
||||
typedef std::map< wxString, C_OGL_3DMODEL * > MAP_3DMODEL;
|
||||
|
||||
#define SIZE_OF_CIRCLE_TEXTURE 512
|
||||
#define SIZE_OF_CIRCLE_TEXTURE 1024
|
||||
|
||||
/**
|
||||
* @brief The C3D_RENDER_OGL_LEGACY class render the board using openGL legacy mode
|
||||
|
@ -46,30 +59,157 @@ typedef std::map< LAYER_ID, CLAYER_TRIANGLES * > MAP_TRIANGLES;
|
|||
class C3D_RENDER_OGL_LEGACY : public C3D_RENDER_BASE
|
||||
{
|
||||
public:
|
||||
C3D_RENDER_OGL_LEGACY( CINFO3D_VISU &aSettings,
|
||||
S3D_CACHE *a3DModelManager );
|
||||
explicit C3D_RENDER_OGL_LEGACY( CINFO3D_VISU &aSettings );
|
||||
|
||||
~C3D_RENDER_OGL_LEGACY();
|
||||
|
||||
// Imported from C3D_RENDER_BASE
|
||||
void SetCurWindowSize( const wxSize &aSize );
|
||||
void Redraw( bool aIsMoving );
|
||||
bool Redraw( bool aIsMoving, REPORTER *aStatusTextReporter );
|
||||
|
||||
int GetWaitForEditingTimeOut();
|
||||
|
||||
private:
|
||||
bool initializeOpenGL();
|
||||
void reload();
|
||||
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 add_triangle_top_bot( CLAYER_TRIANGLES *aDst, const SFVEC2F &v0, const SFVEC2F &v1, const SFVEC2F &v2, float top, float bot );
|
||||
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( LAYER_ID aLayerID,
|
||||
float aZPosition,
|
||||
bool aIsRenderingOnPreviewMode );
|
||||
|
||||
void get_layer_z_pos( 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();
|
||||
|
||||
/**
|
||||
* @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( LAYER_ID aLayerID );
|
||||
SFVEC3F get_layer_color( LAYER_ID aLayerID );
|
||||
|
||||
public:
|
||||
const MAP_OGL_DISP_LISTS &GetLayerDispListMap() const { return m_ogl_disp_lists_layers; }
|
||||
|
@ -78,3 +218,4 @@ public:
|
|||
};
|
||||
|
||||
#endif // C3D_RENDER_OGL_LEGACY_H_
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -30,14 +30,15 @@
|
|||
#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 )
|
||||
C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel,
|
||||
MATERIAL_MODE aMaterialMode )
|
||||
{
|
||||
m_ogl_idx_list_opaque = 0;
|
||||
m_ogl_idx_list_transparent = 0;
|
||||
m_ogl_idx_list_meshes = 0;
|
||||
m_nr_meshes = 0;
|
||||
m_meshs_bbox = NULL;
|
||||
|
||||
|
@ -55,7 +56,7 @@ C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel )
|
|||
m_meshs_bbox = new CBBOX[a3DModel.m_MeshesSize];
|
||||
|
||||
// Generate m_MeshesSize auxiliar lists to render the meshes
|
||||
GLuint m_ogl_idx_list_meshes = glGenLists( a3DModel.m_MeshesSize );
|
||||
m_ogl_idx_list_meshes = glGenLists( a3DModel.m_MeshesSize );
|
||||
|
||||
// Render each mesh of the model
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
|
@ -75,14 +76,18 @@ C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel )
|
|||
(mesh.m_FaceIdx != NULL) &&
|
||||
(mesh.m_FaceIdxSize > 0) && (mesh.m_VertexSize > 0) )
|
||||
{
|
||||
SFVEC4F *pColorRGBA = NULL;
|
||||
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 )
|
||||
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
|
||||
// /////////////////////////////////////////////////////////
|
||||
|
@ -107,22 +112,47 @@ C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel )
|
|||
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||
transparency = a3DModel.m_Materials[mesh.m_MaterialIdx].m_Transparency;
|
||||
|
||||
if( transparency > FLT_EPSILON )
|
||||
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 );
|
||||
pColorRGBA[i] = SFVEC4F( mesh.m_Color[i],
|
||||
1.0f - transparency );
|
||||
|
||||
// Load an RGBA array
|
||||
glColorPointer( 4, GL_FLOAT, 0, pColorRGBA );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else load the original RGB color array
|
||||
glColorPointer( 3, GL_FLOAT, 0, mesh.m_Color );
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,12 +182,29 @@ C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel )
|
|||
|
||||
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||
{
|
||||
OGL_SetMaterial( a3DModel.m_Materials[mesh.m_MaterialIdx] );
|
||||
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 );
|
||||
glDrawElements( GL_TRIANGLES, mesh.m_FaceIdxSize,
|
||||
GL_UNSIGNED_INT, mesh.m_FaceIdx );
|
||||
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
|
||||
|
@ -170,19 +217,22 @@ C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel )
|
|||
glDisableClientState( GL_NORMAL_ARRAY );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
glFinish();
|
||||
|
||||
delete [] pColorRGBA;
|
||||
}
|
||||
}
|
||||
}// for each mesh
|
||||
|
||||
bool have_opaque_meshes = false;
|
||||
bool have_transparent_meshes = false;
|
||||
|
||||
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 );
|
||||
|
||||
|
@ -198,12 +248,12 @@ C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel )
|
|||
|
||||
if( material.m_Transparency == 0.0f )
|
||||
{
|
||||
have_opaque_meshes = true; // Flag that we have at least one opaque mesh
|
||||
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
|
||||
have_transparent_meshes = true; // Flag that we found a transparent mesh
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +262,8 @@ C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel )
|
|||
|
||||
if( !have_opaque_meshes )
|
||||
{
|
||||
glDeleteLists( m_ogl_idx_list_opaque, 1 ); // If we dont have opaque meshes, we can free the list
|
||||
// If we dont have opaque meshes, we can free the list
|
||||
glDeleteLists( m_ogl_idx_list_opaque, 1 );
|
||||
m_ogl_idx_list_opaque = 0;
|
||||
}
|
||||
|
||||
|
@ -239,8 +290,9 @@ C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel )
|
|||
{
|
||||
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 ); // Render the transparent mesh
|
||||
glCallList( m_ogl_idx_list_meshes + mesh_i );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,6 +317,8 @@ C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel )
|
|||
|
||||
for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||
m_model_bbox.Union( m_meshs_bbox[mesh_i] );
|
||||
|
||||
glFinish();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -30,19 +30,21 @@
|
|||
#ifndef _C_OGL_3DMODEL_H_
|
||||
#define _C_OGL_3DMODEL_H_
|
||||
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
#include "common_ogl/openGL_includes.h"
|
||||
#include "3d_rendering/3d_render_raytracing/shapes3D/cbbox.h"
|
||||
#include <plugins/3dapi/c3dmodel.h>
|
||||
#include "../../common_ogl/openGL_includes.h"
|
||||
#include "../3d_render_raytracing/shapes3D/cbbox.h"
|
||||
#include "../../3d_enums.h"
|
||||
|
||||
///
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) C_OGL_3DMODEL
|
||||
///
|
||||
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 );
|
||||
C_OGL_3DMODEL( const S3DMODEL &a3DModel, MATERIAL_MODE aMaterialMode );
|
||||
|
||||
~C_OGL_3DMODEL();
|
||||
|
||||
|
@ -56,16 +58,6 @@ public:
|
|||
*/
|
||||
void Draw_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 Have_opaque - return true if have opaque meshs to render
|
||||
*/
|
||||
|
@ -76,6 +68,16 @@ public:
|
|||
*/
|
||||
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
|
||||
|
@ -83,13 +85,13 @@ public:
|
|||
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
|
||||
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
|
||||
CBBOX m_model_bbox; ///< global bounding box for this model
|
||||
CBBOX *m_meshs_bbox; ///< individual bbox for each mesh
|
||||
};
|
||||
|
||||
#endif // _C_OGL_3DMODEL_H_
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -29,10 +29,11 @@
|
|||
|
||||
|
||||
#include "clayer_triangles.h"
|
||||
#include <wx/debug.h> // For the wxASSERT
|
||||
#include <wx/debug.h> // For the wxASSERT
|
||||
|
||||
|
||||
CLAYER_TRIANGLE_CONTAINER::CLAYER_TRIANGLE_CONTAINER(unsigned int aNrReservedTriangles, bool aReserveNormals)
|
||||
CLAYER_TRIANGLE_CONTAINER::CLAYER_TRIANGLE_CONTAINER( unsigned int aNrReservedTriangles,
|
||||
bool aReserveNormals )
|
||||
{
|
||||
wxASSERT( aNrReservedTriangles > 0 );
|
||||
|
||||
|
@ -46,7 +47,20 @@ CLAYER_TRIANGLE_CONTAINER::CLAYER_TRIANGLE_CONTAINER(unsigned int aNrReservedTri
|
|||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLE_CONTAINER::AddQuad( const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3, const SFVEC3F &aV4 )
|
||||
void CLAYER_TRIANGLE_CONTAINER::Reserve_More( unsigned int aNrReservedTriangles,
|
||||
bool aReserveNormals )
|
||||
{
|
||||
m_vertexs.reserve( m_vertexs.size() + aNrReservedTriangles * 3 );
|
||||
|
||||
if( aReserveNormals )
|
||||
m_normals.reserve( m_normals.size() + aNrReservedTriangles * 3 );
|
||||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLE_CONTAINER::AddQuad( const SFVEC3F &aV1,
|
||||
const SFVEC3F &aV2,
|
||||
const SFVEC3F &aV3,
|
||||
const SFVEC3F &aV4 )
|
||||
{
|
||||
m_vertexs.push_back( aV1 );
|
||||
m_vertexs.push_back( aV2 );
|
||||
|
@ -58,7 +72,9 @@ void CLAYER_TRIANGLE_CONTAINER::AddQuad( const SFVEC3F &aV1, const SFVEC3F &aV2,
|
|||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLE_CONTAINER::AddTriangle( const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3 )
|
||||
void CLAYER_TRIANGLE_CONTAINER::AddTriangle( const SFVEC3F &aV1,
|
||||
const SFVEC3F &aV2,
|
||||
const SFVEC3F &aV3 )
|
||||
{
|
||||
m_vertexs.push_back( aV1 );
|
||||
m_vertexs.push_back( aV2 );
|
||||
|
@ -66,14 +82,19 @@ void CLAYER_TRIANGLE_CONTAINER::AddTriangle( const SFVEC3F &aV1, const SFVEC3F &
|
|||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLE_CONTAINER::AddNormal( const SFVEC3F &aN1, const SFVEC3F &aN2, const SFVEC3F &aN3 )
|
||||
void CLAYER_TRIANGLE_CONTAINER::AddNormal( const SFVEC3F &aN1,
|
||||
const SFVEC3F &aN2,
|
||||
const SFVEC3F &aN3 )
|
||||
{
|
||||
m_normals.push_back( aN1 );
|
||||
m_normals.push_back( aN2 );
|
||||
m_normals.push_back( aN3 );
|
||||
}
|
||||
|
||||
void CLAYER_TRIANGLE_CONTAINER::AddNormal( const SFVEC3F &aN1, const SFVEC3F &aN2, const SFVEC3F &aN3, const SFVEC3F &aN4 )
|
||||
void CLAYER_TRIANGLE_CONTAINER::AddNormal( const SFVEC3F &aN1,
|
||||
const SFVEC3F &aN2,
|
||||
const SFVEC3F &aN3,
|
||||
const SFVEC3F &aN4 )
|
||||
{
|
||||
m_normals.push_back( aN1 );
|
||||
m_normals.push_back( aN2 );
|
||||
|
@ -89,11 +110,16 @@ CLAYER_TRIANGLES::CLAYER_TRIANGLES( unsigned int aNrReservedTriangles )
|
|||
{
|
||||
wxASSERT( aNrReservedTriangles > 0 );
|
||||
|
||||
m_layer_top_segment_ends = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles, false );
|
||||
m_layer_top_triangles = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles, false );
|
||||
m_layer_middle_contourns_quads = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles, true );
|
||||
m_layer_bot_triangles = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles, false );
|
||||
m_layer_bot_segment_ends = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles, false );
|
||||
m_layer_top_segment_ends = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles,
|
||||
false );
|
||||
m_layer_top_triangles = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles,
|
||||
false );
|
||||
m_layer_middle_contourns_quads = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles,
|
||||
true );
|
||||
m_layer_bot_triangles = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles,
|
||||
false );
|
||||
m_layer_bot_segment_ends = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles,
|
||||
false );
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,11 +142,194 @@ CLAYER_TRIANGLES::~CLAYER_TRIANGLES()
|
|||
}
|
||||
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS::CLAYERS_OGL_DISP_LISTS(const CLAYER_TRIANGLES &aLayerTriangles,
|
||||
GLuint aTextureIndexForSegEnds,
|
||||
const SFVEC3F& aLayerColor )
|
||||
void CLAYER_TRIANGLES::AddToMiddleContourns( const std::vector< SFVEC2F > &aContournPoints,
|
||||
float zBot,
|
||||
float zTop,
|
||||
bool aInvertFaceDirection )
|
||||
{
|
||||
wxASSERT( glIsTexture( aTextureIndexForSegEnds ) );
|
||||
if( aContournPoints.size() > 4 )
|
||||
{
|
||||
// Calculate normals of each segment of the contourn
|
||||
std::vector< SFVEC2F > contournNormals;
|
||||
|
||||
contournNormals.clear();
|
||||
contournNormals.resize( aContournPoints.size() - 1 );
|
||||
|
||||
if( aInvertFaceDirection )
|
||||
{
|
||||
for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i )
|
||||
{
|
||||
const SFVEC2F &v0 = aContournPoints[i + 0];
|
||||
const SFVEC2F &v1 = aContournPoints[i + 1];
|
||||
|
||||
const SFVEC2F n = glm::normalize( v1 - v0 );
|
||||
|
||||
contournNormals[i] = SFVEC2F( n.y,-n.x );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i )
|
||||
{
|
||||
const SFVEC2F &v0 = aContournPoints[i + 0];
|
||||
const SFVEC2F &v1 = aContournPoints[i + 1];
|
||||
|
||||
const SFVEC2F n = glm::normalize( v1 - v0 );
|
||||
|
||||
contournNormals[i] = SFVEC2F( -n.y, n.x );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( aInvertFaceDirection )
|
||||
std::swap( zBot, zTop );
|
||||
|
||||
const unsigned int nContournsToProcess = ( aContournPoints.size() - 1 );
|
||||
|
||||
for( unsigned int i = 0; i < nContournsToProcess; ++i )
|
||||
{
|
||||
SFVEC2F lastNormal;
|
||||
|
||||
if( i > 0 )
|
||||
lastNormal = contournNormals[i - 1];
|
||||
else
|
||||
lastNormal = contournNormals[nContournsToProcess - 1];
|
||||
|
||||
SFVEC2F n0 = contournNormals[i];
|
||||
|
||||
// Only interpolate the normal if the angle is closer
|
||||
if( glm::dot( n0, lastNormal ) > 0.5f )
|
||||
n0 = glm::normalize( n0 + lastNormal );
|
||||
|
||||
SFVEC2F nextNormal;
|
||||
|
||||
if( i < (nContournsToProcess - 1) )
|
||||
nextNormal = contournNormals[i + 1];
|
||||
else
|
||||
nextNormal = contournNormals[0];
|
||||
|
||||
SFVEC2F n1 = contournNormals[i];
|
||||
|
||||
if( glm::dot( n1, nextNormal ) > 0.5f )
|
||||
n1 = glm::normalize( n1 + nextNormal );
|
||||
|
||||
const SFVEC3F n3d0 = SFVEC3F( n0.x, n0.y, 0.0f );
|
||||
const SFVEC3F n3d1 = SFVEC3F( n1.x, n1.y, 0.0f );
|
||||
|
||||
const SFVEC2F &v0 = aContournPoints[i + 0];
|
||||
const SFVEC2F &v1 = aContournPoints[i + 1];
|
||||
|
||||
#pragma omp critical
|
||||
{
|
||||
m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, zTop ),
|
||||
SFVEC3F( v1.x, v1.y, zTop ),
|
||||
SFVEC3F( v1.x, v1.y, zBot ),
|
||||
SFVEC3F( v0.x, v0.y, zBot ) );
|
||||
|
||||
m_layer_middle_contourns_quads->AddNormal( n3d0, n3d1, n3d1, n3d0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLES::AddToMiddleContourns( const SHAPE_LINE_CHAIN &outlinePath,
|
||||
float zBot,
|
||||
float zTop,
|
||||
double aBiuTo3Du,
|
||||
bool aInvertFaceDirection )
|
||||
{
|
||||
std::vector< SFVEC2F >contournPoints;
|
||||
|
||||
contournPoints.clear();
|
||||
contournPoints.reserve( outlinePath.PointCount() + 2 );
|
||||
|
||||
const VECTOR2I &firstV = outlinePath.CPoint( 0 );
|
||||
|
||||
SFVEC2F lastV = SFVEC2F( firstV.x * aBiuTo3Du,
|
||||
-firstV.y * aBiuTo3Du );
|
||||
|
||||
contournPoints.push_back( lastV );
|
||||
|
||||
for( unsigned int i = 1; i < (unsigned int)outlinePath.PointCount(); ++i )
|
||||
{
|
||||
const VECTOR2I & v = outlinePath.CPoint( i );
|
||||
|
||||
const SFVEC2F vf = SFVEC2F( v.x * aBiuTo3Du,
|
||||
-v.y * aBiuTo3Du );
|
||||
|
||||
if( vf != lastV ) // Do not add repeated points
|
||||
{
|
||||
lastV = vf;
|
||||
contournPoints.push_back( vf );
|
||||
}
|
||||
}
|
||||
|
||||
// Add first position fo the list to close the path
|
||||
if( lastV != contournPoints[0] )
|
||||
contournPoints.push_back( contournPoints[0] );
|
||||
|
||||
AddToMiddleContourns( contournPoints, zBot, zTop, aInvertFaceDirection );
|
||||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLES::AddToMiddleContourns( const SHAPE_POLY_SET &aPolySet,
|
||||
float zBot,
|
||||
float zTop,
|
||||
double aBiuTo3Du,
|
||||
bool aInvertFaceDirection )
|
||||
{
|
||||
wxASSERT( aPolySet.OutlineCount() > 0 );
|
||||
|
||||
if( aPolySet.OutlineCount() == 0 )
|
||||
return;
|
||||
|
||||
// Calculate an estimation of points to reserve
|
||||
unsigned int nrContournPointsToReserve = 0;
|
||||
|
||||
for( int i = 0; i < aPolySet.OutlineCount(); ++i )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN& pathOutline = aPolySet.COutline( i );
|
||||
|
||||
nrContournPointsToReserve += pathOutline.PointCount();
|
||||
|
||||
for( int h = 0; h < aPolySet.HoleCount( i ); ++h )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN &hole = aPolySet.CHole( i, h );
|
||||
|
||||
nrContournPointsToReserve += hole.PointCount();
|
||||
}
|
||||
}
|
||||
|
||||
// Request to reserve more space
|
||||
m_layer_middle_contourns_quads->Reserve_More( nrContournPointsToReserve * 2,
|
||||
true );
|
||||
|
||||
#pragma omp parallel for
|
||||
for( signed int i = 0; i < aPolySet.OutlineCount(); ++i )
|
||||
{
|
||||
// Add outline
|
||||
const SHAPE_LINE_CHAIN& pathOutline = aPolySet.COutline( i );
|
||||
|
||||
AddToMiddleContourns( pathOutline, zBot, zTop, aBiuTo3Du, aInvertFaceDirection );
|
||||
|
||||
// Add holes for this outline
|
||||
for( int h = 0; h < aPolySet.HoleCount( i ); ++h )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN &hole = aPolySet.CHole( i, h );
|
||||
AddToMiddleContourns( hole, zBot, zTop, aBiuTo3Du, aInvertFaceDirection );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS::CLAYERS_OGL_DISP_LISTS( const CLAYER_TRIANGLES &aLayerTriangles,
|
||||
GLuint aTextureIndexForSegEnds,
|
||||
float aZBot,
|
||||
float aZTop )
|
||||
{
|
||||
m_zBot = aZBot;
|
||||
m_zTop = aZTop;
|
||||
|
||||
m_layer_top_segment_ends = 0;
|
||||
m_layer_top_triangles = 0;
|
||||
|
@ -128,12 +337,41 @@ CLAYERS_OGL_DISP_LISTS::CLAYERS_OGL_DISP_LISTS(const CLAYER_TRIANGLES &aLayerTri
|
|||
m_layer_bot_triangles = 0;
|
||||
m_layer_bot_segment_ends = 0;
|
||||
|
||||
m_layer_top_segment_ends = generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_top_segment_ends, aLayerColor, true, aTextureIndexForSegEnds );
|
||||
m_layer_top_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_top_triangles, aLayerColor, true );
|
||||
m_layer_bot_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_bot_triangles, aLayerColor, false );
|
||||
m_layer_bot_segment_ends = generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_bot_segment_ends, aLayerColor, false, aTextureIndexForSegEnds );
|
||||
if( aTextureIndexForSegEnds )
|
||||
{
|
||||
wxASSERT( glIsTexture( aTextureIndexForSegEnds ) );
|
||||
|
||||
m_layer_middle_contourns_quads = generate_middle_triangles( aLayerTriangles.m_layer_middle_contourns_quads, aLayerColor );
|
||||
if( glIsTexture( aTextureIndexForSegEnds ) )
|
||||
{
|
||||
m_layer_top_segment_ends =
|
||||
generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_top_segment_ends,
|
||||
true,
|
||||
aTextureIndexForSegEnds );
|
||||
|
||||
m_layer_bot_segment_ends =
|
||||
generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_bot_segment_ends,
|
||||
false,
|
||||
aTextureIndexForSegEnds );
|
||||
}
|
||||
}
|
||||
|
||||
m_layer_top_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_top_triangles,
|
||||
true );
|
||||
|
||||
m_layer_bot_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_bot_triangles,
|
||||
false );
|
||||
|
||||
|
||||
if( aLayerTriangles.m_layer_middle_contourns_quads->GetVertexSize() > 0 )
|
||||
{
|
||||
m_layer_middle_contourns_quads =
|
||||
generate_middle_triangles( aLayerTriangles.m_layer_middle_contourns_quads );
|
||||
}
|
||||
|
||||
m_draw_it_transparent = false;
|
||||
m_haveTransformation = false;
|
||||
m_zPositionTransformation = 0.0f;
|
||||
m_zScaleTransformation = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
|
@ -153,73 +391,99 @@ CLAYERS_OGL_DISP_LISTS::~CLAYERS_OGL_DISP_LISTS()
|
|||
|
||||
if( glIsList( m_layer_bot_segment_ends ) )
|
||||
glDeleteLists( m_layer_bot_segment_ends, 1 );
|
||||
|
||||
m_layer_top_segment_ends = 0;
|
||||
m_layer_top_triangles = 0;
|
||||
m_layer_middle_contourns_quads = 0;
|
||||
m_layer_bot_triangles = 0;
|
||||
m_layer_bot_segment_ends = 0;
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawTopAndMiddle() const
|
||||
{
|
||||
if( glIsList( m_layer_top_triangles ) )
|
||||
glCallList( m_layer_top_triangles );
|
||||
beginTransformation();
|
||||
|
||||
if( glIsList( m_layer_middle_contourns_quads ) )
|
||||
glCallList( m_layer_middle_contourns_quads );
|
||||
|
||||
if( glIsList( m_layer_top_triangles ) )
|
||||
glCallList( m_layer_top_triangles );
|
||||
|
||||
if( glIsList( m_layer_top_segment_ends ) )
|
||||
glCallList( m_layer_top_segment_ends );
|
||||
|
||||
endTransformation();
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawBotAndMiddle() const
|
||||
{
|
||||
if( glIsList( m_layer_bot_triangles ) )
|
||||
glCallList( m_layer_bot_triangles );
|
||||
beginTransformation();
|
||||
|
||||
if( glIsList( m_layer_middle_contourns_quads ) )
|
||||
glCallList( m_layer_middle_contourns_quads );
|
||||
|
||||
if( glIsList( m_layer_bot_triangles ) )
|
||||
glCallList( m_layer_bot_triangles );
|
||||
|
||||
if( glIsList( m_layer_bot_segment_ends ) )
|
||||
glCallList( m_layer_bot_segment_ends );
|
||||
|
||||
endTransformation();
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawTop() const
|
||||
{
|
||||
beginTransformation();
|
||||
|
||||
if( glIsList( m_layer_top_triangles ) )
|
||||
glCallList( m_layer_top_triangles );
|
||||
|
||||
if( glIsList( m_layer_top_segment_ends ) )
|
||||
glCallList( m_layer_top_segment_ends );
|
||||
|
||||
endTransformation();
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawBot() const
|
||||
{
|
||||
beginTransformation();
|
||||
|
||||
if( glIsList( m_layer_bot_triangles ) )
|
||||
glCallList( m_layer_bot_triangles );
|
||||
|
||||
if( glIsList( m_layer_bot_segment_ends ) )
|
||||
glCallList( m_layer_bot_segment_ends );
|
||||
|
||||
endTransformation();
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawMiddle() const
|
||||
{
|
||||
beginTransformation();
|
||||
|
||||
if( glIsList( m_layer_middle_contourns_quads ) )
|
||||
glCallList( m_layer_middle_contourns_quads );
|
||||
|
||||
endTransformation();
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawAll() const
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawAll( bool aDrawMiddle ) const
|
||||
{
|
||||
beginTransformation();
|
||||
|
||||
if( aDrawMiddle )
|
||||
if( glIsList( m_layer_middle_contourns_quads ) )
|
||||
glCallList( m_layer_middle_contourns_quads );
|
||||
|
||||
if( glIsList( m_layer_top_triangles ) )
|
||||
glCallList( m_layer_top_triangles );
|
||||
|
||||
if( glIsList( m_layer_middle_contourns_quads ) )
|
||||
glCallList( m_layer_middle_contourns_quads );
|
||||
|
||||
if( glIsList( m_layer_bot_triangles ) )
|
||||
glCallList( m_layer_bot_triangles );
|
||||
|
||||
|
@ -229,15 +493,162 @@ void CLAYERS_OGL_DISP_LISTS::DrawAll() const
|
|||
if( glIsList( m_layer_bot_segment_ends ) )
|
||||
glCallList( m_layer_bot_segment_ends );
|
||||
|
||||
endTransformation();
|
||||
}
|
||||
|
||||
|
||||
GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_seg_ends(const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer, const SFVEC3F &aLayerColor, bool aIsNormalUp, GLuint aTextureId ) const
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawAllCameraCulled(float zCameraPos, bool aDrawMiddle ) const
|
||||
{
|
||||
zCameraPos = m_haveTransformation?( (zCameraPos - m_zPositionTransformation ) /
|
||||
m_zScaleTransformation ):zCameraPos;
|
||||
|
||||
if( aDrawMiddle )
|
||||
DrawMiddle();
|
||||
|
||||
if( zCameraPos > m_zTop )
|
||||
{
|
||||
DrawTop();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( zCameraPos < m_zBot )
|
||||
{
|
||||
DrawBot();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If camera is in the middle dont draw it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawAllCameraCulledSubtractLayer(
|
||||
const CLAYERS_OGL_DISP_LISTS *aLayerToSubtractA,
|
||||
const CLAYERS_OGL_DISP_LISTS *aLayerToSubtractB,
|
||||
bool aDrawMiddle ) const
|
||||
{
|
||||
if( aDrawMiddle )
|
||||
DrawMiddle();
|
||||
|
||||
glClearStencil( 0x00 );
|
||||
glClear( GL_STENCIL_BUFFER_BIT );
|
||||
|
||||
glEnable( GL_CULL_FACE );
|
||||
glCullFace( GL_BACK );
|
||||
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
|
||||
glDepthMask( GL_FALSE );
|
||||
glEnable( GL_STENCIL_TEST );
|
||||
glStencilFunc( GL_ALWAYS, 1, 0 );
|
||||
glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
|
||||
|
||||
if( aLayerToSubtractA )
|
||||
aLayerToSubtractA->DrawBot();
|
||||
|
||||
if( aLayerToSubtractB )
|
||||
aLayerToSubtractB->DrawBot();
|
||||
|
||||
|
||||
//if( !m_draw_it_transparent )
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
glStencilFunc( GL_EQUAL, 0, 1 );
|
||||
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
|
||||
DrawBot();
|
||||
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
|
||||
glDepthMask( GL_FALSE );
|
||||
glEnable( GL_STENCIL_TEST );
|
||||
glStencilFunc( GL_ALWAYS, 2, 0 );
|
||||
glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
|
||||
|
||||
if( aLayerToSubtractA )
|
||||
aLayerToSubtractA->DrawTop();
|
||||
|
||||
if( aLayerToSubtractB )
|
||||
aLayerToSubtractB->DrawTop();
|
||||
|
||||
//if( !m_draw_it_transparent )
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
glStencilFunc( GL_NOTEQUAL, 2, 0x03 );
|
||||
glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
|
||||
DrawTop();
|
||||
|
||||
|
||||
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );
|
||||
|
||||
glCullFace( GL_FRONT );
|
||||
glStencilFunc( GL_GEQUAL, 3, 0x03 );
|
||||
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
|
||||
if( aDrawMiddle )
|
||||
{
|
||||
if( aLayerToSubtractA )
|
||||
aLayerToSubtractA->DrawMiddle();
|
||||
|
||||
// It will not render the middle contours of the layer.
|
||||
// It is used with vias and holes (copper vias and to subtract solder
|
||||
// mask holes). But since in the vias, it will draw a cylinder
|
||||
// and in soldermask it doesn't need to draw the contour.
|
||||
// so it is not used the middle part of B
|
||||
// if( aLayerToSubtractB )
|
||||
// aLayerToSubtractB->DrawMiddle();
|
||||
}
|
||||
|
||||
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
|
||||
|
||||
glCullFace( GL_BACK );
|
||||
glDisable( GL_STENCIL_TEST );
|
||||
|
||||
/*
|
||||
if( m_draw_it_transparent )
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::ApplyScalePosition( float aZposition,
|
||||
float aZscale )
|
||||
{
|
||||
wxASSERT( aZscale > FLT_EPSILON );
|
||||
|
||||
m_zPositionTransformation = aZposition;
|
||||
m_zScaleTransformation = aZscale;
|
||||
m_haveTransformation = true;
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::SetItIsTransparent( bool aSetTransparent )
|
||||
{
|
||||
m_draw_it_transparent = aSetTransparent;
|
||||
}
|
||||
|
||||
|
||||
GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_seg_ends(
|
||||
const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer,
|
||||
bool aIsNormalUp,
|
||||
GLuint aTextureId ) const
|
||||
{
|
||||
wxASSERT( aTriangleContainer != NULL );
|
||||
|
||||
wxASSERT( (aTriangleContainer->GetVertexSize() % 3) == 0 );
|
||||
|
||||
// Top and Bot dont have normals array stored in container
|
||||
wxASSERT( aTriangleContainer->GetNormalsSize() == 0 );
|
||||
|
||||
if( (aTriangleContainer->GetVertexSize() > 0) &&
|
||||
|
@ -250,7 +661,9 @@ GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_seg_ends(const CLAYER_TRIANGL
|
|||
// Prepare an array of UV text coordinates
|
||||
SFVEC2F *uvArray = new SFVEC2F[aTriangleContainer->GetVertexSize()];
|
||||
|
||||
for( unsigned int i = 0; i < aTriangleContainer->GetVertexSize(); i += 3 )
|
||||
for( unsigned int i = 0;
|
||||
i < aTriangleContainer->GetVertexSize();
|
||||
i += 3 )
|
||||
{
|
||||
uvArray[i + 0] = SFVEC2F( 1.0f, 0.0f );
|
||||
uvArray[i + 1] = SFVEC2F( 0.0f, 1.0f );
|
||||
|
@ -266,22 +679,16 @@ GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_seg_ends(const CLAYER_TRIANGL
|
|||
|
||||
glNewList( listIdx, GL_COMPILE );
|
||||
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
glBindTexture( GL_TEXTURE_2D, aTextureId );
|
||||
|
||||
glAlphaFunc( GL_GREATER, 0.60f );
|
||||
setBlendfunction();
|
||||
|
||||
glAlphaFunc( GL_GREATER, 0.2f );
|
||||
glEnable( GL_ALPHA_TEST );
|
||||
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
//SFVEC4F layerColor4 = SFVEC4F( aLayerColor.x, aLayerColor.y, aLayerColor.z, 1.0f );
|
||||
//glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, &layerColor4.x );
|
||||
//glDisable( GL_COLOR_MATERIAL );
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColor4f( aLayerColor.x, aLayerColor.y, aLayerColor.z, 1.0f );
|
||||
|
||||
// OGL_SetMaterial()
|
||||
glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f );
|
||||
|
||||
glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
|
||||
|
@ -289,7 +696,6 @@ GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_seg_ends(const CLAYER_TRIANGL
|
|||
glDisable( GL_TEXTURE_2D );
|
||||
glDisable( GL_ALPHA_TEST );
|
||||
glDisable( GL_BLEND );
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
|
||||
glEndList();
|
||||
|
||||
|
@ -305,18 +711,21 @@ GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_seg_ends(const CLAYER_TRIANGL
|
|||
}
|
||||
|
||||
|
||||
GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_triangles(const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer, const SFVEC3F &aLayerColor , bool aIsNormalUp) const
|
||||
GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_triangles(
|
||||
const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer,
|
||||
bool aIsNormalUp ) const
|
||||
{
|
||||
wxASSERT( aTriangleContainer != NULL );
|
||||
|
||||
wxASSERT( (aTriangleContainer->GetVertexSize() % 3) == 0 );
|
||||
|
||||
// Top and Bot dont have normals array stored in container
|
||||
wxASSERT( aTriangleContainer->GetNormalsSize() == 0 );
|
||||
|
||||
if( (aTriangleContainer->GetVertexSize() > 0) &&
|
||||
((aTriangleContainer->GetVertexSize() % 3) == 0) )
|
||||
( (aTriangleContainer->GetVertexSize() % 3) == 0) )
|
||||
{
|
||||
GLuint listIdx = glGenLists( 1 );
|
||||
const GLuint listIdx = glGenLists( 1 );
|
||||
|
||||
if( glIsList( listIdx ) )
|
||||
{
|
||||
|
@ -328,35 +737,13 @@ GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_triangles(const CLAYER_TRIANG
|
|||
|
||||
glNewList( listIdx, GL_COMPILE );
|
||||
|
||||
//SFVEC4F layerColor4 = SFVEC4F( aLayerColor.x, aLayerColor.y, aLayerColor.z, 1.0f );
|
||||
//glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, &layerColor4.x );
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColor4f( aLayerColor.x, aLayerColor.y, aLayerColor.z, 1.0f );
|
||||
setBlendfunction();
|
||||
|
||||
// OGL_SetMaterial()
|
||||
glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f );
|
||||
|
||||
glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
|
||||
/*
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColor3f( 0.0,1.0,1.0);
|
||||
for( unsigned int i=0; i < aTriangleContainer->GetVertexSize(); ++i )
|
||||
{
|
||||
const SFVEC3F &v1 = aTriangleContainer->GetVertexPointer()[ i * 3];
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f( v1.x, v1.y, v1.z );
|
||||
if( aIsNormalUp )
|
||||
{
|
||||
glVertex3f( v1.x, v1.y, v1.z+1.0f*.0051f );
|
||||
}
|
||||
else
|
||||
{
|
||||
glVertex3f( v1.x, v1.y, v1.z-1.0f*.0051f );
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
*/
|
||||
glDisable( GL_BLEND );
|
||||
glEndList();
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
@ -368,7 +755,9 @@ GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_triangles(const CLAYER_TRIANG
|
|||
return 0;
|
||||
}
|
||||
|
||||
GLuint CLAYERS_OGL_DISP_LISTS::generate_middle_triangles( const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer, const SFVEC3F &aLayerColor ) const
|
||||
|
||||
GLuint CLAYERS_OGL_DISP_LISTS::generate_middle_triangles(
|
||||
const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer ) const
|
||||
{
|
||||
wxASSERT( aTriangleContainer != NULL );
|
||||
|
||||
|
@ -387,7 +776,7 @@ GLuint CLAYERS_OGL_DISP_LISTS::generate_middle_triangles( const CLAYER_TRIANGLE_
|
|||
( (aTriangleContainer->GetVertexSize() % 6) == 0 ) &&
|
||||
( aTriangleContainer->GetNormalsSize() == aTriangleContainer->GetVertexSize() ) )
|
||||
{
|
||||
GLuint listIdx = glGenLists( 1 );
|
||||
const GLuint listIdx = glGenLists( 1 );
|
||||
|
||||
if( glIsList( listIdx ) )
|
||||
{
|
||||
|
@ -399,34 +788,12 @@ GLuint CLAYERS_OGL_DISP_LISTS::generate_middle_triangles( const CLAYER_TRIANGLE_
|
|||
glNormalPointer( GL_FLOAT, 0, aTriangleContainer->GetNormalsPointer() );
|
||||
|
||||
glNewList( listIdx, GL_COMPILE );
|
||||
/*
|
||||
const SFVEC4F specular = SFVEC4F( 0.5f, 0.5f, 0.5f, 1.0f );
|
||||
|
||||
glMaterialfv( GL_FRONT, GL_SPECULAR, &specular.r );
|
||||
glMaterialf( GL_FRONT, GL_SHININESS, 10.0f );*/
|
||||
|
||||
//SFVEC4F layerColor4 = SFVEC4F( aLayerColor.x, aLayerColor.y, aLayerColor.z, 1.0f );
|
||||
//glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, &layerColor4.x );
|
||||
//glDisable( GL_COLOR_MATERIAL );
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColor4f( aLayerColor.x, aLayerColor.y, aLayerColor.z, 1.0f );
|
||||
|
||||
// OGL_SetMaterial()
|
||||
setBlendfunction();
|
||||
|
||||
glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
|
||||
/*
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColor3f( 1.0,0.0,1.0);
|
||||
for( unsigned int i=0; i < aTriangleContainer->GetVertexSize() / 3 ; ++i )
|
||||
{
|
||||
const SFVEC3F &v1 = ((const SFVEC3F*)aTriangleContainer->GetVertexPointer())[i * 3];
|
||||
const SFVEC3F &n1 = ((const SFVEC3F*)aTriangleContainer->GetNormalsPointer())[i * 3];
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f( v1.x, v1.y, v1.z );
|
||||
glVertex3f( v1.x+n1.x*.01f, v1.y+n1.y*.01f, v1.z+n1.z*.01f );
|
||||
glEnd();
|
||||
}
|
||||
*/
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
glEndList();
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
@ -439,3 +806,29 @@ GLuint CLAYERS_OGL_DISP_LISTS::generate_middle_triangles( const CLAYER_TRIANGLE_
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::endTransformation() const
|
||||
{
|
||||
if( m_haveTransformation )
|
||||
{
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::setBlendfunction() const
|
||||
{
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::beginTransformation() const
|
||||
{
|
||||
if( m_haveTransformation )
|
||||
{
|
||||
glPushMatrix();
|
||||
glTranslatef( 0.0f, 0.0f, m_zPositionTransformation );
|
||||
glScalef( 1.0f, 1.0f, m_zScaleTransformation );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -30,8 +30,10 @@
|
|||
#ifndef CLAYER_TRIANGLES_H_
|
||||
#define CLAYER_TRIANGLES_H_
|
||||
|
||||
#include "common_ogl/openGL_includes.h"
|
||||
#include "plugins/3dapi/xv3d_types.h"
|
||||
#include "../../common_ogl/openGL_includes.h"
|
||||
#include <plugins/3dapi/xv3d_types.h>
|
||||
#include <geometry/shape_line_chain.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
@ -49,10 +51,17 @@ public:
|
|||
/**
|
||||
* @brief CLAYER_TRIANGLE_CONTAINER
|
||||
* @param aNrReservedTriangles: number of triangles expected to be used
|
||||
* @param aReserveNormals: if you will use normals, set it to bool to pre reserve space
|
||||
* @param aReserveNormals: if you will use normals, set it to bool to pre
|
||||
* reserve space
|
||||
*/
|
||||
CLAYER_TRIANGLE_CONTAINER( unsigned int aNrReservedTriangles, bool aReserveNormals );
|
||||
|
||||
/**
|
||||
* @brief Reserve_More - reserve more triangles
|
||||
*
|
||||
*/
|
||||
void Reserve_More( unsigned int aNrReservedTriangles, bool aReserveNormals );
|
||||
|
||||
/**
|
||||
* @brief AddTriangle
|
||||
* @param aV1
|
||||
|
@ -68,7 +77,10 @@ public:
|
|||
* @param aV3
|
||||
* @param aV4
|
||||
*/
|
||||
void AddQuad( const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3, const SFVEC3F &aV4 );
|
||||
void AddQuad( const SFVEC3F &aV1,
|
||||
const SFVEC3F &aV2,
|
||||
const SFVEC3F &aV3,
|
||||
const SFVEC3F &aV4 );
|
||||
|
||||
/**
|
||||
* @brief AddNormal
|
||||
|
@ -84,7 +96,10 @@ public:
|
|||
* @param aN2
|
||||
* @param aN3
|
||||
*/
|
||||
void AddNormal( const SFVEC3F &aN1, const SFVEC3F &aN2, const SFVEC3F &aN3, const SFVEC3F &aN4 );
|
||||
void AddNormal( const SFVEC3F &aN1,
|
||||
const SFVEC3F &aN2,
|
||||
const SFVEC3F &aN3,
|
||||
const SFVEC3F &aN4 );
|
||||
|
||||
/**
|
||||
* @brief GetVertexPointer - Get the array of vertexes
|
||||
|
@ -102,17 +117,17 @@ public:
|
|||
* @brief GetVertexSize
|
||||
* @return
|
||||
*/
|
||||
unsigned int GetVertexSize() const { return m_vertexs.size(); }
|
||||
unsigned int GetVertexSize() const { return (unsigned int)m_vertexs.size(); }
|
||||
|
||||
/**
|
||||
* @brief GetNormalsSize
|
||||
* @return
|
||||
*/
|
||||
unsigned int GetNormalsSize() const { return m_normals.size(); }
|
||||
unsigned int GetNormalsSize() const { return (unsigned int)m_normals.size(); }
|
||||
|
||||
private:
|
||||
SFVEC3F_VECTOR m_vertexs; ///< vertex array
|
||||
SFVEC3F_VECTOR m_normals; ///< normals array
|
||||
SFVEC3F_VECTOR m_vertexs; ///< vertex array
|
||||
SFVEC3F_VECTOR m_normals; ///< normals array
|
||||
};
|
||||
|
||||
|
||||
|
@ -127,7 +142,7 @@ public:
|
|||
* @brief CLAYER_TRIANGLES - initialize arrays with reserved triangles
|
||||
* @param aNrReservedTriangles: number of pre alloc triangles to reserve
|
||||
*/
|
||||
CLAYER_TRIANGLES( unsigned int aNrReservedTriangles );
|
||||
explicit CLAYER_TRIANGLES( unsigned int aNrReservedTriangles );
|
||||
|
||||
/**
|
||||
* @brief ~CLAYER_TRIANGLES - Free containers
|
||||
|
@ -135,11 +150,30 @@ public:
|
|||
~CLAYER_TRIANGLES();
|
||||
|
||||
/**
|
||||
* @brief IsLayersSizeValid - check if the vertex arrays of the layers are as expected
|
||||
* @brief IsLayersSizeValid - check if the vertex arrays of the layers are
|
||||
* as expected
|
||||
* @return TRUE if layers are correctly setup
|
||||
*/
|
||||
bool IsLayersSizeValid();
|
||||
|
||||
|
||||
void AddToMiddleContourns( const SHAPE_LINE_CHAIN &outlinePath,
|
||||
float zBot,
|
||||
float zTop,
|
||||
double aBiuTo3Du,
|
||||
bool aInvertFaceDirection );
|
||||
|
||||
void AddToMiddleContourns( const SHAPE_POLY_SET &aPolySet,
|
||||
float zBot,
|
||||
float zTop,
|
||||
double aBiuTo3Du,
|
||||
bool aInvertFaceDirection );
|
||||
|
||||
void AddToMiddleContourns( const std::vector< SFVEC2F > &aContournPoints,
|
||||
float zBot,
|
||||
float zTop,
|
||||
bool aInvertFaceDirection );
|
||||
|
||||
CLAYER_TRIANGLE_CONTAINER *m_layer_top_segment_ends;
|
||||
CLAYER_TRIANGLE_CONTAINER *m_layer_top_triangles;
|
||||
CLAYER_TRIANGLE_CONTAINER *m_layer_middle_contourns_quads;
|
||||
|
@ -157,25 +191,33 @@ class CLAYERS_OGL_DISP_LISTS
|
|||
public:
|
||||
/**
|
||||
* @brief CLAYERS_OGL_DISP_LISTS - Creates the display lists for a layer
|
||||
* @param aLayerTriangles: contains the layers array of vertex to render to display lists
|
||||
* @param aTextureIndexForSegEnds: texture index to be used by segment ends. It is a black and white squared texture with a center circle diameter of the size of the texture.
|
||||
* @param aLayerTriangles: contains the layers array of vertex to render to
|
||||
* display lists
|
||||
* @param aTextureIndexForSegEnds: texture index to be used by segment ends.
|
||||
* It is a black and white squared texture
|
||||
* with a center circle diameter of the size
|
||||
* of the texture.
|
||||
*/
|
||||
CLAYERS_OGL_DISP_LISTS( const CLAYER_TRIANGLES &aLayerTriangles,
|
||||
GLuint aTextureIndexForSegEnds,
|
||||
const SFVEC3F& aLayerColor );
|
||||
float aZBot,
|
||||
float aZTop );
|
||||
|
||||
/**
|
||||
* @brief ~CLAYERS_OGL_DISP_LISTS - Destroy this class while free the display lists from GPU mem
|
||||
* @brief ~CLAYERS_OGL_DISP_LISTS - Destroy this class while free the display
|
||||
* lists from GPU mem
|
||||
*/
|
||||
~CLAYERS_OGL_DISP_LISTS();
|
||||
|
||||
/**
|
||||
* @brief DrawTopAndMiddle - This function calls the display lists for the top elements and middle contourns
|
||||
* @brief DrawTopAndMiddle - This function calls the display lists for the
|
||||
* top elements and middle contourns
|
||||
*/
|
||||
void DrawTopAndMiddle() const;
|
||||
|
||||
/**
|
||||
* @brief DrawBotAndMiddle - This function calls the display lists for the botton elements and middle contourns
|
||||
* @brief DrawBotAndMiddle - This function calls the display lists for the
|
||||
* botton elements and middle contourns
|
||||
*/
|
||||
void DrawBotAndMiddle() const;
|
||||
|
||||
|
@ -190,26 +232,66 @@ public:
|
|||
void DrawBot() const;
|
||||
|
||||
/**
|
||||
* @brief DrawMiddle - This function calls the display lists for the middle elements
|
||||
* @brief DrawMiddle - This function calls the display lists for the middle
|
||||
* elements
|
||||
*/
|
||||
void DrawMiddle() const;
|
||||
|
||||
/**
|
||||
* @brief DrawAll - This function calls all the display lists
|
||||
*/
|
||||
void DrawAll() const;
|
||||
void DrawAll( bool aDrawMiddle = true ) const;
|
||||
|
||||
/**
|
||||
* @brief DrawAllCameraCulled - Draw all layers if they are visible by the camera.
|
||||
* i.e.: if camera position is above the layer. This only works because the
|
||||
* board is centered and the planes are always perpendicular to the Z axis.
|
||||
* @param zCameraPos: camera z position
|
||||
*/
|
||||
void DrawAllCameraCulled( float zCameraPos, bool aDrawMiddle = true ) const;
|
||||
|
||||
void DrawAllCameraCulledSubtractLayer( const CLAYERS_OGL_DISP_LISTS *aLayerToSubtractA,
|
||||
const CLAYERS_OGL_DISP_LISTS *aLayerToSubtractB,
|
||||
bool aDrawMiddle = true ) const;
|
||||
|
||||
void ApplyScalePosition( float aZposition, float aZscale );
|
||||
|
||||
void ClearScalePosition() { m_haveTransformation = false; }
|
||||
|
||||
void SetItIsTransparent( bool aSetTransparent );
|
||||
|
||||
float GetZBot() const { return m_zBot; }
|
||||
float GetZTop() const { return m_zTop; }
|
||||
|
||||
private:
|
||||
GLuint generate_top_or_bot_seg_ends(const CLAYER_TRIANGLE_CONTAINER * aTriangleContainer, const SFVEC3F& aLayerColor, bool aIsNormalUp , GLuint aTextureId ) const;
|
||||
GLuint generate_top_or_bot_triangles( const CLAYER_TRIANGLE_CONTAINER * aTriangleContainer, const SFVEC3F& aLayerColor, bool aIsNormalUp ) const;
|
||||
GLuint generate_middle_triangles( const CLAYER_TRIANGLE_CONTAINER * aTriangleContainer, const SFVEC3F& aLayerColor ) const;
|
||||
GLuint generate_top_or_bot_seg_ends( const CLAYER_TRIANGLE_CONTAINER * aTriangleContainer,
|
||||
bool aIsNormalUp,
|
||||
GLuint aTextureId ) const;
|
||||
|
||||
GLuint generate_top_or_bot_triangles( const CLAYER_TRIANGLE_CONTAINER * aTriangleContainer,
|
||||
bool aIsNormalUp ) const;
|
||||
|
||||
GLuint generate_middle_triangles( const CLAYER_TRIANGLE_CONTAINER * aTriangleContainer ) const;
|
||||
|
||||
void beginTransformation() const;
|
||||
void endTransformation() const;
|
||||
|
||||
void setBlendfunction() const;
|
||||
|
||||
private:
|
||||
GLuint m_layer_top_segment_ends;
|
||||
GLuint m_layer_top_triangles;
|
||||
GLuint m_layer_middle_contourns_quads;
|
||||
GLuint m_layer_bot_triangles;
|
||||
GLuint m_layer_bot_segment_ends;
|
||||
float m_zBot;
|
||||
float m_zTop;
|
||||
GLuint m_layer_top_segment_ends;
|
||||
GLuint m_layer_top_triangles;
|
||||
GLuint m_layer_middle_contourns_quads;
|
||||
GLuint m_layer_bot_triangles;
|
||||
GLuint m_layer_bot_segment_ends;
|
||||
|
||||
bool m_haveTransformation;
|
||||
float m_zPositionTransformation;
|
||||
float m_zScaleTransformation;
|
||||
|
||||
bool m_draw_it_transparent;
|
||||
};
|
||||
|
||||
#endif // CLAYER_TRIANGLES_H_
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -28,10 +28,10 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "common_ogl/openGL_includes.h"
|
||||
#include "../../common_ogl/openGL_includes.h"
|
||||
#include "ogl_legacy_utils.h"
|
||||
#include <trigo.h>
|
||||
#include <wx/debug.h> // For the wxASSERT
|
||||
#include <wx/debug.h> // For the wxASSERT
|
||||
|
||||
#define RADPERDEG 0.0174533
|
||||
|
||||
|
@ -50,8 +50,12 @@ void OGL_draw_arrow( SFVEC3F aPosition, SFVEC3F aTargetPos, float aSize )
|
|||
|
||||
if( ( vec.x != 0.0f ) || ( vec.y != 0.0f ) )
|
||||
{
|
||||
glRotatef( atan2(vec.y, vec.x) / RADPERDEG, 0.0f, 0.0f, 1.0f );
|
||||
glRotatef( atan2(sqrt(vec.x * vec.x + vec.y * vec.y), vec.z) / RADPERDEG, 0.0f, 1.0f, 0.0f );
|
||||
glRotatef( atan2( vec.y, vec.x ) / RADPERDEG, 0.0f, 0.0f, 1.0f );
|
||||
glRotatef( atan2( sqrt( vec.x * vec.x + vec.y * vec.y ), vec.z ) / RADPERDEG,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f );
|
||||
|
||||
} else if( vec.z < 0.0f )
|
||||
{
|
||||
glRotatef( 180.0f, 1.0f, 0.0f, 0.0f );
|
||||
|
@ -87,8 +91,8 @@ void OGL_draw_arrow( SFVEC3F aPosition, SFVEC3F aTargetPos, float aSize )
|
|||
glTranslatef( 0.0f , 0.0f ,-length + 4.0f * aSize );
|
||||
|
||||
quadObj = gluNewQuadric();
|
||||
gluQuadricDrawStyle(quadObj, GLU_FILL );
|
||||
gluQuadricNormals(quadObj, GLU_SMOOTH );
|
||||
gluQuadricDrawStyle( quadObj, GLU_FILL );
|
||||
gluQuadricNormals( quadObj, GLU_SMOOTH );
|
||||
gluCylinder( quadObj, aSize, aSize, length - 4.0 * aSize, 12, 1 );
|
||||
gluDeleteQuadric( quadObj );
|
||||
/*
|
||||
|
@ -154,45 +158,53 @@ void OGL_draw_half_open_cylinder( unsigned int aNrSidesPerCircle )
|
|||
{
|
||||
if( aNrSidesPerCircle > 1 )
|
||||
{
|
||||
float radius = 0.5f;
|
||||
int delta = 3600 / aNrSidesPerCircle;
|
||||
const float radius = 0.5f;
|
||||
const int delta = 3600 / aNrSidesPerCircle;
|
||||
|
||||
// Generate bottom
|
||||
glNormal3f( 0.0f, 0.0f,-1.0f );
|
||||
glBegin( GL_TRIANGLE_FAN );
|
||||
glVertex3f( 0.0, 0.0, 0.0 ); // This is the V0 of the FAN
|
||||
glVertex3f( 0.0, 0.0, 0.0 ); // This is the V0 of the FAN
|
||||
|
||||
for( int ii = 0; ii < 1800; ii += delta )
|
||||
{
|
||||
SFVEC2D corner = SFVEC2D( 0.0, radius );
|
||||
RotatePoint( &corner.x, &corner.y, ii );
|
||||
glVertex3f( corner.x, corner.y, 0.0 );
|
||||
}
|
||||
|
||||
glVertex3d( 0.0, -radius, 0.0 );
|
||||
glEnd();
|
||||
|
||||
// Generate top
|
||||
glNormal3f( 0.0f, 0.0f, 1.0f );
|
||||
glBegin( GL_TRIANGLE_FAN );
|
||||
glVertex3f( 0.0, 0.0, 1.0 ); // This is the V0 of the FAN
|
||||
glVertex3f( 0.0, 0.0, 1.0 ); // This is the V0 of the FAN
|
||||
|
||||
for( int ii = 1800; ii > 0; ii -= delta )
|
||||
{
|
||||
SFVEC2D corner = SFVEC2D( 0.0, radius );
|
||||
|
||||
RotatePoint( &corner.x, &corner.y, ii );
|
||||
glVertex3f( corner.x, corner.y, 1.0 );
|
||||
}
|
||||
|
||||
glVertex3f( 0.0, radius, 1.0 );
|
||||
glEnd();
|
||||
|
||||
// Generate contours
|
||||
glBegin( GL_QUAD_STRIP );
|
||||
|
||||
for( int ii = 1800; ii > 0; ii -= delta )
|
||||
{
|
||||
SFVEC2D corner = SFVEC2D( 0.0, radius );
|
||||
|
||||
RotatePoint( &corner.x, &corner.y, ii );
|
||||
glNormal3f( corner.x * 2.0f, corner.y * 2.0f, 0.0f );
|
||||
glVertex3f( corner.x, corner.y, 1.0 );
|
||||
glVertex3f( corner.x, corner.y, 0.0 );
|
||||
}
|
||||
|
||||
glNormal3f( 0.0, 1.0f, 0.0f );
|
||||
glVertex3d( 0.0, radius, 1.0 );
|
||||
glVertex3d( 0.0, radius, 0.0 );
|
||||
|
@ -201,7 +213,8 @@ void OGL_draw_half_open_cylinder( unsigned int aNrSidesPerCircle )
|
|||
}
|
||||
|
||||
|
||||
void OGL_Draw_segment( const CROUNDSEGMENT2D &aSegment, unsigned int aNrSidesPerCircle )
|
||||
void OGL_Draw_segment( const CROUNDSEGMENT2D &aSegment,
|
||||
unsigned int aNrSidesPerCircle )
|
||||
{
|
||||
glPushMatrix();
|
||||
|
||||
|
@ -215,14 +228,17 @@ void OGL_Draw_segment( const CROUNDSEGMENT2D &aSegment, unsigned int aNrSidesPer
|
|||
|
||||
if( ( end_minus_start.x != 0.0f ) || ( end_minus_start.y != 0.0f ) )
|
||||
{
|
||||
glRotatef( atan2(end_minus_start.y, end_minus_start.x) / RADPERDEG, 0.0f, 0.0f, 1.0f );
|
||||
glRotatef( atan2( end_minus_start.y, end_minus_start.x ) / RADPERDEG,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f );
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef( length, 0.0, 0.0f );
|
||||
glScalef( width, width, 1.0f );
|
||||
OGL_draw_half_open_cylinder( aNrSidesPerCircle );
|
||||
glPopMatrix ();
|
||||
glPopMatrix();
|
||||
|
||||
glBegin( GL_QUADS );
|
||||
glNormal3f( 0.0,-1.0, 0.0 );
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -30,9 +30,8 @@
|
|||
#ifndef OGL_LEGACY_UTILS_H_
|
||||
#define OGL_LEGACY_UTILS_H_
|
||||
|
||||
#include "plugins/3dapi/xv3d_types.h"
|
||||
#include "3d_render_raytracing/shapes3D/cbbox.h"
|
||||
#include "3d_render_raytracing/shapes2D/croundsegment2d.h"
|
||||
#include "../3d_render_raytracing/shapes3D/cbbox.h"
|
||||
#include "../3d_render_raytracing/shapes2D/croundsegment2d.h"
|
||||
|
||||
/**
|
||||
* @brief OGL_draw_arrow - draw a round arrow
|
||||
|
@ -62,6 +61,7 @@ void OGL_draw_half_open_cylinder( unsigned int aNrSidesPerCircle );
|
|||
* @brief OGL_Draw_segment
|
||||
* @param aSegment
|
||||
*/
|
||||
void OGL_Draw_segment( const CROUNDSEGMENT2D &aSegment, unsigned int aNrSidesPerCircle );
|
||||
void OGL_Draw_segment( const CROUNDSEGMENT2D &aSegment,
|
||||
unsigned int aNrSidesPerCircle );
|
||||
|
||||
#endif // OGL_LEGACY_UTILS_H_
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 caccelerator.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "caccelerator.h"
|
||||
|
||||
|
||||
CGENERICACCELERATOR::CGENERICACCELERATOR( )
|
||||
{
|
||||
m_bbox.Reset();
|
||||
}
|
||||
|
||||
CGENERICACCELERATOR::~CGENERICACCELERATOR()
|
||||
{
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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 caccelerator.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef _CACCELERATOR_H_
|
||||
#define _CACCELERATOR_H_
|
||||
|
||||
#include "ccontainer.h"
|
||||
#include "../raypacket.h"
|
||||
|
||||
|
||||
class CGENERICACCELERATOR
|
||||
{
|
||||
protected:
|
||||
CBBOX m_bbox;
|
||||
|
||||
public:
|
||||
CGENERICACCELERATOR( );
|
||||
virtual ~CGENERICACCELERATOR();
|
||||
|
||||
virtual bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const = 0;
|
||||
|
||||
virtual bool Intersect( const RAY &aRay,
|
||||
HITINFO &aHitInfo,
|
||||
unsigned int aAccNodeInfo ) const = 0;
|
||||
|
||||
virtual bool Intersect( const RAYPACKET &aRayPacket,
|
||||
HITINFO_PACKET *aHitInfoPacket ) const = 0;
|
||||
|
||||
virtual bool IntersectP( const RAY &aRay, float aMaxDistance ) const = 0;
|
||||
};
|
||||
|
||||
#endif // _CACCELERATOR_H_
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
* 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 cbvh_packet_traversal.cpp
|
||||
* @brief This file implementes packet traversal over the BVH PBRT implementation
|
||||
*/
|
||||
|
||||
#include "cbvh_pbrt.h"
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
||||
#define BVH_RANGED_TRAVERSAL
|
||||
//#define BVH_PARTITION_TRAVERSAL
|
||||
|
||||
|
||||
#define MAX_TODOS 64
|
||||
|
||||
|
||||
struct StackNode
|
||||
{
|
||||
int cell;
|
||||
unsigned int ia; // Index to the first alive ray
|
||||
};
|
||||
|
||||
|
||||
static inline unsigned int getFirstHit( const RAYPACKET &aRayPacket,
|
||||
const CBBOX &aBBox,
|
||||
unsigned int ia,
|
||||
HITINFO_PACKET *aHitInfoPacket )
|
||||
{
|
||||
float hitT;
|
||||
|
||||
if( aBBox.Intersect( aRayPacket.m_ray[ia], &hitT ) )
|
||||
if( hitT < aHitInfoPacket[ia].m_HitInfo.m_tHit )
|
||||
return ia;
|
||||
|
||||
if( !aRayPacket.m_Frustum.Intersect( aBBox ) )
|
||||
return RAYPACKET_RAYS_PER_PACKET;
|
||||
|
||||
for( unsigned int i = ia + 1; i < RAYPACKET_RAYS_PER_PACKET; ++i )
|
||||
{
|
||||
if( aBBox.Intersect( aRayPacket.m_ray[i], &hitT ) )
|
||||
if( hitT < aHitInfoPacket[i].m_HitInfo.m_tHit )
|
||||
return i;
|
||||
}
|
||||
|
||||
return RAYPACKET_RAYS_PER_PACKET;
|
||||
}
|
||||
|
||||
|
||||
#ifdef BVH_RANGED_TRAVERSAL
|
||||
|
||||
static inline unsigned int getLastHit( const RAYPACKET &aRayPacket,
|
||||
const CBBOX &aBBox,
|
||||
unsigned int ia,
|
||||
HITINFO_PACKET *aHitInfoPacket )
|
||||
{
|
||||
for( unsigned int ie = (RAYPACKET_RAYS_PER_PACKET - 1); ie > ia; --ie )
|
||||
{
|
||||
float hitT;
|
||||
|
||||
if( aBBox.Intersect( aRayPacket.m_ray[ie], &hitT ) )
|
||||
if( hitT < aHitInfoPacket[ie].m_HitInfo.m_tHit )
|
||||
return ie + 1;
|
||||
}
|
||||
|
||||
return ia + 1;
|
||||
}
|
||||
|
||||
|
||||
// "Large Ray Packets for Real-time Whitted Ray Tracing"
|
||||
// http://cseweb.ucsd.edu/~ravir/whitted.pdf
|
||||
|
||||
// Ranged Traversal
|
||||
bool CBVH_PBRT::Intersect( const RAYPACKET &aRayPacket,
|
||||
HITINFO_PACKET *aHitInfoPacket ) const
|
||||
{
|
||||
if( m_nodes == NULL )
|
||||
return false;
|
||||
|
||||
if( (&m_nodes[0]) == NULL )
|
||||
return false;
|
||||
|
||||
bool anyHitted = false;
|
||||
int todoOffset = 0, nodeNum = 0;
|
||||
StackNode todo[MAX_TODOS];
|
||||
|
||||
unsigned int ia = 0;
|
||||
|
||||
while( true )
|
||||
{
|
||||
const LinearBVHNode *curCell = &m_nodes[nodeNum];
|
||||
|
||||
ia = getFirstHit( aRayPacket, curCell->bounds, ia, aHitInfoPacket );
|
||||
|
||||
if( ia < RAYPACKET_RAYS_PER_PACKET )
|
||||
{
|
||||
if( curCell->nPrimitives == 0 )
|
||||
{
|
||||
StackNode &node = todo[todoOffset++];
|
||||
node.cell = curCell->secondChildOffset;
|
||||
node.ia = ia;
|
||||
nodeNum = nodeNum + 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned int ie = getLastHit( aRayPacket,
|
||||
curCell->bounds,
|
||||
ia,
|
||||
aHitInfoPacket );
|
||||
|
||||
for( int j = 0; j < curCell->nPrimitives; ++j )
|
||||
{
|
||||
const COBJECT *obj = m_primitives[curCell->primitivesOffset + j];
|
||||
|
||||
if( aRayPacket.m_Frustum.Intersect( obj->GetBBox() ) )
|
||||
{
|
||||
for( unsigned int i = ia; i < ie; ++i )
|
||||
{
|
||||
const bool hitted = obj->Intersect( aRayPacket.m_ray[i],
|
||||
aHitInfoPacket[i].m_HitInfo );
|
||||
|
||||
if( hitted )
|
||||
{
|
||||
anyHitted |= hitted;
|
||||
aHitInfoPacket[i].m_hitresult |= hitted;
|
||||
aHitInfoPacket[i].m_HitInfo.m_acc_node_info = nodeNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( todoOffset == 0 )
|
||||
break;
|
||||
|
||||
const StackNode &node = todo[--todoOffset];
|
||||
|
||||
nodeNum = node.cell;
|
||||
ia = node.ia;
|
||||
}
|
||||
|
||||
return anyHitted;
|
||||
|
||||
}// Ranged Traversal
|
||||
#endif
|
||||
|
||||
|
||||
// "Ray Tracing Deformable Scenes Using Dynamic Bounding Volume Hierarchies"
|
||||
// http://www.cs.cmu.edu/afs/cs/academic/class/15869-f11/www/readings/wald07_packetbvh.pdf
|
||||
|
||||
#ifdef BVH_PARTITION_TRAVERSAL
|
||||
|
||||
static inline unsigned int getLastHit( const RAYPACKET &aRayPacket,
|
||||
const CBBOX &aBBox,
|
||||
unsigned int ia,
|
||||
const unsigned int *aRayIndex,
|
||||
HITINFO_PACKET *aHitInfoPacket )
|
||||
{
|
||||
for( unsigned int ie = (RAYPACKET_RAYS_PER_PACKET - 1); ie > ia; --ie )
|
||||
{
|
||||
float hitT;
|
||||
|
||||
if( aBBox.Intersect( aRayPacket.m_ray[ aRayIndex[ie] ], &hitT ) )
|
||||
if( hitT < aHitInfoPacket[ aRayIndex[ie] ].m_HitInfo.m_tHit )
|
||||
return ie + 1;
|
||||
}
|
||||
|
||||
return ia + 1;
|
||||
}
|
||||
|
||||
|
||||
static inline unsigned int partRays( const RAYPACKET &aRayPacket,
|
||||
const CBBOX &aBBox,
|
||||
unsigned int ia,
|
||||
unsigned int *aRayIndex,
|
||||
HITINFO_PACKET *aHitInfoPacket )
|
||||
{
|
||||
|
||||
if( !aRayPacket.m_Frustum.Intersect( aBBox ) )
|
||||
return RAYPACKET_RAYS_PER_PACKET;
|
||||
|
||||
unsigned int ie = 0;
|
||||
|
||||
for( unsigned int i = 0; i < ia; ++i )
|
||||
{
|
||||
float hitT;
|
||||
if( aBBox.Intersect( aRayPacket.m_ray[ aRayIndex[i] ], &hitT ) )
|
||||
if( hitT < aHitInfoPacket[ aRayIndex[i] ].m_HitInfo.m_tHit )
|
||||
std::swap( aRayIndex[ie++], aRayIndex[i] );
|
||||
}
|
||||
|
||||
return ie;
|
||||
}
|
||||
|
||||
|
||||
bool CBVH_PBRT::Intersect( const RAYPACKET &aRayPacket,
|
||||
HITINFO_PACKET *aHitInfoPacket ) const
|
||||
{
|
||||
bool anyHitted = false;
|
||||
int todoOffset = 0, nodeNum = 0;
|
||||
StackNode todo[MAX_TODOS];
|
||||
|
||||
unsigned int I[RAYPACKET_RAYS_PER_PACKET];
|
||||
|
||||
memcpy( I, m_I, RAYPACKET_RAYS_PER_PACKET * sizeof( unsigned int ) );
|
||||
|
||||
unsigned int ia = 0;
|
||||
|
||||
while( true )
|
||||
{
|
||||
const LinearBVHNode *curCell = &m_nodes[nodeNum];
|
||||
|
||||
ia = partRays( aRayPacket, curCell->bounds, ia, I, aHitInfoPacket );
|
||||
|
||||
if( ia < RAYPACKET_RAYS_PER_PACKET )
|
||||
{
|
||||
if( curCell->nPrimitives == 0 )
|
||||
{
|
||||
StackNode &node = todo[todoOffset++];
|
||||
node.cell = curCell->secondChildOffset;
|
||||
node.ia = ia;
|
||||
nodeNum = nodeNum + 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int ie = getLastHit( aRayPacket,
|
||||
curCell->bounds,
|
||||
ia,
|
||||
I,
|
||||
aHitInfoPacket );
|
||||
|
||||
for( int j = 0; j < curCell->nPrimitives; ++j )
|
||||
{
|
||||
const COBJECT *obj = m_primitives[curCell->primitivesOffset + j];
|
||||
|
||||
if( aRayPacket.m_Frustum.Intersect( obj->GetBBox() ) )
|
||||
{
|
||||
for( unsigned int i = 0; i < ie; ++i )
|
||||
{
|
||||
unsigned int idx = I[i];
|
||||
|
||||
bool hitted = obj->Intersect(
|
||||
aRayPacket.m_ray[idx],
|
||||
aHitInfoPacket[idx].m_HitInfo );
|
||||
|
||||
if( hitted )
|
||||
{
|
||||
anyHitted |= hitted;
|
||||
aHitInfoPacket[idx].m_hitresult |= hitted;
|
||||
aHitInfoPacket[idx].m_HitInfo.m_acc_node_info = nodeNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( todoOffset == 0 )
|
||||
break;
|
||||
|
||||
const StackNode &node = todo[--todoOffset];
|
||||
|
||||
nodeNum = node.cell;
|
||||
ia = node.ia;
|
||||
}
|
||||
|
||||
return anyHitted;
|
||||
}// Partition Traversal
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* 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 cbvh_pbrt.h
|
||||
* @brief This BVH implementation is based on the source code implementation
|
||||
* from the book "Physically Based Rendering" (v2 and v3)
|
||||
*
|
||||
* Adaptions performed:
|
||||
* - Types and class types adapted to KiCad project
|
||||
* - Convert some source to build in the C++ specification of KiCad
|
||||
* - Code style to match KiCad
|
||||
* - Asserts converted
|
||||
* - Use compare functions/structures for std::partition and std::nth_element
|
||||
*
|
||||
* The original source code have the following licence:
|
||||
*
|
||||
* "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."
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CBVH_PBRT_H_
|
||||
#define _CBVH_PBRT_H_
|
||||
|
||||
#include "caccelerator.h"
|
||||
#include <list>
|
||||
#include <stdint.h>
|
||||
|
||||
// Forward Declarations
|
||||
struct BVHBuildNode;
|
||||
struct BVHPrimitiveInfo;
|
||||
struct MortonPrimitive;
|
||||
|
||||
struct LinearBVHNode
|
||||
{
|
||||
// 24 bytes
|
||||
CBBOX bounds;
|
||||
|
||||
// 4 bytes
|
||||
union
|
||||
{
|
||||
int primitivesOffset; ///< leaf
|
||||
int secondChildOffset; ///< interior
|
||||
};
|
||||
|
||||
// 4 bytes
|
||||
uint16_t nPrimitives; ///< 0 -> interior node
|
||||
uint8_t axis; ///< interior node: xyz
|
||||
uint8_t pad[1]; ///< ensure 32 byte total size
|
||||
};
|
||||
|
||||
|
||||
enum SPLITMETHOD
|
||||
{
|
||||
SPLIT_MIDDLE,
|
||||
SPLIT_EQUALCOUNTS,
|
||||
SPLIT_SAH,
|
||||
SPLIT_HLBVH
|
||||
};
|
||||
|
||||
|
||||
class CBVH_PBRT : public CGENERICACCELERATOR
|
||||
{
|
||||
|
||||
public:
|
||||
CBVH_PBRT( const CGENERICCONTAINER &aObjectContainer,
|
||||
int aMaxPrimsInNode = 4,
|
||||
SPLITMETHOD aSplitMethod = SPLIT_SAH );
|
||||
|
||||
~CBVH_PBRT();
|
||||
|
||||
// Imported from CGENERICACCELERATOR
|
||||
bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const;
|
||||
bool Intersect( const RAY &aRay, HITINFO &aHitInfo, unsigned int aAccNodeInfo ) const;
|
||||
bool Intersect(const RAYPACKET &aRayPacket, HITINFO_PACKET *aHitInfoPacket ) const;
|
||||
bool IntersectP( const RAY &aRay, float aMaxDistance ) const;
|
||||
|
||||
private:
|
||||
|
||||
BVHBuildNode *recursiveBuild( std::vector<BVHPrimitiveInfo> &primitiveInfo,
|
||||
int start,
|
||||
int end,
|
||||
int *totalNodes,
|
||||
CONST_VECTOR_OBJECT &orderedPrims );
|
||||
|
||||
BVHBuildNode *HLBVHBuild( const std::vector<BVHPrimitiveInfo> &primitiveInfo,
|
||||
int *totalNodes,
|
||||
CONST_VECTOR_OBJECT &orderedPrims );
|
||||
|
||||
//!TODO: after implement memory arena, put const back to this functions
|
||||
BVHBuildNode *emitLBVH( BVHBuildNode *&buildNodes,
|
||||
const std::vector<BVHPrimitiveInfo> &primitiveInfo,
|
||||
MortonPrimitive *mortonPrims,
|
||||
int nPrimitives,
|
||||
int *totalNodes,
|
||||
CONST_VECTOR_OBJECT &orderedPrims,
|
||||
int *orderedPrimsOffset,
|
||||
int bit );
|
||||
|
||||
BVHBuildNode *buildUpperSAH( std::vector<BVHBuildNode *> &treeletRoots,
|
||||
int start,
|
||||
int end,
|
||||
int *totalNodes );
|
||||
|
||||
int flattenBVHTree( BVHBuildNode *node,
|
||||
uint32_t *offset );
|
||||
|
||||
// BVH Private Data
|
||||
const int m_maxPrimsInNode;
|
||||
SPLITMETHOD m_splitMethod;
|
||||
CONST_VECTOR_OBJECT m_primitives;
|
||||
LinearBVHNode *m_nodes;
|
||||
|
||||
std::list<void *> m_addresses_pointer_to_mm_free;
|
||||
|
||||
// Partition traversal
|
||||
unsigned int m_I[RAYPACKET_RAYS_PER_PACKET];
|
||||
};
|
||||
|
||||
#endif // _CBVH_PBRT_H_
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* 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 ccontainer.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "ccontainer.h"
|
||||
#include <stdio.h>
|
||||
|
||||
CGENERICCONTAINER::CGENERICCONTAINER()
|
||||
{
|
||||
m_objects.clear();
|
||||
m_bbox.Reset();
|
||||
}
|
||||
|
||||
void CGENERICCONTAINER::Clear()
|
||||
{
|
||||
if( !m_objects.empty() )
|
||||
{
|
||||
for( LIST_OBJECT::iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
++ii )
|
||||
{
|
||||
delete *ii;
|
||||
*ii = NULL;
|
||||
}
|
||||
|
||||
m_objects.clear();
|
||||
}
|
||||
|
||||
m_bbox.Reset();
|
||||
}
|
||||
|
||||
|
||||
CGENERICCONTAINER::~CGENERICCONTAINER()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
void CGENERICCONTAINER::ConvertTo( CONST_VECTOR_OBJECT &aOutVector ) const
|
||||
{
|
||||
aOutVector.resize( m_objects.size() );
|
||||
|
||||
if( !m_objects.empty() )
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for( LIST_OBJECT::const_iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
++ii )
|
||||
{
|
||||
wxASSERT( (*ii) != NULL );
|
||||
|
||||
aOutVector[i++] = static_cast<const COBJECT *>(*ii);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CCONTAINER::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
|
||||
{
|
||||
|
||||
if( !m_bbox.Intersect( aRay ) )
|
||||
return false;
|
||||
|
||||
bool hitted = false;
|
||||
|
||||
for( LIST_OBJECT::const_iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
++ii )
|
||||
{
|
||||
const COBJECT *object = static_cast<const COBJECT *>(*ii);
|
||||
|
||||
if( object->Intersect( aRay, aHitInfo) )
|
||||
hitted = true;
|
||||
}
|
||||
|
||||
return hitted;
|
||||
}
|
||||
|
||||
|
||||
bool CCONTAINER::IntersectP( const RAY &aRay, float aMaxDistance ) const
|
||||
{
|
||||
/*
|
||||
if( !m_bbox.Inside( aRay.m_Origin ) )
|
||||
if( !m_bbox.Intersect( aRay ) )
|
||||
return false;
|
||||
*/
|
||||
for( LIST_OBJECT::const_iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
++ii )
|
||||
{
|
||||
const COBJECT *object = static_cast<const COBJECT *>(*ii);
|
||||
|
||||
if( object->IntersectP( aRay, aMaxDistance ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -38,7 +38,7 @@ typedef std::list<COBJECT *> LIST_OBJECT;
|
|||
typedef std::vector<COBJECT *> VECTOR_OBJECT;
|
||||
typedef std::vector<const COBJECT *> CONST_VECTOR_OBJECT;
|
||||
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CGENERICCONTAINER
|
||||
class CGENERICCONTAINER
|
||||
{
|
||||
protected:
|
||||
CBBOX m_bbox;
|
||||
|
@ -62,7 +62,7 @@ public:
|
|||
|
||||
const LIST_OBJECT &GetList() const { return m_objects; }
|
||||
|
||||
const void ConvertTo( CONST_VECTOR_OBJECT &aOutVector ) const;
|
||||
void ConvertTo( CONST_VECTOR_OBJECT &aOutVector ) const;
|
||||
|
||||
const CBBOX &GetBBox() const { return m_bbox; }
|
||||
|
||||
|
@ -73,7 +73,7 @@ private:
|
|||
};
|
||||
|
||||
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CCONTAINER : public CGENERICCONTAINER
|
||||
class CCONTAINER : public CGENERICCONTAINER
|
||||
{
|
||||
public:
|
||||
bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const;
|
||||
|
|
|
@ -0,0 +1,437 @@
|
|||
/*
|
||||
* 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 ccontainer2d.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "ccontainer2d.h"
|
||||
#include <vector>
|
||||
#include <boost/range/algorithm/partition.hpp>
|
||||
#include <boost/range/algorithm/nth_element.hpp>
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// CGENERICCONTAINER2
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CGENERICCONTAINER2D::CGENERICCONTAINER2D( OBJECT2D_TYPE aObjType )
|
||||
{
|
||||
m_bbox.Reset();
|
||||
}
|
||||
|
||||
|
||||
void CGENERICCONTAINER2D::Clear()
|
||||
{
|
||||
m_bbox.Reset();
|
||||
|
||||
for( LIST_OBJECT2D::iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
++ii )
|
||||
{
|
||||
delete *ii;
|
||||
*ii = NULL;
|
||||
}
|
||||
|
||||
m_objects.clear();
|
||||
}
|
||||
|
||||
|
||||
CGENERICCONTAINER2D::~CGENERICCONTAINER2D()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// CCONTAINER2D
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CCONTAINER2D::CCONTAINER2D() : CGENERICCONTAINER2D( OBJ2D_CONTAINER )
|
||||
{
|
||||
|
||||
}
|
||||
/*
|
||||
|
||||
bool CCONTAINER2D::Intersects( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CCONTAINER2D::Overlaps( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
// NOT IMPLEMENTED
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CCONTAINER2D::Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const
|
||||
{
|
||||
if( !m_bbox.Intersect( aSegRay ) )
|
||||
return false;
|
||||
|
||||
bool hitted = false;
|
||||
|
||||
for( LIST_OBJECT2D::const_iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
ii++ )
|
||||
{
|
||||
const COBJECT2D *object = static_cast<const COBJECT2D *>(*ii);
|
||||
|
||||
float t;
|
||||
SFVEC2F hitNormal;
|
||||
if( object->Intersect( aSegRay, &t, &hitNormal ) )
|
||||
if( (hitted == false) || (t < *aOutT ) )
|
||||
{
|
||||
hitted = true;
|
||||
*aOutT = t;
|
||||
*aNormalOut = hitNormal;
|
||||
}
|
||||
}
|
||||
|
||||
return hitted;
|
||||
}
|
||||
|
||||
|
||||
INTERSECTION_RESULT CCONTAINER2D::IsBBoxInside( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
return INTR_MISSES;
|
||||
}
|
||||
|
||||
|
||||
bool CCONTAINER2D::IsPointInside( const SFVEC2F &aPoint ) const
|
||||
{
|
||||
if( !m_bbox.Inside( aPoint ) )
|
||||
return false;
|
||||
|
||||
for( LIST_OBJECT2D::const_iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
ii++ )
|
||||
{
|
||||
const COBJECT2D *object = static_cast<const COBJECT2D *>(*ii);
|
||||
|
||||
if( object->IsPointInside( aPoint ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
void CCONTAINER2D::GetListObjectsIntersects( const CBBOX2D & aBBox,
|
||||
CONST_LIST_OBJECT2D &aOutList ) const
|
||||
{
|
||||
// !TODO:
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// CBVHCONTAINER2D
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CBVHCONTAINER2D::CBVHCONTAINER2D() : CGENERICCONTAINER2D( OBJ2D_BVHCONTAINER )
|
||||
{
|
||||
m_isInitialized = false;
|
||||
m_bbox.Reset();
|
||||
m_elements_to_delete.clear();
|
||||
m_Tree = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
bool CBVHCONTAINER2D::Intersects( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
// !TODO: implement the BVH
|
||||
return m_bbox.Intersects( aBBox );
|
||||
}
|
||||
|
||||
|
||||
bool CBVHCONTAINER2D::Overlaps( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
// NOT IMPLEMENTED
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CBVHCONTAINER2D::Intersect( const RAYSEG2D &aSegRay,
|
||||
float *aOutT, SFVEC2F *aNormalOut ) const
|
||||
{
|
||||
// !TODO: implement the BVH
|
||||
|
||||
if( !m_bbox.Intersect( aSegRay ) )
|
||||
return false;
|
||||
|
||||
bool hitted = false;
|
||||
|
||||
for( LIST_OBJECT2D::const_iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
ii++ )
|
||||
{
|
||||
const COBJECT2D *object = static_cast<const COBJECT2D *>(*ii);
|
||||
|
||||
float t;
|
||||
SFVEC2F hitNormal;
|
||||
if( object->Intersect( aSegRay, &t, &hitNormal ) )
|
||||
if( (hitted == false) || (t < *aOutT ) )
|
||||
{
|
||||
hitted = true;
|
||||
*aOutT = t;
|
||||
*aNormalOut = hitNormal;
|
||||
}
|
||||
}
|
||||
|
||||
return hitted;
|
||||
}
|
||||
|
||||
|
||||
INTERSECTION_RESULT CBVHCONTAINER2D::IsBBoxInside( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
return INTR_MISSES;
|
||||
}
|
||||
|
||||
|
||||
bool CBVHCONTAINER2D::IsPointInside( const SFVEC2F &aPoint ) const
|
||||
{
|
||||
// !TODO: implement the BVH
|
||||
|
||||
if( !m_bbox.Inside( aPoint ) )
|
||||
return false;
|
||||
|
||||
for( LIST_OBJECT2D::const_iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
ii++ )
|
||||
{
|
||||
const COBJECT2D *object = static_cast<const COBJECT2D *>(*ii);
|
||||
|
||||
if( object->IsPointInside( aPoint ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
void CBVHCONTAINER2D::destroy()
|
||||
{
|
||||
for( std::list<BVH_CONTAINER_NODE_2D *>::iterator ii = m_elements_to_delete.begin();
|
||||
ii != m_elements_to_delete.end();
|
||||
++ii )
|
||||
{
|
||||
delete *ii;
|
||||
*ii = NULL;
|
||||
}
|
||||
m_elements_to_delete.clear();
|
||||
|
||||
m_isInitialized = false;
|
||||
}
|
||||
|
||||
|
||||
CBVHCONTAINER2D::~CBVHCONTAINER2D()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
|
||||
#define BVH_CONTAINER2D_MAX_OBJ_PER_LEAF 4
|
||||
|
||||
|
||||
void CBVHCONTAINER2D::BuildBVH()
|
||||
{
|
||||
if( m_isInitialized )
|
||||
destroy();
|
||||
|
||||
if( m_objects.empty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_isInitialized = true;
|
||||
m_Tree = new BVH_CONTAINER_NODE_2D;
|
||||
|
||||
m_elements_to_delete.push_back( m_Tree );
|
||||
m_Tree->m_BBox = m_bbox;
|
||||
|
||||
for( LIST_OBJECT2D::const_iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
++ii )
|
||||
{
|
||||
m_Tree->m_LeafList.push_back( static_cast<const COBJECT2D *>(*ii) );
|
||||
}
|
||||
|
||||
recursiveBuild_MIDDLE_SPLIT( m_Tree );
|
||||
}
|
||||
|
||||
|
||||
// Based on a blog post by VADIM KRAVCENKO
|
||||
// http://www.vadimkravcenko.com/bvh-tree-building
|
||||
// Implements:
|
||||
|
||||
// "Split in the middle of the longest Axis"
|
||||
// "Creates a binary tree with Top-Down approach.
|
||||
// Fastest BVH building, but least [speed] accuracy."
|
||||
|
||||
static bool sortByCentroid_X( const COBJECT2D *a, const COBJECT2D *b )
|
||||
{
|
||||
return a->GetCentroid()[0] < b->GetCentroid()[0];
|
||||
}
|
||||
|
||||
static bool sortByCentroid_Y( const COBJECT2D *a, const COBJECT2D *b )
|
||||
{
|
||||
return a->GetCentroid()[0] < b->GetCentroid()[0];
|
||||
}
|
||||
|
||||
static bool sortByCentroid_Z( const COBJECT2D *a, const COBJECT2D *b )
|
||||
{
|
||||
return a->GetCentroid()[0] < b->GetCentroid()[0];
|
||||
}
|
||||
|
||||
void CBVHCONTAINER2D::recursiveBuild_MIDDLE_SPLIT( BVH_CONTAINER_NODE_2D *aNodeParent )
|
||||
{
|
||||
wxASSERT( aNodeParent != NULL );
|
||||
wxASSERT( aNodeParent->m_BBox.IsInitialized() == true );
|
||||
wxASSERT( aNodeParent->m_LeafList.size() > 0 );
|
||||
|
||||
if( aNodeParent->m_LeafList.size() > BVH_CONTAINER2D_MAX_OBJ_PER_LEAF )
|
||||
{
|
||||
// Create Leaf Nodes
|
||||
BVH_CONTAINER_NODE_2D *leftNode = new BVH_CONTAINER_NODE_2D;
|
||||
BVH_CONTAINER_NODE_2D *rightNode = new BVH_CONTAINER_NODE_2D;
|
||||
m_elements_to_delete.push_back( leftNode );
|
||||
m_elements_to_delete.push_back( rightNode );
|
||||
|
||||
leftNode->m_BBox.Reset();
|
||||
rightNode->m_BBox.Reset();
|
||||
leftNode->m_LeafList.clear();
|
||||
rightNode->m_LeafList.clear();
|
||||
|
||||
// Decide wich axis to split
|
||||
const unsigned int axis_to_split = aNodeParent->m_BBox.MaxDimension();
|
||||
|
||||
// Divide the objects
|
||||
switch( axis_to_split )
|
||||
{
|
||||
case 0: aNodeParent->m_LeafList.sort( sortByCentroid_X );
|
||||
case 1: aNodeParent->m_LeafList.sort( sortByCentroid_Y );
|
||||
case 2: aNodeParent->m_LeafList.sort( sortByCentroid_Z );
|
||||
}
|
||||
|
||||
unsigned int i = 0;
|
||||
|
||||
for( CONST_LIST_OBJECT2D::const_iterator ii = aNodeParent->m_LeafList.begin();
|
||||
ii != aNodeParent->m_LeafList.end();
|
||||
++ii )
|
||||
{
|
||||
const COBJECT2D *object = static_cast<const COBJECT2D *>(*ii);
|
||||
|
||||
if( i < (aNodeParent->m_LeafList.size() / 2 ) )
|
||||
{
|
||||
leftNode->m_BBox.Union( object->GetBBox() );
|
||||
leftNode->m_LeafList.push_back( object );
|
||||
}
|
||||
else
|
||||
{
|
||||
rightNode->m_BBox.Union( object->GetBBox() );
|
||||
rightNode->m_LeafList.push_back( object );
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
wxASSERT( leftNode->m_LeafList.size() > 0 );
|
||||
wxASSERT( rightNode->m_LeafList.size() > 0 );
|
||||
wxASSERT( ( leftNode->m_LeafList.size() + rightNode->m_LeafList.size() ) ==
|
||||
aNodeParent->m_LeafList.size() );
|
||||
|
||||
aNodeParent->m_Children[0] = leftNode;
|
||||
aNodeParent->m_Children[1] = rightNode;
|
||||
aNodeParent->m_LeafList.clear();
|
||||
|
||||
recursiveBuild_MIDDLE_SPLIT( leftNode );
|
||||
recursiveBuild_MIDDLE_SPLIT( rightNode );
|
||||
}
|
||||
else
|
||||
{
|
||||
// It is a Leaf
|
||||
aNodeParent->m_Children[0] = NULL;
|
||||
aNodeParent->m_Children[1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBVHCONTAINER2D::GetListObjectsIntersects( const CBBOX2D &aBBox,
|
||||
CONST_LIST_OBJECT2D &aOutList ) const
|
||||
{
|
||||
wxASSERT( aBBox.IsInitialized() == true );
|
||||
wxASSERT( m_isInitialized == true );
|
||||
|
||||
aOutList.clear();
|
||||
|
||||
if( m_Tree )
|
||||
recursiveGetListObjectsIntersects( m_Tree, aBBox, aOutList );
|
||||
}
|
||||
|
||||
|
||||
void CBVHCONTAINER2D::recursiveGetListObjectsIntersects( const BVH_CONTAINER_NODE_2D *aNode,
|
||||
const CBBOX2D & aBBox,
|
||||
CONST_LIST_OBJECT2D &aOutList ) const
|
||||
{
|
||||
wxASSERT( aNode != NULL );
|
||||
wxASSERT( aBBox.IsInitialized() == true );
|
||||
|
||||
if( aNode->m_BBox.Intersects( aBBox ) )
|
||||
{
|
||||
if( !aNode->m_LeafList.empty() )
|
||||
{
|
||||
wxASSERT( aNode->m_Children[0] == NULL );
|
||||
wxASSERT( aNode->m_Children[1] == NULL );
|
||||
|
||||
// Leaf
|
||||
for( CONST_LIST_OBJECT2D::const_iterator ii = aNode->m_LeafList.begin();
|
||||
ii != aNode->m_LeafList.end();
|
||||
++ii )
|
||||
{
|
||||
const COBJECT2D *obj = static_cast<const COBJECT2D *>(*ii);
|
||||
|
||||
if( obj->Intersects( aBBox ) )
|
||||
aOutList.push_back( obj );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxASSERT( aNode->m_Children[0] != NULL );
|
||||
wxASSERT( aNode->m_Children[1] != NULL );
|
||||
|
||||
// Node
|
||||
recursiveGetListObjectsIntersects( aNode->m_Children[0], aBBox, aOutList );
|
||||
recursiveGetListObjectsIntersects( aNode->m_Children[1], aBBox, aOutList );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -37,14 +37,14 @@ typedef std::list<COBJECT2D *> LIST_OBJECT2D;
|
|||
typedef std::list<const COBJECT2D *> CONST_LIST_OBJECT2D;
|
||||
|
||||
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CGENERICCONTAINER2D
|
||||
class CGENERICCONTAINER2D
|
||||
{
|
||||
protected:
|
||||
CBBOX2D m_bbox;
|
||||
LIST_OBJECT2D m_objects;
|
||||
|
||||
public:
|
||||
CGENERICCONTAINER2D( OBJECT2D_TYPE aObjType );
|
||||
explicit CGENERICCONTAINER2D( OBJECT2D_TYPE aObjType );
|
||||
|
||||
virtual ~CGENERICCONTAINER2D();
|
||||
|
||||
|
@ -55,7 +55,7 @@ public:
|
|||
m_objects.push_back( aObject );
|
||||
m_bbox.Union( aObject->GetBBox() );
|
||||
}
|
||||
}// automatically releases the lock when lck goes out of scope.
|
||||
}
|
||||
|
||||
void Clear();
|
||||
|
||||
|
@ -66,19 +66,21 @@ public:
|
|||
* @param aBBox - a bbox to make the query
|
||||
* @param aOutList - A list of objects that intersects the bbox
|
||||
*/
|
||||
virtual void GetListObjectsIntersects( const CBBOX2D & aBBox, CONST_LIST_OBJECT2D &aOutList ) const = 0;
|
||||
virtual void GetListObjectsIntersects( const CBBOX2D & aBBox,
|
||||
CONST_LIST_OBJECT2D &aOutList ) const = 0;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CCONTAINER2D : public CGENERICCONTAINER2D
|
||||
class CCONTAINER2D : public CGENERICCONTAINER2D
|
||||
{
|
||||
public:
|
||||
CCONTAINER2D();
|
||||
|
||||
// Imported from CGENERICCONTAINER2D
|
||||
void GetListObjectsIntersects( const CBBOX2D & aBBox, CONST_LIST_OBJECT2D &aOutList ) const;
|
||||
void GetListObjectsIntersects( const CBBOX2D & aBBox,
|
||||
CONST_LIST_OBJECT2D &aOutList ) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -86,11 +88,13 @@ struct BVH_CONTAINER_NODE_2D
|
|||
{
|
||||
CBBOX2D m_BBox;
|
||||
BVH_CONTAINER_NODE_2D *m_Children[2];
|
||||
CONST_LIST_OBJECT2D m_LeafList; ///< Store the list of objects if that node is a Leaf
|
||||
|
||||
/// Store the list of objects if that node is a Leaf
|
||||
CONST_LIST_OBJECT2D m_LeafList;
|
||||
};
|
||||
|
||||
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CBVHCONTAINER2D : public CGENERICCONTAINER2D
|
||||
class CBVHCONTAINER2D : public CGENERICCONTAINER2D
|
||||
{
|
||||
public:
|
||||
CBVHCONTAINER2D();
|
||||
|
@ -105,12 +109,15 @@ private:
|
|||
|
||||
void destroy();
|
||||
void recursiveBuild_MIDDLE_SPLIT( BVH_CONTAINER_NODE_2D *aNodeParent );
|
||||
void recursiveGetListObjectsIntersects( const BVH_CONTAINER_NODE_2D *aNode, const CBBOX2D & aBBox, CONST_LIST_OBJECT2D &aOutList ) const;
|
||||
void recursiveGetListObjectsIntersects( const BVH_CONTAINER_NODE_2D *aNode,
|
||||
const CBBOX2D & aBBox,
|
||||
CONST_LIST_OBJECT2D &aOutList ) const;
|
||||
|
||||
public:
|
||||
|
||||
// Imported from CGENERICCONTAINER2D
|
||||
void GetListObjectsIntersects( const CBBOX2D & aBBox, CONST_LIST_OBJECT2D &aOutList ) const;
|
||||
void GetListObjectsIntersects( const CBBOX2D & aBBox,
|
||||
CONST_LIST_OBJECT2D &aOutList ) const;
|
||||
};
|
||||
|
||||
#endif // _CCONTAINER2D_H_
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* 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_raytracing.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef C3D_RENDER_RAYTRACING_H
|
||||
#define C3D_RENDER_RAYTRACING_H
|
||||
|
||||
#include "../../common_ogl/openGL_includes.h"
|
||||
#include "accelerators/ccontainer.h"
|
||||
#include "accelerators/caccelerator.h"
|
||||
#include "../c3d_render_base.h"
|
||||
#include "clight.h"
|
||||
#include "../cpostshader_ssao.h"
|
||||
#include "cmaterial.h"
|
||||
#include <plugins/3dapi/c3dmodel.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
/// Vector of materials
|
||||
typedef std::vector< CBLINN_PHONG_MATERIAL > MODEL_MATERIALS;
|
||||
|
||||
/// Maps a S3DMODEL pointer with a created CBLINN_PHONG_MATERIAL vector
|
||||
typedef std::map< const S3DMODEL * , MODEL_MATERIALS > MAP_MODEL_MATERIALS;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RT_RENDER_STATE_TRACING = 0,
|
||||
RT_RENDER_STATE_POST_PROCESS_SHADE,
|
||||
RT_RENDER_STATE_POST_PROCESS_BLUR_AND_FINISH,
|
||||
RT_RENDER_STATE_FINISH,
|
||||
RT_RENDER_STATE_MAX
|
||||
}RT_RENDER_STATE;
|
||||
|
||||
class C3D_RENDER_RAYTRACING : public C3D_RENDER_BASE
|
||||
{
|
||||
public:
|
||||
explicit C3D_RENDER_RAYTRACING( CINFO3D_VISU &aSettings );
|
||||
|
||||
~C3D_RENDER_RAYTRACING();
|
||||
|
||||
// Imported from C3D_RENDER_BASE
|
||||
void SetCurWindowSize( const wxSize &aSize );
|
||||
bool Redraw(bool aIsMoving, REPORTER *aStatusTextReporter );
|
||||
|
||||
int GetWaitForEditingTimeOut();
|
||||
|
||||
private:
|
||||
bool initializeOpenGL();
|
||||
void initializeNewWindowSize();
|
||||
void opengl_init_pbo();
|
||||
void opengl_delete_pbo();
|
||||
void reload( REPORTER *aStatusTextReporter );
|
||||
|
||||
void restart_render_state();
|
||||
void rt_render_tracing( GLubyte *ptrPBO , REPORTER *aStatusTextReporter );
|
||||
void rt_render_post_process_shade( GLubyte *ptrPBO , REPORTER *aStatusTextReporter );
|
||||
void rt_render_post_process_blur_finish( GLubyte *ptrPBO , REPORTER *aStatusTextReporter );
|
||||
void rt_render_trace_block( GLubyte *ptrPBO , signed int iBlock );
|
||||
|
||||
// Materials
|
||||
void setupMaterials();
|
||||
|
||||
struct
|
||||
{
|
||||
CBLINN_PHONG_MATERIAL m_Paste;
|
||||
CBLINN_PHONG_MATERIAL m_SilkS;
|
||||
CBLINN_PHONG_MATERIAL m_SolderMask;
|
||||
CBLINN_PHONG_MATERIAL m_EpoxyBoard;
|
||||
CBLINN_PHONG_MATERIAL m_Copper;
|
||||
CBLINN_PHONG_MATERIAL m_Floor;
|
||||
}m_materials;
|
||||
|
||||
bool m_isPreview;
|
||||
|
||||
SFVEC3F shadeHit( const SFVEC3F &aBgColor,
|
||||
const RAY &aRay,
|
||||
HITINFO &aHitInfo,
|
||||
bool aIsInsideObject,
|
||||
unsigned int aRecursiveLevel ) const;
|
||||
|
||||
/// State used on quality render
|
||||
RT_RENDER_STATE m_rt_render_state;
|
||||
|
||||
/// Time that the render starts
|
||||
unsigned long int m_stats_start_rendering_time;
|
||||
|
||||
/// Save the number of blocks progress of the render
|
||||
unsigned int m_nrBlocksRenderProgress;
|
||||
|
||||
CPOSTSHADER_SSAO m_postshader_ssao;
|
||||
|
||||
CLIGHTCONTAINER m_lights;
|
||||
|
||||
CDIRECTIONALLIGHT *m_camera_light;
|
||||
|
||||
bool m_opengl_support_vertex_buffer_object;
|
||||
GLuint m_pboId;
|
||||
GLuint m_pboDataSize;
|
||||
|
||||
CCONTAINER m_object_container;
|
||||
|
||||
/// This will store the list of created objects special for RT,
|
||||
/// that will be clear in the end
|
||||
CCONTAINER2D m_containerWithObjectsToDelete;
|
||||
|
||||
CCONTAINER2D *m_outlineBoard2dObjects;
|
||||
|
||||
CGENERICACCELERATOR *m_accelerator;
|
||||
|
||||
|
||||
// Morton codes
|
||||
|
||||
/// used to see if the windows size changed
|
||||
wxSize m_oldWindowsSize;
|
||||
|
||||
/// this encodes the Morton code positions
|
||||
std::vector< SFVEC2UI > m_blockPositions;
|
||||
|
||||
/// this flags if a position was already processed (cleared each new render)
|
||||
std::vector< bool > m_blockPositionsWasProcessed;
|
||||
|
||||
/// this encodes the Morton code positions (on fast preview mode)
|
||||
std::vector< SFVEC2UI > m_blockPositionsFast;
|
||||
|
||||
SFVEC2UI m_realBufferSize;
|
||||
SFVEC2UI m_fastPreviewModeSize;
|
||||
|
||||
HITINFO_PACKET *m_firstHitinfo;
|
||||
|
||||
SFVEC3F *m_shaderBuffer;
|
||||
|
||||
// Display Offset
|
||||
unsigned int m_xoffset;
|
||||
unsigned int m_yoffset;
|
||||
|
||||
// Statistics
|
||||
unsigned int m_stats_converted_dummy_to_plane;
|
||||
unsigned int m_stats_converted_roundsegment2d_to_roundsegment;
|
||||
|
||||
void create_3d_object_from( CCONTAINER &aDstContainer,
|
||||
const COBJECT2D *aObject2D,
|
||||
float aZMin, float aZMax,
|
||||
const CMATERIAL *aMaterial,
|
||||
const SFVEC3F &aObjColor );
|
||||
|
||||
void add_3D_vias_and_pads_to_container();
|
||||
void insert3DViaHole( const VIA* aVia );
|
||||
void insert3DPadHole( const D_PAD* aPad );
|
||||
void load_3D_models();
|
||||
void add_3D_models( const S3DMODEL *a3DModel,
|
||||
const glm::mat4 &aModelMatrix );
|
||||
|
||||
/// Stores materials of the 3D models
|
||||
MAP_MODEL_MATERIALS m_model_materials;
|
||||
|
||||
void initialize_block_positions();
|
||||
|
||||
void render( GLubyte *ptrPBO, REPORTER *aStatusTextReporter );
|
||||
void render_preview( GLubyte *ptrPBO );
|
||||
};
|
||||
|
||||
#endif // C3D_RENDER_RAYTRACING_H
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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 cfrustum.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
|
||||
#include "cfrustum.h"
|
||||
|
||||
// !TODO: optimize wih SSE
|
||||
//#if(GLM_ARCH != GLM_ARCH_PURE)
|
||||
#if 0
|
||||
#error not implemented
|
||||
#else
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
void CFRUSTUM::GenerateFrustum( const RAY &topLeft,
|
||||
const RAY &topRight,
|
||||
const RAY &bottomLeft,
|
||||
const RAY &bottomRight )
|
||||
{
|
||||
m_point[0] = topLeft.m_Origin;
|
||||
m_point[1] = topRight.m_Origin;
|
||||
m_point[2] = bottomLeft.m_Origin;
|
||||
m_point[3] = topLeft.m_Origin;
|
||||
|
||||
if( topRight.m_Dir == topLeft.m_Dir )
|
||||
{
|
||||
// This will be the case if the camera is Ortho projection
|
||||
|
||||
m_normals[0] = glm::normalize( bottomLeft.m_Origin - topLeft.m_Origin ); // TOP
|
||||
m_normals[1] = glm::normalize( topLeft.m_Origin - topRight.m_Origin ); // RIGHT
|
||||
m_normals[2] = -m_normals[0]; // BOTTOM
|
||||
m_normals[3] = -m_normals[1]; // LEFT
|
||||
}
|
||||
else
|
||||
{
|
||||
m_normals[0] = glm::cross( topRight.m_Dir, topLeft.m_Dir ); // TOP
|
||||
m_normals[1] = glm::cross( bottomRight.m_Dir, topRight.m_Dir ); // RIGHT
|
||||
m_normals[2] = glm::cross( bottomLeft.m_Dir, bottomRight.m_Dir ); // BOTTOM
|
||||
m_normals[3] = glm::cross( topLeft.m_Dir, bottomLeft.m_Dir ); // LEFT
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// There are multiple implementation of this algorithm on the web,
|
||||
// this one was based on the one find in:
|
||||
// https://github.com/nslo/raytracer/blob/2c2e0ff4bbb6082e07804ec7cf0b92673b98dcb1/src/raytracer/geom_utils.cpp#L66
|
||||
// by Nathan Slobody and Adam Wright
|
||||
// The frustum test is not exllude all the boxes,
|
||||
// when a box is behind and if it is intersecting the planes it will not be discardly but should.
|
||||
bool CFRUSTUM::Intersect( const CBBOX &aBBox ) const
|
||||
{
|
||||
const SFVEC3F box[8] = { aBBox.Min(),
|
||||
aBBox.Max(),
|
||||
SFVEC3F(aBBox.Min().x, aBBox.Min().y, aBBox.Max().z),
|
||||
SFVEC3F(aBBox.Min().x, aBBox.Max().y, aBBox.Min().z),
|
||||
SFVEC3F(aBBox.Min().x, aBBox.Max().y, aBBox.Max().z),
|
||||
SFVEC3F(aBBox.Max().x, aBBox.Min().y, aBBox.Min().z),
|
||||
SFVEC3F(aBBox.Max().x, aBBox.Min().y, aBBox.Max().z),
|
||||
SFVEC3F(aBBox.Max().x, aBBox.Max().y, aBBox.Min().z) };
|
||||
|
||||
// test each plane of frustum individually; if the point is on the wrong
|
||||
// side of the plane, the box is outside the frustum and we can exit
|
||||
int out_side = 0;
|
||||
|
||||
for( unsigned int i = 0; i < 4; ++i )
|
||||
{
|
||||
const SFVEC3F &pointPlane = m_point[i];
|
||||
const SFVEC3F &normalPlane = m_normals[i];
|
||||
|
||||
for( unsigned int j = 0; j < 8; ++j )
|
||||
{
|
||||
const SFVEC3F OP = pointPlane - box[j];
|
||||
const float dot = glm::dot( OP, normalPlane );
|
||||
|
||||
if( dot < 0.0f )
|
||||
{
|
||||
out_side++;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( out_side == 4 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -24,13 +24,12 @@
|
|||
|
||||
/**
|
||||
* @file cfrustum.h
|
||||
* @brief
|
||||
* @brief implements a frustum that is used to test ray pack tests
|
||||
*/
|
||||
|
||||
#ifndef _CFRUSTUM_H_
|
||||
#define _CFRUSTUM_H_
|
||||
|
||||
#include "plugins/3dapi/xv3d_types.h"
|
||||
#include "shapes3D/cbbox.h"
|
||||
#include "ray.h"
|
||||
|
||||
|
@ -39,13 +38,32 @@
|
|||
#if 0
|
||||
#error not implemented
|
||||
#else
|
||||
GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) CFRUSTUM
|
||||
struct CFRUSTUM
|
||||
{
|
||||
SFVEC3F m_normals[4];
|
||||
SFVEC3F m_point[4];
|
||||
|
||||
void GenerateFrustum( const RAY &topLeft, const RAY &topRight, const RAY &bottomLeft, const RAY &bottomRight );
|
||||
public:
|
||||
/**
|
||||
* @brief GenerateFrustum
|
||||
* @param topLeft
|
||||
* @param topRight
|
||||
* @param bottomLeft
|
||||
* @param bottomRight
|
||||
*/
|
||||
void GenerateFrustum( const RAY &topLeft,
|
||||
const RAY &topRight,
|
||||
const RAY &bottomLeft,
|
||||
const RAY &bottomRight );
|
||||
|
||||
/**
|
||||
* @brief Intersect - Intersects a bbox with this frustum
|
||||
* @param aBBox: a bbox to test
|
||||
* @return true if the bbox intersects this frustum
|
||||
*/
|
||||
bool Intersect( const CBBOX &aBBox ) const;
|
||||
|
||||
private:
|
||||
SFVEC3F m_normals[4];
|
||||
SFVEC3F m_point[4];
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* 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 clight.h
|
||||
* @brief declare and implement light types classes
|
||||
*/
|
||||
|
||||
#ifndef _CLIGHT_H_
|
||||
#define _CLIGHT_H_
|
||||
|
||||
#include "ray.h"
|
||||
#include "hitinfo.h"
|
||||
|
||||
/// A base light class to derive to implement other light classes
|
||||
class CLIGHT
|
||||
{
|
||||
public:
|
||||
CLIGHT() { m_castShadow = true; }
|
||||
|
||||
virtual ~CLIGHT() {}
|
||||
|
||||
/**
|
||||
* @brief GetLightParameters - Get parameters from this light
|
||||
* @param aHitPoint: input hit position
|
||||
* @param aOutVectorToLight: a vector that points from the hit
|
||||
* position in direction to the light
|
||||
* @param aOutLightColor: the color of this light
|
||||
* @param aOutDistance: the distance from the point to the light
|
||||
*/
|
||||
virtual void GetLightParameters( const SFVEC3F &aHitPoint,
|
||||
SFVEC3F &aOutVectorToLight,
|
||||
SFVEC3F &aOutLightColor,
|
||||
float &aOutDistance ) const = 0;
|
||||
|
||||
void SetCastShadows( bool aCastShadow ) { m_castShadow = aCastShadow; }
|
||||
bool GetCastShadows() const { return m_castShadow; }
|
||||
|
||||
protected:
|
||||
bool m_castShadow;
|
||||
};
|
||||
|
||||
|
||||
/// Point light based on:
|
||||
/// http://ogldev.atspace.co.uk/www/tutorial20/tutorial20.html
|
||||
class CPOINTLIGHT : public CLIGHT
|
||||
{
|
||||
|
||||
public:
|
||||
CPOINTLIGHT( const SFVEC3F &aPos, const SFVEC3F &aColor )
|
||||
{
|
||||
m_position = aPos;
|
||||
m_color = aColor;
|
||||
m_att_constant = 1.0f;
|
||||
m_att_linear = 0.5f;
|
||||
m_att_exp = 0.25f;
|
||||
m_castShadow = true;
|
||||
}
|
||||
|
||||
// Imported functions from CLIGHT
|
||||
|
||||
void GetLightParameters( const SFVEC3F &aHitPoint,
|
||||
SFVEC3F &aOutVectorToLight,
|
||||
SFVEC3F &aOutLightColor,
|
||||
float &aOutDistance ) const
|
||||
{
|
||||
const SFVEC3F vectorLight = m_position - aHitPoint;
|
||||
|
||||
aOutDistance = glm::length( vectorLight );
|
||||
aOutVectorToLight = vectorLight / aOutDistance; // normalize
|
||||
|
||||
|
||||
float att = 1.0f / ( m_att_constant +
|
||||
m_att_linear * aOutDistance +
|
||||
m_att_exp * aOutDistance * aOutDistance );
|
||||
|
||||
if( att <= 0.0f )
|
||||
aOutLightColor = SFVEC3F( 0.0f, 0.0f, 0.0f );
|
||||
else
|
||||
aOutLightColor = m_color * att;
|
||||
}
|
||||
|
||||
private:
|
||||
SFVEC3F m_position;
|
||||
SFVEC3F m_color;
|
||||
|
||||
float m_att_constant;
|
||||
float m_att_linear;
|
||||
float m_att_exp;
|
||||
};
|
||||
|
||||
|
||||
/// Directional light - a light based only on a direction vector
|
||||
class CDIRECTIONALLIGHT : public CLIGHT
|
||||
{
|
||||
public:
|
||||
CDIRECTIONALLIGHT( const SFVEC3F &aDir, const SFVEC3F &aColor )
|
||||
{
|
||||
// Invert light direction and make sure it is normalized
|
||||
m_inv_direction = glm::normalize( -aDir );
|
||||
m_color = aColor;
|
||||
m_castShadow = true; // Set as default to cast shadows
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SetDirection - Set directional light orientation
|
||||
* @param aDir: vector from the light
|
||||
*/
|
||||
void SetDirection( const SFVEC3F &aDir ) { m_inv_direction = -aDir; }
|
||||
|
||||
// Imported functions from CLIGHT
|
||||
|
||||
void GetLightParameters( const SFVEC3F &aHitPoint,
|
||||
SFVEC3F &aOutVectorToLight,
|
||||
SFVEC3F &aOutLightColor,
|
||||
float &aOutDistance ) const
|
||||
{
|
||||
(void)aHitPoint; // unused
|
||||
|
||||
aOutVectorToLight = m_inv_direction;
|
||||
aOutDistance = std::numeric_limits<float>::infinity();
|
||||
aOutLightColor = m_color;
|
||||
}
|
||||
|
||||
private:
|
||||
SFVEC3F m_inv_direction; ///< oposite direction of the light
|
||||
SFVEC3F m_color; ///< light color
|
||||
};
|
||||
|
||||
|
||||
typedef std::list< CLIGHT * > LIST_LIGHT;
|
||||
|
||||
|
||||
/// A light contariner. It will add lights and remove it in the end
|
||||
class CLIGHTCONTAINER
|
||||
{
|
||||
public:
|
||||
CLIGHTCONTAINER() {}
|
||||
|
||||
~CLIGHTCONTAINER() { Clear(); }
|
||||
|
||||
/**
|
||||
* @brief Clear - Remove all lights from the container
|
||||
*/
|
||||
void Clear()
|
||||
{
|
||||
if( !m_lights.empty() )
|
||||
{
|
||||
for( LIST_LIGHT::iterator ii = m_lights.begin();
|
||||
ii != m_lights.end();
|
||||
--ii )
|
||||
{
|
||||
delete *ii;
|
||||
*ii = NULL;
|
||||
}
|
||||
|
||||
m_lights.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add - Add a light to the container
|
||||
* @param aLight
|
||||
*/
|
||||
void Add( CLIGHT *aLight )
|
||||
{
|
||||
if( aLight )
|
||||
m_lights.push_back( aLight );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GetList - get light list of this container
|
||||
* @return a list of lights
|
||||
*/
|
||||
const LIST_LIGHT &GetList() const { return m_lights; }
|
||||
|
||||
private:
|
||||
LIST_LIGHT m_lights; ///< list of lights
|
||||
};
|
||||
|
||||
#endif // _CLIGHT_H_
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* 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 cmaterial.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "cmaterial.h"
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
||||
CMATERIAL::CMATERIAL()
|
||||
{
|
||||
m_ambientColor = SFVEC3F( 0.2f, 0.2f, 0.2f );
|
||||
m_emissiveColor = SFVEC3F( 0.0f, 0.0f, 0.0f );
|
||||
m_specularColor = SFVEC3F( 1.0f, 1.0f, 1.0f );
|
||||
m_shinness = 50.2f;
|
||||
m_transparency = 0.0f; // completely opaque
|
||||
m_cast_shadows = true;
|
||||
m_reflection = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
CMATERIAL::CMATERIAL( const SFVEC3F &aAmbient,
|
||||
const SFVEC3F &aEmissive,
|
||||
const SFVEC3F &aSpecular,
|
||||
float aShinness,
|
||||
float aTransparency,
|
||||
float aReflection )
|
||||
{
|
||||
wxASSERT( aReflection >= 0.0f );
|
||||
wxASSERT( aReflection <= 1.0f );
|
||||
|
||||
wxASSERT( aTransparency >= 0.0f );
|
||||
wxASSERT( aTransparency <= 1.0f );
|
||||
|
||||
wxASSERT( aShinness >= 0.0f );
|
||||
wxASSERT( aShinness <= 180.0f );
|
||||
|
||||
m_ambientColor = aAmbient;
|
||||
m_emissiveColor = aEmissive;
|
||||
m_specularColor = aSpecular;
|
||||
m_shinness = aShinness;
|
||||
m_transparency = aTransparency;
|
||||
m_reflection = aReflection;
|
||||
m_cast_shadows = true;
|
||||
}
|
||||
|
||||
|
||||
// This may be a good value if based on nr of lights
|
||||
// that contribute to the illumination of that point
|
||||
#define AMBIENT_FACTOR 0.160f
|
||||
#define SPECULAR_FACTOR 1.000f
|
||||
|
||||
// https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model
|
||||
SFVEC3F CBLINN_PHONG_MATERIAL::Shade( const RAY &aRay,
|
||||
const HITINFO &aHitInfo,
|
||||
float NdotL,
|
||||
const SFVEC3F &aDiffuseObjColor,
|
||||
const SFVEC3F &aDirToLight,
|
||||
const SFVEC3F &aLightColor,
|
||||
float aShadowAttenuationFactor ) const
|
||||
{
|
||||
wxASSERT( NdotL >= FLT_EPSILON );
|
||||
|
||||
//const float ambientFactor = AMBIENT_FACTOR;
|
||||
|
||||
// This is a hack to get some kind of fake ambient illumination
|
||||
// There is no logic behind this, just pure artistic experimentation
|
||||
const float ambientFactor = glm::max( ( (1.0f - NdotL) /** (1.0f - NdotL)*/ ) *
|
||||
( AMBIENT_FACTOR + AMBIENT_FACTOR ),
|
||||
AMBIENT_FACTOR );
|
||||
|
||||
if( aShadowAttenuationFactor > FLT_EPSILON )
|
||||
{
|
||||
// Calculate the diffuse light factoring in light color,
|
||||
// power and the attenuation
|
||||
const SFVEC3F diffuse = NdotL * aLightColor;
|
||||
|
||||
// Calculate the half vector between the light vector and the view vector.
|
||||
const SFVEC3F H = glm::normalize( aDirToLight - aRay.m_Dir );
|
||||
|
||||
//Intensity of the specular light
|
||||
const float NdotH = glm::dot( H, aHitInfo.m_HitNormal );
|
||||
const float intensitySpecular = glm::pow( glm::max( NdotH, 0.0f ),
|
||||
m_shinness );
|
||||
|
||||
return m_ambientColor * ambientFactor +
|
||||
aShadowAttenuationFactor * ( diffuse * aDiffuseObjColor +
|
||||
SPECULAR_FACTOR *
|
||||
aLightColor *
|
||||
intensitySpecular *
|
||||
m_specularColor );
|
||||
}
|
||||
|
||||
return m_ambientColor * ambientFactor;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -33,37 +33,57 @@
|
|||
#include "ray.h"
|
||||
#include "hitinfo.h"
|
||||
|
||||
///
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CMATERIAL
|
||||
|
||||
/// A base material class that can be used to derive a material implementation
|
||||
class CMATERIAL
|
||||
{
|
||||
public:
|
||||
CMATERIAL();
|
||||
CMATERIAL( const SFVEC3F &aAmbient, const SFVEC3F &aEmissive, const SFVEC3F &aSpecular, float aShinness, float aTransparency );
|
||||
CMATERIAL( const SFVEC3F &aAmbient,
|
||||
const SFVEC3F &aEmissive,
|
||||
const SFVEC3F &aSpecular,
|
||||
float aShinness,
|
||||
float aTransparency,
|
||||
float aReflection );
|
||||
|
||||
const SFVEC3F &GetAmbientColor() const { return m_ambientColor; }
|
||||
const SFVEC3F &GetAmbientColor() const { return m_ambientColor; }
|
||||
const SFVEC3F &GetEmissiveColor() const { return m_emissiveColor; }
|
||||
const SFVEC3F &GetSpecularColor() const { return m_specularColor; }
|
||||
|
||||
float GetShinness() const { return m_shinness; }
|
||||
float GetShinness() const { return m_shinness; }
|
||||
float GetTransparency() const { return m_transparency; }
|
||||
float GetReflection() const { return m_reflection; }
|
||||
|
||||
/**
|
||||
* @brief SetCastShadows - Set if the material can receive shadows
|
||||
* @param aCastShadows - true yes it can, false not it cannot
|
||||
*/
|
||||
void SetCastShadows( bool aCastShadows ) { m_cast_shadows = aCastShadows; }
|
||||
|
||||
void SetCastShadows( bool aCastShadows ) { m_cast_shadows = aCastShadows; }
|
||||
bool GetCastShadows() const { return m_cast_shadows; }
|
||||
|
||||
virtual SFVEC3F Shade( const RAY &aRay, const HITINFO &aHitInfo, float NdotL, const SFVEC3F &aDiffuseObjColor, const SFVEC3F &aDirToLight, const SFVEC3F &aLightColor, bool aIsInShadow ) const = 0;
|
||||
/**
|
||||
* @brief Shade - Shades an intersection point
|
||||
* @param aRay: the camera ray that hits the object
|
||||
* @param aHitInfo: the hit information
|
||||
* @param NdotL: the dot product between Normal and Light
|
||||
* @param aDiffuseObjColor: diffuse object color
|
||||
* @param aDirToLight: a vector of the incident light direction
|
||||
* @param aLightColor: the light color
|
||||
* @param aShadowAttenuationFactor 0.0f total in shadow, 1.0f completely not in shadow
|
||||
* @return the resultant color
|
||||
*/
|
||||
virtual SFVEC3F Shade( const RAY &aRay,
|
||||
const HITINFO &aHitInfo,
|
||||
float NdotL,
|
||||
const SFVEC3F &aDiffuseObjColor,
|
||||
const SFVEC3F &aDirToLight,
|
||||
const SFVEC3F &aLightColor,
|
||||
float aShadowAttenuationFactor ) const = 0;
|
||||
|
||||
/*
|
||||
|
||||
|
||||
virtual SFVEC3F GetReflect(Vec3f point){ return reflectiveColor;}
|
||||
virtual Vec3f GetTrans(Vec3f point){ return transparentColor;}
|
||||
virtual float getIndexOfRefrac(Vec3f point){ return indexOfRefraction;}
|
||||
|
||||
virtual bool isReflect(Vec3f point){return ((reflectiveColor.x()>0)||(reflectiveColor.y()>0)||(reflectiveColor.z()>0));}
|
||||
virtual bool isTransparent(Vec3f point){return ((transparentColor.x()>0)||(transparentColor.y()>0)||(transparentColor.z()>0));}
|
||||
*/
|
||||
protected:
|
||||
SFVEC3F m_ambientColor;
|
||||
|
||||
// NOTE: we will not use diffuse color material here,
|
||||
// because it will be stored in object, since there are objects (i.e: triangles)
|
||||
// that can have per vertex color
|
||||
|
@ -72,12 +92,14 @@ protected:
|
|||
SFVEC3F m_specularColor;
|
||||
float m_shinness;
|
||||
float m_transparency; ///< 1.0 is completely transparent, 0.0 completely opaque
|
||||
float m_reflection; ///< 1.0 completely reflective, 0.0 no reflective
|
||||
bool m_cast_shadows; ///< true if this object will block the light
|
||||
};
|
||||
|
||||
|
||||
/// Blinn Phong based material
|
||||
/// https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CBLINN_PHONG_MATERIAL : public CMATERIAL
|
||||
class CBLINN_PHONG_MATERIAL : public CMATERIAL
|
||||
{
|
||||
public:
|
||||
CBLINN_PHONG_MATERIAL() : CMATERIAL() {}
|
||||
|
@ -86,10 +108,22 @@ public:
|
|||
const SFVEC3F &aEmissive,
|
||||
const SFVEC3F &aSpecular,
|
||||
float aShinness,
|
||||
float aTransparency ) :
|
||||
CMATERIAL( aAmbient, aEmissive, aSpecular, aShinness, aTransparency ) {}
|
||||
float aTransparency,
|
||||
float aReflection ) : CMATERIAL( aAmbient,
|
||||
aEmissive,
|
||||
aSpecular,
|
||||
aShinness,
|
||||
aTransparency,
|
||||
aReflection ) {}
|
||||
|
||||
SFVEC3F Shade( const RAY &aRay, const HITINFO &aHitInfo, float NdotL, const SFVEC3F &aDiffuseObjColor, const SFVEC3F &aDirToLight, const SFVEC3F &aLightColor, bool aIsInShadow ) const;
|
||||
// Imported from CMATERIAL
|
||||
SFVEC3F Shade( const RAY &aRay,
|
||||
const HITINFO &aHitInfo,
|
||||
float NdotL,
|
||||
const SFVEC3F &aDiffuseObjColor,
|
||||
const SFVEC3F &aDirToLight,
|
||||
const SFVEC3F &aLightColor,
|
||||
float aShadowAttenuationFactor ) const;
|
||||
};
|
||||
|
||||
#endif // _CMATERIAL_H_
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -30,7 +30,6 @@
|
|||
#ifndef _HITINFO_H_
|
||||
#define _HITINFO_H_
|
||||
|
||||
#include "plugins/3dapi/xv3d_types.h"
|
||||
#include "raypacket.h"
|
||||
|
||||
//#define RAYTRACING_RAY_STATISTICS
|
||||
|
@ -38,15 +37,16 @@
|
|||
class COBJECT;
|
||||
|
||||
/// Stores the hit information of a ray with a point on the surface of a object
|
||||
GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) HITINFO
|
||||
struct HITINFO
|
||||
{
|
||||
SFVEC3F m_HitNormal; ///< (12) normal at the hit point
|
||||
float m_tHit; ///< ( 4) distance
|
||||
|
||||
const COBJECT *pHitObject; ///< ( 4) Object that was hitted
|
||||
SFVEC2F m_UV; ///< ( 8) 2-D texture coordinates
|
||||
unsigned int m_acc_node_info; ///< ( 4) The acc stores here the node that it hits
|
||||
|
||||
unsigned int m_acc_node_info; ///< ( 4) The acc should store here information (Ex: the node that it hits)
|
||||
float m_ShadowFactor; ///< ( 4) Shadow attenuation (1.0 no shadow, 0.0f darkness)
|
||||
|
||||
#ifdef RAYTRACING_RAY_STATISTICS
|
||||
// Statistics
|
||||
|
@ -55,11 +55,11 @@ GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) HITINFO
|
|||
#endif
|
||||
};
|
||||
|
||||
GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) HITINFO_PACKET
|
||||
|
||||
struct HITINFO_PACKET
|
||||
{
|
||||
bool m_hitresult;
|
||||
HITINFO m_HitInfo;
|
||||
|
||||
};
|
||||
|
||||
#endif // _HITINFO_H_
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* 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 mortoncodes.cpp
|
||||
* @brief Implementes Morton Codes base on the implementation of Fabian “ryg” Giesen
|
||||
* https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
|
||||
*/
|
||||
|
||||
#include "mortoncodes.h"
|
||||
|
||||
|
||||
// "Insert" a 0 bit after each of the 16 low bits of x
|
||||
uint32_t Part1By1( uint32_t x )
|
||||
{
|
||||
x &= 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210
|
||||
x = (x ^ (x << 8)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210
|
||||
x = (x ^ (x << 4)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210
|
||||
x = (x ^ (x << 2)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10
|
||||
x = (x ^ (x << 1)) & 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
// "Insert" two 0 bits after each of the 10 low bits of x
|
||||
uint32_t Part1By2( uint32_t x )
|
||||
{
|
||||
x &= 0x000003ff; // x = ---- ---- ---- ---- ---- --98 7654 3210
|
||||
x = (x ^ (x << 16)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210
|
||||
x = (x ^ (x << 8)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210
|
||||
x = (x ^ (x << 4)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10
|
||||
x = (x ^ (x << 2)) & 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
// Inverse of Part1By1 - "delete" all odd-indexed bits
|
||||
uint32_t Compact1By1( uint32_t x )
|
||||
{
|
||||
x &= 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
|
||||
x = (x ^ (x >> 1)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10
|
||||
x = (x ^ (x >> 2)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210
|
||||
x = (x ^ (x >> 4)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210
|
||||
x = (x ^ (x >> 8)) & 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
// Inverse of Part1By2 - "delete" all bits not at positions divisible by 3
|
||||
uint32_t Compact1By2( uint32_t x )
|
||||
{
|
||||
x &= 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0
|
||||
x = (x ^ (x >> 2)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10
|
||||
x = (x ^ (x >> 4)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210
|
||||
x = (x ^ (x >> 8)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210
|
||||
x = (x ^ (x >> 16)) & 0x000003ff; // x = ---- ---- ---- ---- ---- --98 7654 3210
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
uint32_t EncodeMorton2( uint32_t x, uint32_t y )
|
||||
{
|
||||
return ( Part1By1( y ) << 1 ) + Part1By1( x );
|
||||
}
|
||||
|
||||
|
||||
uint32_t EncodeMorton3( uint32_t x, uint32_t y, uint32_t z )
|
||||
{
|
||||
return ( Part1By2( z ) << 2 ) + ( Part1By2( y ) << 1 ) + Part1By2( x );
|
||||
}
|
||||
|
||||
|
||||
uint32_t DecodeMorton2X( uint32_t code )
|
||||
{
|
||||
return Compact1By1( code >> 0 );
|
||||
}
|
||||
|
||||
|
||||
uint32_t DecodeMorton2Y( uint32_t code )
|
||||
{
|
||||
return Compact1By1( code >> 1 );
|
||||
}
|
||||
|
||||
|
||||
uint32_t DecodeMorton3X( uint32_t code )
|
||||
{
|
||||
return Compact1By2( code >> 0 );
|
||||
}
|
||||
|
||||
|
||||
uint32_t DecodeMorton3Y( uint32_t code )
|
||||
{
|
||||
return Compact1By2( code >> 1 );
|
||||
}
|
||||
|
||||
|
||||
uint32_t DecodeMorton3Z( uint32_t code )
|
||||
{
|
||||
return Compact1By2( code >> 2 );
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 mortoncodes.h
|
||||
* @brief Implementes Morton Codes
|
||||
* https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
|
||||
* http://www.forceflow.be/2013/10/07/morton-encodingdecoding-through-bit-interleaving-implementations/
|
||||
*/
|
||||
|
||||
#ifndef _MORTONCODES_H_
|
||||
#define _MORTONCODES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t EncodeMorton2( uint32_t x, uint32_t y );
|
||||
uint32_t EncodeMorton3( uint32_t x, uint32_t y, uint32_t z );
|
||||
|
||||
uint32_t DecodeMorton2X( uint32_t code );
|
||||
uint32_t DecodeMorton2Y( uint32_t code );
|
||||
|
||||
uint32_t DecodeMorton3X( uint32_t code );
|
||||
uint32_t DecodeMorton3Y( uint32_t code );
|
||||
uint32_t DecodeMorton3Z( uint32_t code );
|
||||
|
||||
#endif // _MORTONCODES_H_
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -29,7 +29,7 @@
|
|||
|
||||
|
||||
#include "ray.h"
|
||||
#include "3d_math/3d_fastmath.h"
|
||||
#include "../../3d_fastmath.h"
|
||||
#include <stdio.h>
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
@ -189,7 +189,9 @@ void RAY::Init( const SFVEC3F& o, const SFVEC3F& d )
|
|||
bool IntersectSegment( const SFVEC2F &aStartA, const SFVEC2F &aEnd_minus_startA,
|
||||
const SFVEC2F &aStartB, const SFVEC2F &aEnd_minus_startB )
|
||||
{
|
||||
float rxs = aEnd_minus_startA.x * aEnd_minus_startB.y - aEnd_minus_startA.y * aEnd_minus_startB.x;
|
||||
float rxs = aEnd_minus_startA.x *
|
||||
aEnd_minus_startB.y - aEnd_minus_startA.y *
|
||||
aEnd_minus_startB.x;
|
||||
|
||||
if( fabs(rxs) > glm::epsilon<float>() )
|
||||
{
|
||||
|
@ -213,6 +215,7 @@ bool IntersectSegment( const SFVEC2F &aStartA, const SFVEC2F &aEnd_minus_startA,
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
// !TODO: not tested
|
||||
bool RAY::IntersectSphere( const SFVEC3F &aCenter, float aRadius, float &aOutT0, float &aOutT1 ) const
|
||||
{
|
||||
|
@ -271,6 +274,7 @@ bool RAY::IntersectSphere( const SFVEC3F &aCenter, float aRadius, float &aOutT0,
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
RAYSEG2D::RAYSEG2D( const SFVEC2F& s, const SFVEC2F& e )
|
||||
{
|
||||
m_Start = s;
|
||||
|
@ -290,17 +294,21 @@ RAYSEG2D::RAYSEG2D( const SFVEC2F& s, const SFVEC2F& e )
|
|||
}
|
||||
|
||||
|
||||
bool RAYSEG2D::IntersectSegment( const SFVEC2F &aStart, const SFVEC2F &aEnd_minus_start, float *aOutT ) const
|
||||
bool RAYSEG2D::IntersectSegment( const SFVEC2F &aStart,
|
||||
const SFVEC2F &aEnd_minus_start,
|
||||
float *aOutT ) const
|
||||
{
|
||||
float rxs = m_End_minus_start.x * aEnd_minus_start.y - m_End_minus_start.y * aEnd_minus_start.x;
|
||||
float rxs = m_End_minus_start.x *
|
||||
aEnd_minus_start.y - m_End_minus_start.y *
|
||||
aEnd_minus_start.x;
|
||||
|
||||
if( fabs(rxs) > glm::epsilon<float>() )
|
||||
if( fabs( rxs ) > glm::epsilon<float>() )
|
||||
{
|
||||
float inv_rxs = 1.0f / rxs;
|
||||
const float inv_rxs = 1.0f / rxs;
|
||||
|
||||
SFVEC2F pq = aStart - m_Start;
|
||||
const SFVEC2F pq = aStart - m_Start;
|
||||
|
||||
float t = (pq.x * aEnd_minus_start.y - pq.y * aEnd_minus_start.x) * inv_rxs;
|
||||
const float t = (pq.x * aEnd_minus_start.y - pq.y * aEnd_minus_start.x) * inv_rxs;
|
||||
|
||||
if( (t < 0.0f) || (t > 1.0f) )
|
||||
return false;
|
||||
|
@ -324,7 +332,7 @@ float RAYSEG2D::DistanceToPointSquared( const SFVEC2F &aPoint ) const
|
|||
{
|
||||
SFVEC2F p = aPoint - m_Start;
|
||||
|
||||
float c1 = glm::dot( p, m_End_minus_start );
|
||||
const float c1 = glm::dot( p, m_End_minus_start );
|
||||
|
||||
if( c1 < FLT_EPSILON )
|
||||
return glm::dot( p, p );
|
||||
|
@ -333,8 +341,9 @@ float RAYSEG2D::DistanceToPointSquared( const SFVEC2F &aPoint ) const
|
|||
p = aPoint - m_End;
|
||||
else
|
||||
{
|
||||
float b = c1 / m_DOT_End_minus_start;
|
||||
SFVEC2F pb = m_Start + m_End_minus_start * b;
|
||||
const float b = c1 / m_DOT_End_minus_start;
|
||||
const SFVEC2F pb = m_Start + m_End_minus_start * b;
|
||||
|
||||
p = aPoint - pb;
|
||||
}
|
||||
|
||||
|
@ -342,21 +351,26 @@ float RAYSEG2D::DistanceToPointSquared( const SFVEC2F &aPoint ) const
|
|||
}
|
||||
|
||||
|
||||
bool RAYSEG2D::IntersectCircle( const SFVEC2F &aCenter, float aRadius, float *aOutT0, float *aOutT1, SFVEC2F *aOutNormalT0, SFVEC2F *aOutNormalT1 ) const
|
||||
bool RAYSEG2D::IntersectCircle( const SFVEC2F &aCenter,
|
||||
float aRadius,
|
||||
float *aOutT0,
|
||||
float *aOutT1,
|
||||
SFVEC2F *aOutNormalT0,
|
||||
SFVEC2F *aOutNormalT1 ) const
|
||||
{
|
||||
// This code used directly from Steve Marschner's CS667 framework
|
||||
// http://cs665pd.googlecode.com/svn/trunk/photon/sphere.cpp
|
||||
|
||||
// Compute some factors used in computation
|
||||
float qx = m_Start.x - aCenter.x;
|
||||
float qy = m_Start.y - aCenter.y;
|
||||
const float qx = m_Start.x - aCenter.x;
|
||||
const float qy = m_Start.y - aCenter.y;
|
||||
|
||||
float qd = qx * m_Dir.x + qy * m_Dir.y;
|
||||
float qq = qx * qx + qy * qy;
|
||||
const float qd = qx * m_Dir.x + qy * m_Dir.y;
|
||||
const float qq = qx * qx + qy * qy;
|
||||
|
||||
// solving the quadratic equation for t at the pts of intersection
|
||||
// dd*t^2 + (2*qd)*t + (qq-r^2) = 0
|
||||
float discriminantsqr = (qd * qd - (qq - aRadius * aRadius));
|
||||
const float discriminantsqr = (qd * qd - (qq - aRadius * aRadius));
|
||||
|
||||
// If the discriminant is less than zero, there is no intersection
|
||||
if( discriminantsqr < FLT_EPSILON )
|
||||
|
@ -365,9 +379,9 @@ bool RAYSEG2D::IntersectCircle( const SFVEC2F &aCenter, float aRadius, float *aO
|
|||
|
||||
// Otherwise check and make sure that the intersections occur on the ray (t
|
||||
// > 0) and return the closer one
|
||||
float discriminant = sqrt(discriminantsqr);
|
||||
float t1 = (-qd - discriminant);
|
||||
float t2 = (-qd + discriminant);
|
||||
const float discriminant = sqrt( discriminantsqr );
|
||||
const float t1 = (-qd - discriminant);
|
||||
const float t2 = (-qd + discriminant);
|
||||
|
||||
if( (( t1 < 0.0f ) || ( t1 > m_Length ) ) &&
|
||||
(( t2 < 0.0f ) || ( t2 > m_Length ) ) )
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
#ifndef _RAY_H_
|
||||
#define _RAY_H_
|
||||
|
||||
#include "plugins/3dapi/xv3d_types.h"
|
||||
#include <plugins/3dapi/xv3d_types.h>
|
||||
|
||||
|
||||
enum RAY_CLASSIFICATION
|
||||
|
@ -40,7 +40,7 @@ enum RAY_CLASSIFICATION
|
|||
};
|
||||
|
||||
|
||||
GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAY
|
||||
struct RAY
|
||||
{
|
||||
SFVEC3F m_Origin;
|
||||
unsigned int rayID; ///< unique ray ID
|
||||
|
@ -57,16 +57,21 @@ GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAY
|
|||
|
||||
void Init( const SFVEC3F& o, const SFVEC3F& d );
|
||||
|
||||
bool IntersectSphere( const SFVEC3F &aCenter, float aRadius, float &aOutT0, float &aOutT1 ) const;
|
||||
bool IntersectSphere( const SFVEC3F &aCenter,
|
||||
float aRadius,
|
||||
float &aOutT0,
|
||||
float &aOutT1 ) const;
|
||||
|
||||
SFVEC3F at( float t ) const { return m_Origin + m_Dir * t; }
|
||||
SFVEC2F at2D( float t ) const { return SFVEC2F( m_Origin.x + m_Dir.x * t, m_Origin.y + m_Dir.y * t ); }
|
||||
|
||||
SFVEC2F at2D( float t ) const {
|
||||
return SFVEC2F( m_Origin.x + m_Dir.x * t, m_Origin.y + m_Dir.y * t ); }
|
||||
|
||||
void debug() const;
|
||||
};
|
||||
|
||||
|
||||
GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAY2D
|
||||
struct RAY2D
|
||||
{
|
||||
SFVEC2F m_Origin;
|
||||
SFVEC2F m_Dir;
|
||||
|
@ -78,7 +83,7 @@ GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAY2D
|
|||
};
|
||||
|
||||
|
||||
GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAYSEG2D
|
||||
struct RAYSEG2D
|
||||
{
|
||||
SFVEC2F m_Start;
|
||||
SFVEC2F m_End;
|
||||
|
@ -90,10 +95,19 @@ GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAYSEG2D
|
|||
|
||||
RAYSEG2D( const SFVEC2F& s, const SFVEC2F& e );
|
||||
|
||||
bool IntersectSegment( const SFVEC2F &aStart, const SFVEC2F &aEnd_minus_start, float *aOutT ) const;
|
||||
bool IntersectCircle( const SFVEC2F &aCenter, float aRadius, float *aOutT0, float *aOutT1, SFVEC2F *aOutNormalT0, SFVEC2F *aOutNormalT1 ) const;
|
||||
bool IntersectSegment( const SFVEC2F &aStart,
|
||||
const SFVEC2F &aEnd_minus_start,
|
||||
float *aOutT ) const;
|
||||
|
||||
bool IntersectCircle( const SFVEC2F &aCenter,
|
||||
float aRadius,
|
||||
float *aOutT0,
|
||||
float *aOutT1,
|
||||
SFVEC2F *aOutNormalT0,
|
||||
SFVEC2F *aOutNormalT1 ) const;
|
||||
|
||||
float DistanceToPointSquared( const SFVEC2F &aPoint ) const;
|
||||
|
||||
/**
|
||||
* Function atNormalized - returns the position at t
|
||||
* t - value 0.0 ... 1.0
|
||||
|
@ -109,7 +123,7 @@ bool IntersectSegment( const SFVEC2F &aStartA, const SFVEC2F &aEnd_minus_startA,
|
|||
|
||||
#if(GLM_ARCH != GLM_ARCH_PURE)
|
||||
/*
|
||||
GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAY4
|
||||
struct RAY4
|
||||
{
|
||||
glm::simdVec4 m_orgX; ///< x coordinate of ray origin
|
||||
glm::simdVec4 m_orgy; ///< y coordinate of ray origin
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* 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 raypacket.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "raypacket.h"
|
||||
#include "../3d_fastmath.h"
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
||||
RAYPACKET::RAYPACKET( const CCAMERA &aCamera, const SFVEC2I &aWindowsPosition )
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
|
||||
{
|
||||
for( unsigned int x = 0; x < RAYPACKET_DIM; ++x )
|
||||
{
|
||||
SFVEC3F rayOrigin;
|
||||
SFVEC3F rayDir;
|
||||
|
||||
aCamera.MakeRay( SFVEC2I( aWindowsPosition.x + x,
|
||||
aWindowsPosition.y + y ),
|
||||
rayOrigin, rayDir );
|
||||
|
||||
m_ray[i].Init( rayOrigin, rayDir );
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
wxASSERT( i == RAYPACKET_RAYS_PER_PACKET );
|
||||
|
||||
m_Frustum.GenerateFrustum(
|
||||
m_ray[ 0 * RAYPACKET_DIM + 0 ],
|
||||
m_ray[ 0 * RAYPACKET_DIM + (RAYPACKET_DIM - 1) ],
|
||||
m_ray[ (RAYPACKET_DIM - 1) * RAYPACKET_DIM + 0 ],
|
||||
m_ray[ (RAYPACKET_DIM - 1) * RAYPACKET_DIM + (RAYPACKET_DIM - 1) ] );
|
||||
|
||||
}
|
||||
|
||||
|
||||
RAYPACKET::RAYPACKET( const CCAMERA &aCamera,
|
||||
const SFVEC2I &aWindowsPosition,
|
||||
const SFVEC3F &aDirectionDisplacementFactor )
|
||||
{
|
||||
unsigned int i = 0;
|
||||
for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
|
||||
for( unsigned int x = 0; x < RAYPACKET_DIM; ++x )
|
||||
{
|
||||
SFVEC3F rayOrigin;
|
||||
SFVEC3F rayDir;
|
||||
|
||||
aCamera.MakeRay( SFVEC2I( aWindowsPosition.x + x,
|
||||
aWindowsPosition.y + y ),
|
||||
rayOrigin, rayDir );
|
||||
|
||||
const SFVEC3F randVector = SFVEC3F( Fast_RandFloat() * aDirectionDisplacementFactor.x,
|
||||
Fast_RandFloat() * aDirectionDisplacementFactor.y,
|
||||
Fast_RandFloat() * aDirectionDisplacementFactor.z );
|
||||
|
||||
m_ray[i].Init( rayOrigin,
|
||||
glm::normalize( rayDir + randVector ) );
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
wxASSERT( i == RAYPACKET_RAYS_PER_PACKET );
|
||||
|
||||
m_Frustum.GenerateFrustum( m_ray[ 0 * RAYPACKET_DIM + 0 ],
|
||||
m_ray[ 0 * RAYPACKET_DIM + (RAYPACKET_DIM - 1) ],
|
||||
m_ray[ (RAYPACKET_DIM - 1) * RAYPACKET_DIM + 0 ],
|
||||
m_ray[ (RAYPACKET_DIM - 1) * RAYPACKET_DIM + (RAYPACKET_DIM - 1) ] );
|
||||
|
||||
}
|
||||
|
||||
|
||||
RAYPACKET::RAYPACKET( const CCAMERA &aCamera,
|
||||
const SFVEC2I &aWindowsPosition,
|
||||
unsigned int aPixelMultiple )
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for( unsigned int y = 0; y < RAYPACKET_DIM; y++ )
|
||||
{
|
||||
for( unsigned int x = 0; x < RAYPACKET_DIM; x++ )
|
||||
{
|
||||
SFVEC3F rayOrigin;
|
||||
SFVEC3F rayDir;
|
||||
|
||||
aCamera.MakeRay( SFVEC2I( aWindowsPosition.x + x * aPixelMultiple,
|
||||
aWindowsPosition.y + y * aPixelMultiple),
|
||||
rayOrigin, rayDir );
|
||||
|
||||
m_ray[i].Init( rayOrigin, rayDir );
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
wxASSERT( i == RAYPACKET_RAYS_PER_PACKET );
|
||||
|
||||
m_Frustum.GenerateFrustum( m_ray[ 0 * RAYPACKET_DIM + 0 ],
|
||||
m_ray[ 0 * RAYPACKET_DIM + (RAYPACKET_DIM - 1) ],
|
||||
m_ray[ (RAYPACKET_DIM - 1) * RAYPACKET_DIM + 0 ],
|
||||
m_ray[ (RAYPACKET_DIM - 1) * RAYPACKET_DIM + (RAYPACKET_DIM - 1) ] );
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -40,13 +40,21 @@
|
|||
#define RAYPACKET_RAYS_PER_PACKET (RAYPACKET_DIM * RAYPACKET_DIM)
|
||||
|
||||
|
||||
GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAYPACKET
|
||||
struct RAYPACKET
|
||||
{
|
||||
CFRUSTUM m_Frustum;
|
||||
RAY m_ray[RAYPACKET_RAYS_PER_PACKET];
|
||||
|
||||
RAYPACKET( const CCAMERA &aCamera, const SFVEC2I &aWindowsPosition );
|
||||
RAYPACKET( const CCAMERA &aCamera, const SFVEC2I &aWindowsPosition, unsigned int aPixelMultiple );
|
||||
RAYPACKET( const CCAMERA &aCamera,
|
||||
const SFVEC2I &aWindowsPosition );
|
||||
|
||||
RAYPACKET( const CCAMERA &aCamera,
|
||||
const SFVEC2I &aWindowsPosition,
|
||||
const SFVEC3F &aDirectionDisplacementFactor );
|
||||
|
||||
RAYPACKET( const CCAMERA &aCamera,
|
||||
const SFVEC2I &aWindowsPosition,
|
||||
unsigned int aPixelMultiple );
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@gmail.com>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -27,7 +27,7 @@
|
|||
* @brief Bounding Box class implementation
|
||||
*/
|
||||
|
||||
#include "3d_math/3d_fastmath.h"
|
||||
#include "3d_fastmath.h"
|
||||
|
||||
#include "cbbox2d.h"
|
||||
#include <fctsys.h>
|
||||
|
@ -106,11 +106,13 @@ void CBBOX2D::Union( const SFVEC2F &aPoint )
|
|||
|
||||
void CBBOX2D::Union( const CBBOX2D &aBBox )
|
||||
{
|
||||
// get the minimun value between the added bounding box and the existent bounding box
|
||||
// get the minimun value between the added bounding box and
|
||||
// the existent bounding box
|
||||
m_min.x = fminf( m_min.x, aBBox.m_min.x );
|
||||
m_min.y = fminf( m_min.y, aBBox.m_min.y );
|
||||
|
||||
// get the maximun value between the added bounding box and the existent bounding box
|
||||
// get the maximun value between the added bounding box and
|
||||
// the existent bounding box
|
||||
m_max.x = fmaxf( m_max.x, aBBox.m_max.x );
|
||||
m_max.y = fmaxf( m_max.y, aBBox.m_max.y );
|
||||
}
|
||||
|
@ -131,7 +133,7 @@ SFVEC2F CBBOX2D::GetExtent() const
|
|||
unsigned int CBBOX2D::MaxDimension() const
|
||||
{
|
||||
unsigned int result = 0;
|
||||
SFVEC2F extent = GetExtent();
|
||||
const SFVEC2F extent = GetExtent();
|
||||
|
||||
if( extent.y > extent.x ) result = 1;
|
||||
|
||||
|
@ -141,7 +143,8 @@ unsigned int CBBOX2D::MaxDimension() const
|
|||
|
||||
float CBBOX2D::Perimeter() const
|
||||
{
|
||||
SFVEC2F extent = GetExtent();
|
||||
const SFVEC2F extent = GetExtent();
|
||||
|
||||
return 2.0f * ( extent.x + extent.y );
|
||||
}
|
||||
|
||||
|
@ -150,8 +153,8 @@ void CBBOX2D::Scale( float aScale )
|
|||
{
|
||||
wxASSERT( IsInitialized() );
|
||||
|
||||
SFVEC2F scaleV( aScale, aScale );
|
||||
SFVEC2F centerV = GetCenter();
|
||||
const SFVEC2F scaleV( aScale, aScale );
|
||||
const SFVEC2F centerV = GetCenter();
|
||||
|
||||
m_min = (m_min - centerV) * scaleV + centerV;
|
||||
m_max = (m_max - centerV) * scaleV + centerV;
|
||||
|
@ -184,18 +187,20 @@ bool CBBOX2D::Intersects( const SFVEC2F &aCenter, float aRadiusSquared ) const
|
|||
{
|
||||
float fDistSq = 0.0f;
|
||||
|
||||
for ( unsigned int i = 0; i < 2; i++ )
|
||||
for( unsigned int i = 0; i < 2; i++ )
|
||||
{
|
||||
if( aCenter[i] < m_min[i] )
|
||||
{
|
||||
float fDist = aCenter[i] - m_min[i];
|
||||
const float fDist = aCenter[i] - m_min[i];
|
||||
|
||||
fDistSq += fDist * fDist;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aCenter[i] > m_max[i] )
|
||||
{
|
||||
float fDist = aCenter[i] - m_max[i];
|
||||
const float fDist = aCenter[i] - m_max[i];
|
||||
|
||||
fDistSq += fDist * fDist;
|
||||
}
|
||||
}
|
||||
|
@ -210,8 +215,8 @@ bool CBBOX2D::Intersects( const CBBOX2D &aBBox ) const
|
|||
wxASSERT( IsInitialized() );
|
||||
wxASSERT( aBBox.IsInitialized() );
|
||||
|
||||
bool x = ( m_max.x >= aBBox.m_min.x ) && ( m_min.x <= aBBox.m_max.x );
|
||||
bool y = ( m_max.y >= aBBox.m_min.y ) && ( m_min.y <= aBBox.m_max.y );
|
||||
const bool x = ( m_max.x >= aBBox.m_min.x ) && ( m_min.x <= aBBox.m_max.x );
|
||||
const bool y = ( m_max.y >= aBBox.m_min.y ) && ( m_min.y <= aBBox.m_max.y );
|
||||
|
||||
return ( x && y );
|
||||
}
|
||||
|
@ -238,14 +243,14 @@ bool CBBOX2D::Intersect( const RAY2D &aRay, float *t ) const
|
|||
{
|
||||
wxASSERT( t );
|
||||
|
||||
float tx1 = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
float tx2 = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
const float tx1 = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
const float tx2 = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
float tmin = glm::min( tx1, tx2 );
|
||||
float tmax = glm::max( tx1, tx2 );
|
||||
|
||||
float ty1 = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
float ty2 = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
const float ty1 = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
const float ty2 = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
|
||||
tmin = glm::max( tmin, glm::min( ty1, ty2 ) );
|
||||
tmax = glm::min( tmax, glm::max( ty1, ty2 ) );
|
||||
|
@ -261,21 +266,22 @@ bool CBBOX2D::Intersect( const RAY2D &aRay, float *t ) const
|
|||
|
||||
bool CBBOX2D::Intersect( const RAYSEG2D &aRaySeg ) const
|
||||
{
|
||||
float tx1 = (m_min.x - aRaySeg.m_Start.x) * aRaySeg.m_InvDir.x;
|
||||
float tx2 = (m_max.x - aRaySeg.m_Start.x) * aRaySeg.m_InvDir.x;
|
||||
const float tx1 = (m_min.x - aRaySeg.m_Start.x) * aRaySeg.m_InvDir.x;
|
||||
const float tx2 = (m_max.x - aRaySeg.m_Start.x) * aRaySeg.m_InvDir.x;
|
||||
|
||||
float tmin = glm::min( tx1, tx2 );
|
||||
float tmax = glm::max( tx1, tx2 );
|
||||
|
||||
float ty1 = (m_min.y - aRaySeg.m_Start.y) * aRaySeg.m_InvDir.y;
|
||||
float ty2 = (m_max.y - aRaySeg.m_Start.y) * aRaySeg.m_InvDir.y;
|
||||
const float ty1 = (m_min.y - aRaySeg.m_Start.y) * aRaySeg.m_InvDir.y;
|
||||
const float ty2 = (m_max.y - aRaySeg.m_Start.y) * aRaySeg.m_InvDir.y;
|
||||
|
||||
tmin = glm::max( tmin, glm::min( ty1, ty2 ) );
|
||||
tmax = glm::min( tmax, glm::max( ty1, ty2 ) );
|
||||
|
||||
if( (tmax >= 0.0f) && (tmax >= tmin) )
|
||||
{
|
||||
float t = (tmin > 0.0f)?tmin:tmax;
|
||||
const float t = (tmin > 0.0f)?tmin:tmax;
|
||||
|
||||
return ( t < aRaySeg.m_Length );
|
||||
}
|
||||
|
||||
|
@ -288,14 +294,14 @@ bool CBBOX2D::Intersect( const RAY2D &aRay, float *aOutHitT0, float *aOutHitT1 )
|
|||
wxASSERT( aOutHitT0 );
|
||||
wxASSERT( aOutHitT1 );
|
||||
|
||||
float tx1 = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
float tx2 = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
const float tx1 = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
const float tx2 = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
float tmin = glm::min( tx1, tx2 );
|
||||
float tmax = glm::max( tx1, tx2 );
|
||||
|
||||
float ty1 = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
float ty2 = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
const float ty1 = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
const float ty2 = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
|
||||
tmin = glm::max( tmin, glm::min( ty1, ty2 ) );
|
||||
tmax = glm::min( tmax, glm::max( ty1, ty2 ) );
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@gmail.com>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -30,15 +30,14 @@
|
|||
#ifndef _CBBOX2D_H_
|
||||
#define _CBBOX2D_H_
|
||||
|
||||
#include "plugins/3dapi/xv3d_types.h"
|
||||
#include "3d_rendering/3d_render_raytracing/ray.h"
|
||||
#include "../ray.h"
|
||||
|
||||
|
||||
/**
|
||||
* Class CBBOX
|
||||
* manages a bounding box defined by two SFVEC2F min max points.
|
||||
*/
|
||||
GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) CBBOX2D
|
||||
struct CBBOX2D
|
||||
{
|
||||
|
||||
public:
|
||||
|
@ -54,7 +53,7 @@ public:
|
|||
* Initialize a bounding box with a given point
|
||||
* @param aPbInit a point for the bounding box initialization
|
||||
*/
|
||||
CBBOX2D( const SFVEC2F &aPbInit );
|
||||
explicit CBBOX2D( const SFVEC2F &aPbInit );
|
||||
|
||||
/**
|
||||
* Constructor CBBOX2D
|
||||
|
@ -209,8 +208,8 @@ public:
|
|||
bool Intersect( const RAYSEG2D &aRaySeg ) const;
|
||||
|
||||
private:
|
||||
SFVEC2F m_min; ///< point of the lower position of the bounding box
|
||||
SFVEC2F m_max; ///< point of the higher position of the bounding box
|
||||
SFVEC2F m_min; ///< point of the lower position of the bounding box
|
||||
SFVEC2F m_max; ///< point of the higher position of the bounding box
|
||||
};
|
||||
|
||||
#endif // CBBox2d_h
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* 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 cfilledcircle2d.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "cfilledcircle2d.h"
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
||||
CFILLEDCIRCLE2D::CFILLEDCIRCLE2D( const SFVEC2F &aCenter,
|
||||
float aRadius,
|
||||
const BOARD_ITEM &aBoardItem ) :
|
||||
COBJECT2D( OBJ2D_FILLED_CIRCLE, aBoardItem )
|
||||
{
|
||||
wxASSERT( aRadius > 0.0f ); // If that happens, it should be handled before create this circle
|
||||
|
||||
m_center = aCenter;
|
||||
m_radius = aRadius;
|
||||
m_radius_squared = aRadius * aRadius;
|
||||
|
||||
m_bbox.Reset();
|
||||
m_bbox.Set( m_center - SFVEC2F( aRadius, aRadius ),
|
||||
m_center + SFVEC2F( aRadius, aRadius ) );
|
||||
m_bbox.ScaleNextUp();
|
||||
m_centroid = m_bbox.GetCenter();
|
||||
|
||||
wxASSERT( m_bbox.IsInitialized() );
|
||||
}
|
||||
|
||||
|
||||
bool CFILLEDCIRCLE2D::Overlaps( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
// NOT IMPLEMENTED
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CFILLEDCIRCLE2D::Intersects( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
return aBBox.Intersects( m_center, m_radius_squared );
|
||||
}
|
||||
|
||||
|
||||
bool CFILLEDCIRCLE2D::Intersect( const RAYSEG2D &aSegRay,
|
||||
float *aOutT,
|
||||
SFVEC2F *aNormalOut ) const
|
||||
{
|
||||
wxASSERT( aOutT );
|
||||
wxASSERT( aNormalOut );
|
||||
|
||||
// This code used directly from Steve Marschner's CS667 framework
|
||||
// http://cs665pd.googlecode.com/svn/trunk/photon/sphere.cpp
|
||||
|
||||
// Compute some factors used in computation
|
||||
const float qx = aSegRay.m_Start.x - m_center.x;
|
||||
const float qy = aSegRay.m_Start.y - m_center.y;
|
||||
|
||||
const float qd = qx * aSegRay.m_Dir.x + qy * aSegRay.m_Dir.y;
|
||||
const float qq = qx * qx + qy * qy;
|
||||
|
||||
// solving the quadratic equation for t at the pts of intersection
|
||||
// dd*t^2 + (2*qd)*t + (qq-r^2) = 0
|
||||
const float discriminantsqr = (qd * qd - (qq - m_radius_squared));
|
||||
|
||||
// If the discriminant is less than zero, there is no intersection
|
||||
if( discriminantsqr < FLT_EPSILON )
|
||||
return false;
|
||||
|
||||
|
||||
// Otherwise check and make sure that the intersections occur on the ray (t
|
||||
// > 0) and return the closer one
|
||||
const float discriminant = sqrt(discriminantsqr);
|
||||
const float t1 = (-qd - discriminant);
|
||||
const float t2 = (-qd + discriminant);
|
||||
float t;
|
||||
|
||||
|
||||
if( (t1 > 0.0f) && (t1 < aSegRay.m_Length) )
|
||||
t = t1;
|
||||
else
|
||||
{
|
||||
if( (t2 > 0.0f) && (t2 < aSegRay.m_Length) )
|
||||
t = t2;
|
||||
else
|
||||
return false; // Neither intersection was in the ray's half line.
|
||||
}
|
||||
|
||||
wxASSERT( (t > 0.0f) && (t <= aSegRay.m_Length) );
|
||||
|
||||
// Convert the intersection to a normalized 0.0 .. 1.0
|
||||
*aOutT = t / aSegRay.m_Length;
|
||||
|
||||
const SFVEC2F hitPoint = aSegRay.at( t );
|
||||
|
||||
*aNormalOut = (hitPoint - m_center) / m_radius;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
INTERSECTION_RESULT CFILLEDCIRCLE2D::IsBBoxInside( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
if( !m_bbox.Intersects( aBBox ) )
|
||||
return INTR_MISSES;
|
||||
|
||||
SFVEC2F v[4];
|
||||
|
||||
v[0] = aBBox.Min() - m_center;
|
||||
v[1] = aBBox.Max() - m_center;
|
||||
v[2] = SFVEC2F( aBBox.Min().x, aBBox.Max().y ) - m_center;
|
||||
v[3] = SFVEC2F( aBBox.Max().x, aBBox.Min().y ) - m_center;
|
||||
|
||||
float s[4];
|
||||
|
||||
s[0] = v[0].x * v[0].x + v[0].y * v[0].y;
|
||||
s[1] = v[1].x * v[1].x + v[1].y * v[1].y;
|
||||
s[2] = v[2].x * v[2].x + v[2].y * v[2].y;
|
||||
s[3] = v[3].x * v[3].x + v[3].y * v[3].y;
|
||||
|
||||
bool isInside[4];
|
||||
|
||||
isInside[0] = s[0] <= m_radius_squared;
|
||||
isInside[1] = s[1] <= m_radius_squared;
|
||||
isInside[2] = s[2] <= m_radius_squared;
|
||||
isInside[3] = s[3] <= m_radius_squared;
|
||||
|
||||
// Check if all points are inside the circle
|
||||
if( isInside[0] &&
|
||||
isInside[1] &&
|
||||
isInside[2] &&
|
||||
isInside[3] )
|
||||
return INTR_FULL_INSIDE;
|
||||
|
||||
// Check if any point is inside the circle
|
||||
if( isInside[0] ||
|
||||
isInside[1] ||
|
||||
isInside[2] ||
|
||||
isInside[3] )
|
||||
return INTR_INTERSECTS;
|
||||
|
||||
return INTR_MISSES;
|
||||
}
|
||||
|
||||
|
||||
bool CFILLEDCIRCLE2D::IsPointInside( const SFVEC2F &aPoint ) const
|
||||
{
|
||||
const SFVEC2F v = m_center - aPoint;
|
||||
|
||||
if( (v.x * v.x + v.y * v.y) <= m_radius_squared )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -32,7 +32,7 @@
|
|||
|
||||
#include "cobject2d.h"
|
||||
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CFILLEDCIRCLE2D : public COBJECT2D
|
||||
class CFILLEDCIRCLE2D : public COBJECT2D
|
||||
{
|
||||
public:
|
||||
float GetRadius() const { return m_radius; }
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* 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 citemlayercsg2d.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "citemlayercsg2d.h"
|
||||
#include "3d_fastmath.h"
|
||||
#include <wx/debug.h>
|
||||
|
||||
CITEMLAYERCSG2D::CITEMLAYERCSG2D( const COBJECT2D *aObjectA,
|
||||
std::vector<const COBJECT2D *> *aObjectB,
|
||||
const COBJECT2D *aObjectC,
|
||||
const BOARD_ITEM &aBoardItem ):
|
||||
COBJECT2D( OBJ2D_CSG, aBoardItem ),
|
||||
m_objectA(aObjectA),
|
||||
m_objectB(aObjectB),
|
||||
m_objectC(aObjectC)
|
||||
{
|
||||
wxASSERT( aObjectA );
|
||||
|
||||
m_bbox.Reset();
|
||||
m_bbox.Set( aObjectA->GetBBox() );
|
||||
m_bbox.ScaleNextUp();
|
||||
m_centroid = m_bbox.GetCenter();
|
||||
|
||||
wxASSERT( m_bbox.IsInitialized() );
|
||||
}
|
||||
|
||||
|
||||
CITEMLAYERCSG2D::~CITEMLAYERCSG2D()
|
||||
{
|
||||
if( ((void*)m_objectB != CSGITEM_EMPTY) &&
|
||||
((void*)m_objectB != CSGITEM_FULL) )
|
||||
{
|
||||
delete m_objectB;
|
||||
m_objectB = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CITEMLAYERCSG2D::Intersects( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
return m_bbox.Intersects( aBBox );
|
||||
// !TODO: improove this implementation
|
||||
//return false;
|
||||
}
|
||||
|
||||
|
||||
bool CITEMLAYERCSG2D::Overlaps( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
// NOT IMPLEMENTED
|
||||
return false;
|
||||
}
|
||||
|
||||
// Based on ideas and implementation by Nick Chapman
|
||||
// http://homepages.paradise.net.nz/nickamy/raytracer/raytracer.htm
|
||||
bool CITEMLAYERCSG2D::Intersect( const RAYSEG2D &aSegRay,
|
||||
float *aOutT,
|
||||
SFVEC2F *aNormalOut ) const
|
||||
{
|
||||
wxASSERT( aOutT );
|
||||
wxASSERT( aNormalOut );
|
||||
|
||||
if( m_objectA->GetObjectType() == OBJ2D_DUMMYBLOCK )
|
||||
return false;
|
||||
|
||||
float currentRayDist;
|
||||
SFVEC2F currentRayPos;
|
||||
SFVEC2F currentNormal;
|
||||
|
||||
if( m_objectA->IsPointInside( aSegRay.m_Start ) )
|
||||
{
|
||||
// start ray point off where it is now (at the origin)
|
||||
currentRayDist = 0.0f;
|
||||
currentRayPos = aSegRay.m_Start;
|
||||
}
|
||||
else
|
||||
{
|
||||
//move ray point to start of main object
|
||||
if( !m_objectA->Intersect( aSegRay, ¤tRayDist, ¤tNormal ) )
|
||||
return false;
|
||||
|
||||
currentRayPos = aSegRay.atNormalized( NextFloatDown( currentRayDist ) );
|
||||
}
|
||||
|
||||
//wxASSERT( (currentRayDist >= 0.0f) && (currentRayDist <= 1.0f) );
|
||||
|
||||
|
||||
// move through the union of subtracted regions
|
||||
bool hitSubRegion = false;
|
||||
|
||||
if( m_objectB )
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
bool wasInsideSubVol = false;
|
||||
|
||||
//check against all subbed objects
|
||||
for( unsigned int i = 0; i < m_objectB->size(); ++i )
|
||||
{
|
||||
if( ((const COBJECT2D *)(*m_objectB)[i])->IsPointInside( currentRayPos ) )
|
||||
{
|
||||
hitSubRegion = true;
|
||||
|
||||
// ray point is inside a subtracted region, so move it to the end of the
|
||||
// subtracted region
|
||||
float hitDist;
|
||||
if( !((const COBJECT2D *)(*m_objectB)[i])->Intersect( aSegRay,
|
||||
&hitDist,
|
||||
¤tNormal ) )
|
||||
return false; // ray hit main object but did not leave subtracted volume
|
||||
|
||||
wxASSERT( hitDist <= 1.0f );
|
||||
|
||||
if( hitDist > currentRayDist )
|
||||
currentRayDist = hitDist;
|
||||
|
||||
currentRayDist += 0.0001f;
|
||||
|
||||
// ray has left this specific subtracted object volume
|
||||
currentRayPos = aSegRay.atNormalized( currentRayDist );
|
||||
|
||||
if( m_objectA->IsPointInside( currentRayPos ) )
|
||||
//if(1)
|
||||
{
|
||||
wasInsideSubVol = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !wasInsideSubVol )
|
||||
break; // ray has succesfully passed through all subtracted regions
|
||||
|
||||
if( currentRayDist >= 1.0f )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//ray is not inside any of the specific subtracted regions
|
||||
|
||||
if( hitSubRegion )
|
||||
{
|
||||
//if( !m_objectA->IsPointInside( currentRayPos ) )
|
||||
// return false; // ray got right through the hole in the object!
|
||||
|
||||
currentNormal *= -1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
//ray just hit the main object without hitting any holes
|
||||
}
|
||||
|
||||
*aNormalOut = currentNormal;
|
||||
*aOutT = currentRayDist;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
INTERSECTION_RESULT CITEMLAYERCSG2D::IsBBoxInside( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
|
||||
// !TODO:
|
||||
|
||||
return INTR_MISSES;
|
||||
}
|
||||
|
||||
|
||||
bool CITEMLAYERCSG2D::IsPointInside( const SFVEC2F &aPoint ) const
|
||||
{
|
||||
// Perform the operation (A - B) /\ C
|
||||
|
||||
if( m_objectA->IsPointInside( aPoint ) )
|
||||
{
|
||||
|
||||
if( m_objectB != CSGITEM_EMPTY)
|
||||
for( unsigned int i = 0; i< m_objectB->size(); i++ )
|
||||
{
|
||||
if( (*m_objectB)[i]->IsPointInside( aPoint ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
// !TODO: not yet implemented
|
||||
//if( m_objectC && m_objectC != CSGITEM_FULL )
|
||||
// return m_objectC->IsPointInside( aPoint );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* 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 citemlayercsg2d.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef _CITEMLAYERCSG2D_H_
|
||||
#define _CITEMLAYERCSG2D_H_
|
||||
|
||||
#include "cobject2d.h"
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* This class is used to make constructive solig geometry for items
|
||||
* objects on layers.
|
||||
* The operation is in the form (A - B) /\ C
|
||||
* For almost all of the layers it translate something like:
|
||||
* A (a via, a track, pad, polygon), B (a via hole, a THT hole, .. ),
|
||||
* C the board (epoxy)
|
||||
* For layers like Solder mask that are negative:
|
||||
* A ( epoxy ), B( pads, polygons, ..), C=1
|
||||
*
|
||||
* Some notes:
|
||||
* BODY = PCB_outlines - PCB_holes - (Modules_THT_holes + VIA_THT_holes)
|
||||
*
|
||||
* Plated_vias_and_holes = Tracks.Vias + Modules.PlatedHoles
|
||||
*
|
||||
* Layer.cu = ( Tracks.cu + Modules_Pads.cu + Modules_Graphics.cu +
|
||||
* Layer_zones.cu + PCB_drawings.cu - Layer_VIA_holes ) & BODY
|
||||
*
|
||||
* Layer.Mask = BODY -
|
||||
* (PCB_drawing.Mask + Modules_Graphics.Mask +
|
||||
* Modules_Pads.Mask + Layer_zones.Mask )
|
||||
* Layer.Paste = (PCB_drawing.Paste + Modules_Graphics.Paste +
|
||||
* Modules_Pads.Paste + Layer_zones.Paste) & BODY
|
||||
* Layer.Silk = (PCB_drawing.Silk + Modules_Graphics.Silk +
|
||||
* Modules_Pads.Silk + Layer_zones.Paste) & BODY
|
||||
*
|
||||
* BODY = A - B /\ 1
|
||||
* Layer.cu = A - B /\ C
|
||||
* Layer.mask = A - B /\ 1
|
||||
* Layers.Paste = A - 0 /\ C
|
||||
* Layers.Silk = A - 0 /\ C
|
||||
*
|
||||
* BODY = P - T /\ 1
|
||||
* Layer.cu = T - H /\ BODY
|
||||
* Layer.mask = BODY - M /\ 1
|
||||
* Layers.Paste = P - 0 /\ BODY
|
||||
* Layers.Silk = S - 0 /\ BODY
|
||||
*/
|
||||
|
||||
#define CSGITEM_EMPTY 0
|
||||
#define CSGITEM_FULL (COBJECT2D *)((size_t)(-1))
|
||||
|
||||
class CITEMLAYERCSG2D : public COBJECT2D
|
||||
{
|
||||
private:
|
||||
const COBJECT2D *m_objectA;
|
||||
std::vector<const COBJECT2D *> *m_objectB;
|
||||
const COBJECT2D *m_objectC;
|
||||
|
||||
public:
|
||||
CITEMLAYERCSG2D( const COBJECT2D *aObjectA,
|
||||
std::vector<const COBJECT2D *> *aObjectB,
|
||||
const COBJECT2D *aObjectC,
|
||||
const BOARD_ITEM &aBoardItem );
|
||||
|
||||
~CITEMLAYERCSG2D();
|
||||
|
||||
// Imported from COBJECT2D
|
||||
bool Overlaps( const CBBOX2D &aBBox ) const;
|
||||
bool Intersects( const CBBOX2D &aBBox ) const;
|
||||
bool Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const;
|
||||
INTERSECTION_RESULT IsBBoxInside( const CBBOX2D &aBBox ) const;
|
||||
bool IsPointInside( const SFVEC2F &aPoint ) const;
|
||||
};
|
||||
|
||||
|
||||
#endif // _CITEMLAYERCSG2D_H_
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -30,7 +30,6 @@
|
|||
#ifndef _COBJECT2D_H_
|
||||
#define _COBJECT2D_H_
|
||||
|
||||
#include "plugins/3dapi/xv3d_types.h"
|
||||
#include "cbbox2d.h"
|
||||
#include <string.h>
|
||||
|
||||
|
@ -60,7 +59,7 @@ enum OBJECT2D_TYPE
|
|||
};
|
||||
|
||||
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) COBJECT2D
|
||||
class COBJECT2D
|
||||
{
|
||||
protected:
|
||||
CBBOX2D m_bbox;
|
||||
|
@ -78,12 +77,13 @@ public:
|
|||
/** Function Overlaps
|
||||
* @brief Test if the box overlaps the object
|
||||
* Conformance
|
||||
* The function overlaps implements function Overlaps from the OGC Simple Feature Specification.
|
||||
* The function overlaps implements function Overlaps from the OGC
|
||||
* Simple Feature Specification.
|
||||
* http://www.opengeospatial.org/standards/sfa
|
||||
* a.Overlaps(b) ⇔ ( dim(I(a)) = dim(I(b)) = dim(I(a) ∩ I(b))) ∧ (a ∩ b ≠ a) ∧ (a ∩ b ≠ b)
|
||||
* It means that the result dimension of an overlap is the same dimentions of the bounding box
|
||||
* (so the overlap cannot be a point or a line) and one of the boxes cannot full contain the other
|
||||
* box.
|
||||
* It means that the result dimension of an overlap is the same dimentions
|
||||
* of the bounding box (so the overlap cannot be a point or a line) and one
|
||||
* of the boxes cannot full contain the other box.
|
||||
* @param aBBox - The bounding box to test
|
||||
* @return true if the BBox intersects the object or is inside it
|
||||
*/
|
||||
|
@ -100,11 +100,14 @@ public:
|
|||
/** Function Intersect
|
||||
* @brief Intersect
|
||||
* @param aSegRay
|
||||
* @param aOutT a value between 0.0 and 1.0 in relation to the time of the hit of the segment
|
||||
* @param aOutT a value between 0.0 and 1.0 in relation to the time of the
|
||||
* hit of the segment
|
||||
* @param aNormalOut
|
||||
* @return
|
||||
*/
|
||||
virtual bool Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const = 0;
|
||||
virtual bool Intersect( const RAYSEG2D &aSegRay,
|
||||
float *aOutT,
|
||||
SFVEC2F *aNormalOut ) const = 0;
|
||||
|
||||
/** Function IsBBoxInside
|
||||
* @brief Tests if the bouding is out, intersects or is complety inside
|
||||
|
@ -119,7 +122,7 @@ public:
|
|||
|
||||
const SFVEC2F &GetCentroid() const { return m_centroid; }
|
||||
|
||||
const OBJECT2D_TYPE GetObjectType() const { return m_obj_type; }
|
||||
OBJECT2D_TYPE GetObjectType() const { return m_obj_type; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -129,9 +132,12 @@ public:
|
|||
class COBJECT2D_STATS
|
||||
{
|
||||
public:
|
||||
void ResetStats() { memset( m_counter, 0, sizeof(unsigned int) * OBJ2D_MAX ); }
|
||||
void ResetStats() { memset( m_counter, 0, sizeof( unsigned int ) * OBJ2D_MAX ); }
|
||||
|
||||
unsigned int GetCountOf( OBJECT2D_TYPE aObjType ) const { return m_counter[aObjType]; }
|
||||
unsigned int GetCountOf( OBJECT2D_TYPE aObjType ) const
|
||||
{
|
||||
return m_counter[aObjType];
|
||||
}
|
||||
|
||||
void AddOne( OBJECT2D_TYPE aObjType ) { m_counter[aObjType]++; }
|
||||
|
||||
|
|
|
@ -0,0 +1,831 @@
|
|||
/*
|
||||
* 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 cpolygon2d.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "cpolygon2d.h"
|
||||
#include <wx/debug.h>
|
||||
#include <fctsys.h>
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
// CPOLYGONBLOCK2D
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool polygon_IsPointInside( const SEGMENTS &aSegments, const SFVEC2F &aPoint )
|
||||
{
|
||||
wxASSERT( aSegments.size() >= 3 );
|
||||
|
||||
unsigned int i;
|
||||
unsigned int j = aSegments.size() - 1;
|
||||
bool oddNodes = false;
|
||||
|
||||
for( i = 0; i < aSegments.size(); j = i++ )
|
||||
{
|
||||
const float polyJY = aSegments[j].m_Start.y;
|
||||
const float polyIY = aSegments[i].m_Start.y;
|
||||
|
||||
if( ((polyIY <= aPoint.y) && (polyJY >= aPoint.y)) ||
|
||||
((polyJY <= aPoint.y) && (polyIY >= aPoint.y))
|
||||
)
|
||||
{
|
||||
const float polyJX = aSegments[j].m_Start.x;
|
||||
const float polyIX = aSegments[i].m_Start.x;
|
||||
|
||||
if( (polyIX <= aPoint.x) || (polyJX <= aPoint.x) )
|
||||
oddNodes ^= ( ( polyIX +
|
||||
( ( aPoint.y - polyIY ) *
|
||||
aSegments[i].m_inv_JY_minus_IY ) *
|
||||
aSegments[i].m_JX_minus_IX ) < aPoint.x );
|
||||
}
|
||||
}
|
||||
|
||||
return oddNodes;
|
||||
}
|
||||
|
||||
|
||||
CPOLYGONBLOCK2D::CPOLYGONBLOCK2D( const SEGMENTS_WIDTH_NORMALS &aOpenSegmentList,
|
||||
const OUTERS_AND_HOLES &aOuter_and_holes,
|
||||
const BOARD_ITEM &aBoardItem ) :
|
||||
COBJECT2D( OBJ2D_POLYGON, aBoardItem )
|
||||
{
|
||||
m_open_segments.resize( aOpenSegmentList.size() );
|
||||
|
||||
// Copy vectors and structures
|
||||
for( unsigned int i = 0; i < aOpenSegmentList.size(); i++ )
|
||||
m_open_segments[i] = aOpenSegmentList[i];
|
||||
|
||||
m_outers_and_holes = aOuter_and_holes;
|
||||
|
||||
// Compute bounding box with the points of the polygon
|
||||
m_bbox.Reset();
|
||||
|
||||
for( unsigned int i = 0; i < m_outers_and_holes.m_Outers.size(); i++ )
|
||||
{
|
||||
for( unsigned int j = 0; j < m_outers_and_holes.m_Outers[i].size(); j++ )
|
||||
m_bbox.Union( ((SEGMENTS)m_outers_and_holes.m_Outers[i])[j].m_Start );
|
||||
}
|
||||
|
||||
m_bbox.ScaleNextUp();
|
||||
m_centroid = m_bbox.GetCenter();
|
||||
|
||||
// Some checks
|
||||
wxASSERT( m_open_segments.size() == aOpenSegmentList.size() );
|
||||
wxASSERT( m_open_segments.size() > 0 );
|
||||
|
||||
wxASSERT( m_outers_and_holes.m_Outers.size() > 0 );
|
||||
wxASSERT( m_outers_and_holes.m_Outers.size() == aOuter_and_holes.m_Outers.size() );
|
||||
wxASSERT( m_outers_and_holes.m_Holes.size() == aOuter_and_holes.m_Holes.size() );
|
||||
|
||||
wxASSERT( m_outers_and_holes.m_Outers[0].size() >= 3 );
|
||||
wxASSERT( m_outers_and_holes.m_Outers[0].size() ==
|
||||
aOuter_and_holes.m_Outers[0].size() );
|
||||
|
||||
wxASSERT( m_bbox.IsInitialized() );
|
||||
}
|
||||
|
||||
|
||||
bool CPOLYGONBLOCK2D::Intersects( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
return m_bbox.Intersects( aBBox );
|
||||
|
||||
// !TODO: this is a quick not perfect implementation
|
||||
// in order to make it perfect the box must be checked against all the
|
||||
// polygons in the outers and not inside the holes
|
||||
}
|
||||
|
||||
|
||||
bool CPOLYGONBLOCK2D::Overlaps( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
// NOT IMPLEMENTED
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CPOLYGONBLOCK2D::Intersect( const RAYSEG2D &aSegRay,
|
||||
float *aOutT,
|
||||
SFVEC2F *aNormalOut ) const
|
||||
{
|
||||
int hitIndex = -1;
|
||||
float hitU = 0.0f;
|
||||
float tMin = 0.0f;
|
||||
|
||||
for( unsigned int i = 0; i < m_open_segments.size(); i++ )
|
||||
{
|
||||
const SFVEC2F &s = m_open_segments[i].m_Precalc_slope;
|
||||
const SFVEC2F &q = m_open_segments[i].m_Start;
|
||||
|
||||
float rxs = aSegRay.m_End_minus_start.x * s.y -
|
||||
aSegRay.m_End_minus_start.y * s.x;
|
||||
|
||||
if( fabs(rxs) > FLT_EPSILON )
|
||||
{
|
||||
const float inv_rxs = 1.0f / rxs;
|
||||
|
||||
const SFVEC2F pq = q - aSegRay.m_Start;
|
||||
|
||||
const float t = (pq.x * s.y - pq.y * s.x) * inv_rxs;
|
||||
|
||||
if( (t < 0.0f) || (t > 1.0f) )
|
||||
continue;
|
||||
|
||||
const float u = ( pq.x * aSegRay.m_End_minus_start.y -
|
||||
pq.y * aSegRay.m_End_minus_start.x ) * inv_rxs;
|
||||
|
||||
if( (u < 0.0f) || (u > 1.0f) )
|
||||
continue;
|
||||
|
||||
if( ( hitIndex == -1 ) || ( t <= tMin ) )
|
||||
{
|
||||
tMin = t;
|
||||
hitIndex = i;
|
||||
hitU = u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( hitIndex >= 0 )
|
||||
{
|
||||
wxASSERT( (tMin >= 0.0f) && (tMin <= 1.0f) );
|
||||
|
||||
*aOutT = tMin;
|
||||
*aNormalOut = glm::normalize(
|
||||
m_open_segments[hitIndex].m_Normals.m_Start * hitU +
|
||||
m_open_segments[hitIndex].m_Normals.m_End *
|
||||
(1.0f - hitU) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
INTERSECTION_RESULT CPOLYGONBLOCK2D::IsBBoxInside( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
|
||||
return INTR_MISSES;
|
||||
}
|
||||
|
||||
|
||||
bool CPOLYGONBLOCK2D::IsPointInside( const SFVEC2F &aPoint ) const
|
||||
{
|
||||
// NOTE: we could add here a test for the bounding box, but because in the
|
||||
// 3d object it already checked for a 3d bbox.
|
||||
|
||||
// First test if point is inside a hole.
|
||||
// If true it can early exit
|
||||
for( unsigned int i = 0; i < m_outers_and_holes.m_Holes.size(); i++ )
|
||||
if( !m_outers_and_holes.m_Holes[i].empty() )
|
||||
if( polygon_IsPointInside( m_outers_and_holes.m_Holes[i], aPoint ) )
|
||||
return false;
|
||||
|
||||
// At this moment, the point is not inside a hole, so check if it is
|
||||
// inside the polygon
|
||||
for( unsigned int i = 0; i < m_outers_and_holes.m_Outers.size(); i++ )
|
||||
if( !m_outers_and_holes.m_Outers.empty() )
|
||||
if( polygon_IsPointInside( m_outers_and_holes.m_Outers[i], aPoint ) )
|
||||
return true;
|
||||
|
||||
// Miss the polygon
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// CDUMMYBLOCK2D
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CDUMMYBLOCK2D::CDUMMYBLOCK2D( const SFVEC2F &aPbMin, const SFVEC2F &aPbMax,
|
||||
const BOARD_ITEM &aBoardItem ) :
|
||||
COBJECT2D( OBJ2D_DUMMYBLOCK, aBoardItem )
|
||||
{
|
||||
m_bbox.Set( aPbMin, aPbMax );
|
||||
m_bbox.ScaleNextUp();
|
||||
m_centroid = m_bbox.GetCenter();
|
||||
}
|
||||
|
||||
|
||||
CDUMMYBLOCK2D::CDUMMYBLOCK2D( const CBBOX2D &aBBox,
|
||||
const BOARD_ITEM &aBoardItem ) :
|
||||
COBJECT2D( OBJ2D_DUMMYBLOCK, aBoardItem )
|
||||
{
|
||||
m_bbox.Set( aBBox );
|
||||
m_bbox.ScaleNextUp();
|
||||
m_centroid = m_bbox.GetCenter();
|
||||
}
|
||||
|
||||
|
||||
bool CDUMMYBLOCK2D::Intersects( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
return m_bbox.Intersects( aBBox );
|
||||
}
|
||||
|
||||
|
||||
bool CDUMMYBLOCK2D::Overlaps( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
// Not implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CDUMMYBLOCK2D::Intersect( const RAYSEG2D &aSegRay,
|
||||
float *aOutT,
|
||||
SFVEC2F *aNormalOut ) const
|
||||
{
|
||||
// The dummy block will be never intersected because it have no edges,
|
||||
// only it have a plan surface of the size of the bounding box
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
INTERSECTION_RESULT CDUMMYBLOCK2D::IsBBoxInside( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
//!TODO:
|
||||
return INTR_MISSES;
|
||||
}
|
||||
|
||||
|
||||
bool CDUMMYBLOCK2D::IsPointInside( const SFVEC2F &aPoint ) const
|
||||
{
|
||||
// The dummy is filled in all his bounding box, so if it hit the bbox
|
||||
// it will hit this dummy
|
||||
if( m_bbox.Inside( aPoint ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Polygon process and conversion
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef std::vector<SFVEC2F> KF_POINTS;
|
||||
|
||||
#define MAX_NR_DIVISIONS 96
|
||||
|
||||
|
||||
static bool intersect( const SEGMENT_WITH_NORMALS &aSeg,
|
||||
const SFVEC2F &aStart,
|
||||
const SFVEC2F &aEnd )
|
||||
{
|
||||
const SFVEC2F r = aEnd - aStart;
|
||||
const SFVEC2F s = aSeg.m_Precalc_slope;
|
||||
const SFVEC2F q = aSeg.m_Start;
|
||||
|
||||
const float rxs = r.x * s.y - r.y * s.x;
|
||||
|
||||
if( fabs(rxs) > glm::epsilon<float>() )
|
||||
{
|
||||
const float inv_rxs = 1.0f / rxs;
|
||||
|
||||
const SFVEC2F pq = q - aStart;
|
||||
|
||||
const float t = (pq.x * s.y - pq.y * s.x) * inv_rxs;
|
||||
|
||||
if( (t < 0.0f) || (t > 1.0f) )
|
||||
return false;
|
||||
|
||||
const float u = (pq.x * r.y - pq.y * r.x) * inv_rxs;
|
||||
|
||||
if( (u < 0.0f) || (u > 1.0f) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void extractPathsFrom( const SEGMENTS_WIDTH_NORMALS &aSegList,
|
||||
const CBBOX2D &aBBox,
|
||||
SEGMENTS_WIDTH_NORMALS &aOutSegThatIntersect )
|
||||
{
|
||||
wxASSERT( aSegList.size () >= 3 );
|
||||
|
||||
unsigned int i;
|
||||
unsigned int j = aSegList.size() - 1;
|
||||
|
||||
const SFVEC2F p1( aBBox.Min().x, aBBox.Min().y );
|
||||
const SFVEC2F p2( aBBox.Max().x, aBBox.Min().y );
|
||||
const SFVEC2F p3( aBBox.Max().x, aBBox.Max().y );
|
||||
const SFVEC2F p4( aBBox.Min().x, aBBox.Max().y );
|
||||
|
||||
aOutSegThatIntersect.clear();
|
||||
|
||||
for( i = 0; i < aSegList.size(); j = i++ )
|
||||
{
|
||||
if( aBBox.Inside( aSegList[i].m_Start ) ||
|
||||
aBBox.Inside( aSegList[j].m_Start ) )
|
||||
{
|
||||
// if the segment points are inside the bounding box then this
|
||||
// segment is touching the bbox.
|
||||
aOutSegThatIntersect.push_back( aSegList[i] );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if a segment intersects the bounding box
|
||||
|
||||
// Make a bounding box based on the segments start and end
|
||||
CBBOX2D segmentBBox( aSegList[i].m_Start,
|
||||
aSegList[j].m_Start );
|
||||
|
||||
if( aBBox.Intersects( segmentBBox ) )
|
||||
{
|
||||
|
||||
const SEGMENT_WITH_NORMALS &seg = aSegList[i];
|
||||
|
||||
if( intersect( seg, p1, p2 ) ||
|
||||
intersect( seg, p2, p3 ) ||
|
||||
intersect( seg, p3, p4 ) ||
|
||||
intersect( seg, p4, p1 ) )
|
||||
{
|
||||
aOutSegThatIntersect.push_back( seg );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void polygon_Convert( const SHAPE_LINE_CHAIN &aPath,
|
||||
SEGMENTS &aOutSegment,
|
||||
float aBiuTo3DunitsScale )
|
||||
{
|
||||
aOutSegment.resize( aPath.PointCount() );
|
||||
|
||||
for( int j = 0; j < aPath.PointCount(); j++ )
|
||||
{
|
||||
const VECTOR2I &a = aPath.CPoint( j );
|
||||
|
||||
aOutSegment[j].m_Start = SFVEC2F( (float) a.x * aBiuTo3DunitsScale,
|
||||
(float)-a.y * aBiuTo3DunitsScale );
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
unsigned int j = aOutSegment.size () - 1;
|
||||
|
||||
for( i = 0; i < aOutSegment.size (); j = i++ )
|
||||
{
|
||||
// Calculate constants for each segment
|
||||
aOutSegment[i].m_inv_JY_minus_IY = 1.0f / ( aOutSegment[j].m_Start.y -
|
||||
aOutSegment[i].m_Start.y );
|
||||
|
||||
aOutSegment[i].m_JX_minus_IX = (aOutSegment[j].m_Start.x -
|
||||
aOutSegment[i].m_Start.x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(
|
||||
const SHAPE_POLY_SET &aMainPath,
|
||||
CGENERICCONTAINER2D &aDstContainer,
|
||||
float aBiuTo3DunitsScale,
|
||||
float aDivFactor,
|
||||
const BOARD_ITEM &aBoardItem )
|
||||
{
|
||||
BOX2I pathBounds = aMainPath.BBox();
|
||||
|
||||
// Get the path
|
||||
|
||||
wxASSERT( aMainPath.OutlineCount() == 1 );
|
||||
const SHAPE_POLY_SET::POLYGON& curr_polywithholes = aMainPath.CPolygon( 0 );
|
||||
|
||||
wxASSERT( curr_polywithholes.size() == 1 );
|
||||
const SHAPE_LINE_CHAIN& path = curr_polywithholes[0]; // a simple polygon
|
||||
|
||||
// Convert the points to segments class
|
||||
CBBOX2D bbox;
|
||||
bbox.Reset();
|
||||
|
||||
// Contains the main list of segments and each segment normal interpolated
|
||||
SEGMENTS_WIDTH_NORMALS segments_and_normals;
|
||||
|
||||
// Contains a closed polygon used to calc if points are inside
|
||||
SEGMENTS segments;
|
||||
|
||||
segments_and_normals.resize( path.PointCount() );
|
||||
segments.resize( path.PointCount() );
|
||||
|
||||
for( int i = 0; i < path.PointCount(); i++ )
|
||||
{
|
||||
const VECTOR2I& a = path.CPoint( i );
|
||||
|
||||
const SFVEC2F point ( (float)( a.x) * aBiuTo3DunitsScale,
|
||||
(float)(-a.y) * aBiuTo3DunitsScale );
|
||||
|
||||
bbox.Union( point );
|
||||
segments_and_normals[i].m_Start = point;
|
||||
segments[i].m_Start = point;
|
||||
}
|
||||
|
||||
bbox.ScaleNextUp();
|
||||
|
||||
|
||||
// Calc the slopes, normals and some statistics about this polygon
|
||||
unsigned int i;
|
||||
unsigned int j = segments_and_normals.size() - 1;
|
||||
|
||||
// Temporary normal to the segment, it will later be used for interpolation
|
||||
std::vector< SFVEC2F > tmpSegmentNormals;
|
||||
tmpSegmentNormals.resize( segments_and_normals.size() );
|
||||
|
||||
float medOfTheSquaresSegmentLength = 0.0f;
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
float minLength = FLT_MAX;
|
||||
#endif
|
||||
|
||||
for( i = 0; i < segments_and_normals.size(); j = i++ )
|
||||
{
|
||||
const SFVEC2F slope = segments_and_normals[j].m_Start -
|
||||
segments_and_normals[i].m_Start;
|
||||
|
||||
segments_and_normals[i].m_Precalc_slope = slope;
|
||||
|
||||
// Calculate constants for each segment
|
||||
segments[i].m_inv_JY_minus_IY = 1.0f / ( segments_and_normals[j].m_Start.y -
|
||||
segments_and_normals[i].m_Start.y );
|
||||
|
||||
segments[i].m_JX_minus_IX = ( segments_and_normals[j].m_Start.x -
|
||||
segments_and_normals[i].m_Start.x );
|
||||
|
||||
// The normal orientation expect a fixed polygon orientation (!TODO: which one?)
|
||||
//tmpSegmentNormals[i] = glm::normalize( SFVEC2F( -slope.y, +slope.x ) );
|
||||
tmpSegmentNormals[i] = glm::normalize( SFVEC2F( slope.y, -slope.x ) );
|
||||
|
||||
const float length = slope.x * slope.x + slope.y * slope.y;
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
if( length < minLength )
|
||||
minLength = length;
|
||||
#endif
|
||||
|
||||
medOfTheSquaresSegmentLength += length;
|
||||
}
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
float minSegmentLength = sqrt( minLength );
|
||||
#endif
|
||||
|
||||
// This calc an approximation of medium lengths, that will be used to calc
|
||||
// the size of the division.
|
||||
medOfTheSquaresSegmentLength /= segments_and_normals.size();
|
||||
medOfTheSquaresSegmentLength = sqrt( medOfTheSquaresSegmentLength );
|
||||
|
||||
|
||||
// Compute the normal interpolation
|
||||
// If calculate the dot between the segments, if they are above/below some
|
||||
// threshould it will not interpolated it (ex: if you are in a edge corner
|
||||
// or in a smooth transaction)
|
||||
j = segments_and_normals.size() - 1;
|
||||
for( i = 0; i < segments_and_normals.size(); j = i++ )
|
||||
{
|
||||
const SFVEC2F normalBeforeSeg = tmpSegmentNormals[j];
|
||||
const SFVEC2F normalSeg = tmpSegmentNormals[i];
|
||||
const SFVEC2F normalAfterSeg = tmpSegmentNormals[ (i + 1) %
|
||||
segments_and_normals.size() ];
|
||||
|
||||
const float dotBefore = glm::dot( normalBeforeSeg, normalSeg );
|
||||
const float dotAfter = glm::dot( normalAfterSeg, normalSeg );
|
||||
|
||||
if( dotBefore < 0.7f )
|
||||
segments_and_normals[i].m_Normals.m_Start = normalSeg;
|
||||
else
|
||||
segments_and_normals[i].m_Normals.m_Start =
|
||||
glm::normalize( (((normalBeforeSeg * dotBefore ) + normalSeg) * 0.5f) );
|
||||
|
||||
if( dotAfter < 0.7f )
|
||||
segments_and_normals[i].m_Normals.m_End = normalSeg;
|
||||
else
|
||||
segments_and_normals[i].m_Normals.m_End =
|
||||
glm::normalize( (((normalAfterSeg * dotAfter ) + normalSeg) * 0.5f) );
|
||||
}
|
||||
|
||||
if( aDivFactor == 0.0f )
|
||||
aDivFactor = medOfTheSquaresSegmentLength;
|
||||
|
||||
SFVEC2UI grid_divisions;
|
||||
grid_divisions.x = (unsigned int)( (bbox.GetExtent().x / aDivFactor) );
|
||||
grid_divisions.y = (unsigned int)( (bbox.GetExtent().y / aDivFactor) );
|
||||
|
||||
grid_divisions = glm::clamp( grid_divisions ,
|
||||
SFVEC2UI( 1, 1 ),
|
||||
SFVEC2UI( MAX_NR_DIVISIONS, MAX_NR_DIVISIONS ) );
|
||||
|
||||
// Calculate the steps advance of the grid
|
||||
SFVEC2F blockAdvance;
|
||||
|
||||
blockAdvance.x = bbox.GetExtent().x / (float)grid_divisions.x;
|
||||
blockAdvance.y = bbox.GetExtent().y / (float)grid_divisions.y;
|
||||
|
||||
wxASSERT( blockAdvance.x > 0.0f );
|
||||
wxASSERT( blockAdvance.y > 0.0f );
|
||||
|
||||
const int leftToRight_inc = (pathBounds.GetRight() - pathBounds.GetLeft()) /
|
||||
grid_divisions.x;
|
||||
|
||||
const int topToBottom_inc = (pathBounds.GetBottom() - pathBounds.GetTop()) /
|
||||
grid_divisions.y;
|
||||
|
||||
// Statistics
|
||||
unsigned int stats_n_empty_blocks = 0;
|
||||
unsigned int stats_n_dummy_blocks = 0;
|
||||
unsigned int stats_n_poly_blocks = 0;
|
||||
unsigned int stats_sum_size_of_polygons = 0;
|
||||
|
||||
|
||||
// Step by each block of a grid trying to extract segments and create
|
||||
// polygon blocks
|
||||
|
||||
int topToBottom = pathBounds.GetTop();
|
||||
float blockY = bbox.Max().y;
|
||||
|
||||
for( unsigned int iy = 0; iy < grid_divisions.y; iy++ )
|
||||
{
|
||||
|
||||
int leftToRight = pathBounds.GetLeft();
|
||||
float blockX = bbox.Min().x;
|
||||
|
||||
for( unsigned int ix = 0; ix < grid_divisions.x; ix++ )
|
||||
{
|
||||
CBBOX2D blockBox( SFVEC2F( blockX,
|
||||
blockY - blockAdvance.y ),
|
||||
SFVEC2F( blockX + blockAdvance.x,
|
||||
blockY ) );
|
||||
|
||||
// Make the box large to it will catch (intersect) the edges
|
||||
blockBox.ScaleNextUp();
|
||||
blockBox.ScaleNextUp();
|
||||
blockBox.ScaleNextUp();
|
||||
|
||||
SEGMENTS_WIDTH_NORMALS extractedSegments;
|
||||
|
||||
extractPathsFrom( segments_and_normals, blockBox, extractedSegments );
|
||||
|
||||
|
||||
if( extractedSegments.empty() )
|
||||
{
|
||||
|
||||
SFVEC2F p1( blockBox.Min().x, blockBox.Min().y );
|
||||
SFVEC2F p2( blockBox.Max().x, blockBox.Min().y );
|
||||
SFVEC2F p3( blockBox.Max().x, blockBox.Max().y );
|
||||
SFVEC2F p4( blockBox.Min().x, blockBox.Max().y );
|
||||
|
||||
if( polygon_IsPointInside( segments, p1 ) ||
|
||||
polygon_IsPointInside( segments, p2 ) ||
|
||||
polygon_IsPointInside( segments, p3 ) ||
|
||||
polygon_IsPointInside( segments, p4 ) )
|
||||
{
|
||||
// In this case, the segments are not intersecting the
|
||||
// polygon, so it means that if any point is inside it,
|
||||
// then all other are inside the polygon.
|
||||
// This is a full bbox inside, so add a dummy box
|
||||
|
||||
aDstContainer.Add( new CDUMMYBLOCK2D( blockBox, aBoardItem ) );
|
||||
stats_n_dummy_blocks++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Points are outside, so this block complety missed the polygon
|
||||
// In this case, no objects need to be added
|
||||
stats_n_empty_blocks++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// At this point, the borders of polygon were intersected by the
|
||||
// bounding box, so we must calculate a new polygon that will
|
||||
// close that small block.
|
||||
// This block will be used to calculate if points are inside
|
||||
// the (sub block) polygon.
|
||||
|
||||
SHAPE_POLY_SET subBlockPoly;
|
||||
|
||||
SHAPE_LINE_CHAIN sb = SHAPE_LINE_CHAIN(
|
||||
VECTOR2I( leftToRight,
|
||||
topToBottom ),
|
||||
VECTOR2I( leftToRight + leftToRight_inc,
|
||||
topToBottom ),
|
||||
VECTOR2I( leftToRight + leftToRight_inc,
|
||||
topToBottom + topToBottom_inc ),
|
||||
VECTOR2I( leftToRight,
|
||||
topToBottom + topToBottom_inc ) );
|
||||
|
||||
//sb.Append( leftToRight, topToBottom );
|
||||
sb.SetClosed( true );
|
||||
|
||||
subBlockPoly.AddOutline( sb );
|
||||
|
||||
// We need here a strictly simple polygon with outlines and holes
|
||||
SHAPE_POLY_SET solution;
|
||||
solution.BooleanIntersection( aMainPath,
|
||||
subBlockPoly,
|
||||
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
OUTERS_AND_HOLES outersAndHoles;
|
||||
|
||||
outersAndHoles.m_Holes.clear();
|
||||
outersAndHoles.m_Outers.clear();
|
||||
|
||||
for( int idx = 0; idx < solution.OutlineCount(); idx++ )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN & outline = solution.Outline( idx );
|
||||
|
||||
SEGMENTS solutionSegment;
|
||||
|
||||
polygon_Convert( outline, solutionSegment, aBiuTo3DunitsScale );
|
||||
outersAndHoles.m_Outers.push_back( solutionSegment );
|
||||
|
||||
stats_sum_size_of_polygons += solutionSegment.size();
|
||||
|
||||
for( int holeIdx = 0;
|
||||
holeIdx < solution.HoleCount( idx );
|
||||
holeIdx++ )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN & hole = solution.Hole( idx, holeIdx );
|
||||
|
||||
polygon_Convert( hole, solutionSegment, aBiuTo3DunitsScale );
|
||||
outersAndHoles.m_Holes.push_back( solutionSegment );
|
||||
stats_sum_size_of_polygons += solutionSegment.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !outersAndHoles.m_Outers.empty() )
|
||||
{
|
||||
aDstContainer.Add( new CPOLYGONBLOCK2D( extractedSegments,
|
||||
outersAndHoles,
|
||||
aBoardItem ) );
|
||||
stats_n_poly_blocks++;
|
||||
}
|
||||
}
|
||||
|
||||
blockX += blockAdvance.x;
|
||||
leftToRight += leftToRight_inc;
|
||||
}
|
||||
|
||||
blockY -= blockAdvance.y;
|
||||
topToBottom += topToBottom_inc;
|
||||
}
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
printf( "////////////////////////////////////////////////////////////////////////////////\n" );
|
||||
printf( "Convert_path_polygon_to_polygon_blocks_and_dummy_blocks\n" );
|
||||
printf( " grid_divisions (%u, %u)\n", grid_divisions.x, grid_divisions.y );
|
||||
printf( " N Total Blocks %u\n", grid_divisions.x * grid_divisions.y );
|
||||
printf( " N Empty Blocks %u\n", stats_n_empty_blocks );
|
||||
printf( " N Dummy Blocks %u\n", stats_n_dummy_blocks );
|
||||
printf( " N Polyg Blocks %u\n", stats_n_poly_blocks );
|
||||
printf( " Med N Seg Poly %u\n", stats_sum_size_of_polygons / stats_n_poly_blocks );
|
||||
printf( " medOfTheSquaresSegmentLength %f\n", medOfTheSquaresSegmentLength );
|
||||
printf( " minSegmentLength %f\n", minSegmentLength );
|
||||
printf( " aDivFactor %f\n", aDivFactor );
|
||||
printf( "////////////////////////////////////////////////////////////////////////////////\n" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Polygon_Calc_BBox_3DU( const SHAPE_POLY_SET &aPolysList,
|
||||
CBBOX2D &aOutBBox ,
|
||||
float aBiuTo3DunitsScale )
|
||||
{
|
||||
aOutBBox.Reset();
|
||||
|
||||
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 );
|
||||
|
||||
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 );
|
||||
|
||||
aOutBBox.Union( SFVEC2F( (float) a.x * aBiuTo3DunitsScale,
|
||||
(float)-a.y * aBiuTo3DunitsScale ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aOutBBox.ScaleNextUp();
|
||||
}
|
||||
|
||||
|
||||
void Polygon_Convert( const KI_POLYGON &aPolygon,
|
||||
ClipperLib::Path &aOutPath,
|
||||
CBBOX2D &aOutBBox,
|
||||
float aBiuTo3DunitsScale )
|
||||
{
|
||||
aOutPath.resize( aPolygon.size() );
|
||||
aOutBBox.Reset();
|
||||
|
||||
for( unsigned i = 0; i < aPolygon.size(); i++ )
|
||||
{
|
||||
const KI_POLY_POINT point = *(aPolygon.begin() + i);
|
||||
|
||||
aOutPath[i] = ClipperLib::IntPoint( (ClipperLib::cInt)point.x(),
|
||||
(ClipperLib::cInt)point.y() );
|
||||
|
||||
aOutBBox.Union( SFVEC2F( (float) point.x() * aBiuTo3DunitsScale,
|
||||
(float)-point.y() * aBiuTo3DunitsScale ) );
|
||||
}
|
||||
|
||||
aOutBBox.ScaleNextUp();
|
||||
|
||||
ClipperLib::CleanPolygon( aOutPath );
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
static void polygon_Convert( const ClipperLib::Path &aPath,
|
||||
SEGMENTS &aOutSegment,
|
||||
float aBiuTo3DunitsScale )
|
||||
{
|
||||
aOutSegment.resize( aPath.size() );
|
||||
|
||||
for( unsigned i = 0; i < aPath.size(); i++ )
|
||||
{
|
||||
aOutSegment[i].m_Start = SFVEC2F( (float) aPath[i].X * aBiuTo3DunitsScale,
|
||||
(float)-aPath[i].Y * aBiuTo3DunitsScale );
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
unsigned int j = aOutSegment.size () - 1;
|
||||
|
||||
for( i = 0; i < aOutSegment.size (); j = i++ )
|
||||
{
|
||||
// Calculate constants for each segment
|
||||
aOutSegment[i].m_inv_JY_minus_IY = 1.0f / ( aOutSegment[j].m_Start.y -
|
||||
aOutSegment[i].m_Start.y );
|
||||
aOutSegment[i].m_JX_minus_IX = (aOutSegment[j].m_Start.x - aOutSegment[i].m_Start.x);
|
||||
}
|
||||
}
|
||||
|
||||
void Polygon2d_TestModule()
|
||||
{
|
||||
// "This structure contains a sequence of IntPoint vertices defining a
|
||||
// single contour"
|
||||
ClipperLib::Path aPath;
|
||||
|
||||
SEGMENTS aSegments;
|
||||
|
||||
aPath.resize( 4 );
|
||||
|
||||
aPath[0] = ClipperLib::IntPoint( -2, -2 );
|
||||
aPath[1] = ClipperLib::IntPoint( 2, -2 );
|
||||
aPath[2] = ClipperLib::IntPoint( 2, 2 );
|
||||
aPath[3] = ClipperLib::IntPoint( -2, 2 );
|
||||
|
||||
// It must be an outter polygon
|
||||
wxASSERT( ClipperLib::Orientation( aPath ) );
|
||||
|
||||
polygon_Convert( aPath, aSegments, 1.0f );
|
||||
|
||||
wxASSERT( aPath.size() == aSegments.size() );
|
||||
|
||||
wxASSERT( aSegments[0].m_Start == SFVEC2F( -2.0f, 2.0f ) );
|
||||
wxASSERT( aSegments[1].m_Start == SFVEC2F( 2.0f, 2.0f ) );
|
||||
wxASSERT( aSegments[2].m_Start == SFVEC2F( 2.0f, -2.0f ) );
|
||||
wxASSERT( aSegments[3].m_Start == SFVEC2F( -2.0f, -2.0f ) );
|
||||
|
||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 0.0f, 0.0f ) ) );
|
||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -1.9f, -1.9f ) ) );
|
||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -1.9f, 1.9f ) ) );
|
||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 1.9f, 1.9f ) ) );
|
||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 1.9f, -1.9f ) ) );
|
||||
|
||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -2.1f, -2.0f ) ) == false );
|
||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -2.1f, 2.0f ) ) == false );
|
||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 2.1f, 2.0f ) ) == false );
|
||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 2.1f, -2.0f ) ) == false );
|
||||
}
|
||||
#endif
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -84,7 +84,7 @@ typedef struct
|
|||
/// polygons. This polygon class represent a sub part of that main polygon.
|
||||
/// There is information for the contours (used to test the ray2d intersection)
|
||||
/// and a close definition of the block polygon to test if a point is inside.
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CPOLYGONBLOCK2D : public COBJECT2D
|
||||
class CPOLYGONBLOCK2D : public COBJECT2D
|
||||
{
|
||||
private:
|
||||
/// This is the outter part of the polygon. This list is used to test a ray
|
||||
|
@ -115,11 +115,14 @@ public:
|
|||
/// a ray will return allways false.
|
||||
/// This is used as a sub block extrated from polygon (pcb polygon areas) and
|
||||
/// represents an area that is full filled.
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CDUMMYBLOCK2D : public COBJECT2D
|
||||
class CDUMMYBLOCK2D : public COBJECT2D
|
||||
{
|
||||
|
||||
public:
|
||||
CDUMMYBLOCK2D(const SFVEC2F &aPbMin, const SFVEC2F &aPbMax , const BOARD_ITEM &aBoardItem );
|
||||
CDUMMYBLOCK2D( const SFVEC2F &aPbMin,
|
||||
const SFVEC2F &aPbMax,
|
||||
const BOARD_ITEM &aBoardItem );
|
||||
|
||||
CDUMMYBLOCK2D( const CBBOX2D &aBBox, const BOARD_ITEM &aBoardItem );
|
||||
|
||||
// Imported from COBJECT2D
|
||||
|
@ -138,16 +141,24 @@ public:
|
|||
* @param aMainPath - the polygon are that was converted from the pcb board
|
||||
* @param aDstContainer - the destination container to put the created sub blocks
|
||||
* @param aBiuTo3DunitsScale - the rendering target 3d scale
|
||||
* @param aDivFactor - a division factor (in 3Dunits) to divide the polygon plane, 0.0f will use the internal polygon segm statistics
|
||||
* @param aDivFactor - a division factor (in 3Dunits) to divide the polygon plane,
|
||||
* 0.0f will use the internal polygon segm statistics
|
||||
*/
|
||||
void Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(const SHAPE_POLY_SET &aMainPath,
|
||||
void Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(
|
||||
const SHAPE_POLY_SET &aMainPath,
|
||||
CGENERICCONTAINER2D &aDstContainer,
|
||||
float aBiuTo3DunitsScale,
|
||||
float aDivFactor,
|
||||
const BOARD_ITEM &aBoardItem );
|
||||
|
||||
void Polygon_Calc_BBox_3DU(const SHAPE_POLY_SET &aPolysList, CBBOX2D &aOutBBox , float aBiuTo3DunitsScale );
|
||||
void Polygon_Convert( const KI_POLYGON &aPolygon, ClipperLib::Path &aOutPath, CBBOX2D &aOutBBox, float aBiuTo3DunitsScale );
|
||||
void Polygon_Calc_BBox_3DU( const SHAPE_POLY_SET &aPolysList,
|
||||
CBBOX2D &aOutBBox,
|
||||
float aBiuTo3DunitsScale );
|
||||
|
||||
void Polygon_Convert( const KI_POLYGON &aPolygon,
|
||||
ClipperLib::Path &aOutPath,
|
||||
CBBOX2D &aOutBBox,
|
||||
float aBiuTo3DunitsScale );
|
||||
|
||||
void Polygon2d_TestModule();
|
||||
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* 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 cpolygon4pts2d.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "cpolygon4pts2d.h"
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
||||
CPOLYGON4PTS2D::CPOLYGON4PTS2D( const SFVEC2F &v1,
|
||||
const SFVEC2F &v2,
|
||||
const SFVEC2F &v3,
|
||||
const SFVEC2F &v4,
|
||||
const BOARD_ITEM &aBoardItem ) :
|
||||
COBJECT2D( OBJ2D_POLYGON4PT, aBoardItem )
|
||||
{/*
|
||||
if( (v1.x > v2.x) || (v1.y < v2.y) )
|
||||
{
|
||||
m_segments[0] = v4;
|
||||
m_segments[1] = v3;
|
||||
m_segments[2] = v2;
|
||||
m_segments[3] = v1;
|
||||
}
|
||||
else
|
||||
{*/
|
||||
m_segments[0] = v1;
|
||||
m_segments[1] = v4;
|
||||
m_segments[2] = v3;
|
||||
m_segments[3] = v2;
|
||||
// }
|
||||
|
||||
unsigned int i;
|
||||
unsigned int j = 4 - 1;
|
||||
|
||||
for( i = 0; i < 4; j = i++ )
|
||||
{
|
||||
SFVEC2F slope = m_segments[j] - m_segments[i];
|
||||
m_precalc_slope[i] = slope;
|
||||
m_seg_normal[i] = glm::normalize( SFVEC2F( -slope.y, +slope.x ) );
|
||||
}
|
||||
|
||||
m_bbox.Reset();
|
||||
m_bbox.Union( v1 );
|
||||
m_bbox.Union( v2 );
|
||||
m_bbox.Union( v3 );
|
||||
m_bbox.Union( v4 );
|
||||
m_bbox.ScaleNextUp();
|
||||
m_bbox.ScaleNextUp();
|
||||
m_bbox.ScaleNextUp();
|
||||
m_bbox.ScaleNextUp();
|
||||
m_bbox.ScaleNextUp();
|
||||
m_centroid = m_bbox.GetCenter();
|
||||
|
||||
wxASSERT( m_bbox.IsInitialized() );
|
||||
}
|
||||
|
||||
|
||||
bool CPOLYGON4PTS2D::Intersects( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
return m_bbox.Intersects( aBBox );
|
||||
|
||||
// This source code is not working OK.
|
||||
/*
|
||||
if( !m_bbox.Intersects( aBBox ) )
|
||||
return false;
|
||||
|
||||
// Check if the bouding box complety have inside the small bouding box
|
||||
if( (aBBox.Max().x > m_bbox.Max().x) &&
|
||||
(aBBox.Max().y > m_bbox.Max().x) &&
|
||||
(aBBox.Min().x < m_bbox.Min().x) &&
|
||||
(aBBox.Min().y < m_bbox.Min().y)
|
||||
)
|
||||
return true;
|
||||
|
||||
SFVEC2F v[4];
|
||||
|
||||
v[0] = aBBox.Min();
|
||||
v[1] = SFVEC2F( aBBox.Min().x, aBBox.Max().y );
|
||||
v[2] = aBBox.Max();
|
||||
v[3] = SFVEC2F( aBBox.Max().x, aBBox.Min().y );
|
||||
|
||||
for( unsigned int i = 0; i < 4; i++ )
|
||||
{
|
||||
if( IntersectSegment( m_segments[i], m_precalc_slope[i], v[0], v[1] - v[0] ) )
|
||||
return true;
|
||||
if( IntersectSegment( m_segments[i], m_precalc_slope[i], v[1], v[2] - v[1] ) )
|
||||
return true;
|
||||
if( IntersectSegment( m_segments[i], m_precalc_slope[i], v[2], v[3] - v[2] ) )
|
||||
return true;
|
||||
if( IntersectSegment( m_segments[i], m_precalc_slope[i], v[3], v[0] - v[3] ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
if( IsPointInside( v[0] ) )
|
||||
return true;
|
||||
if( IsPointInside( v[1] ) )
|
||||
return true;
|
||||
if( IsPointInside( v[2] ) )
|
||||
return true;
|
||||
if( IsPointInside( v[3] ) )
|
||||
return true;
|
||||
|
||||
return false;*/
|
||||
}
|
||||
|
||||
|
||||
bool CPOLYGON4PTS2D::Overlaps( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
// NOT IMPLEMENTED
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CPOLYGON4PTS2D::Intersect( const RAYSEG2D &aSegRay,
|
||||
float *aOutT,
|
||||
SFVEC2F *aNormalOut ) const
|
||||
{
|
||||
wxASSERT( aOutT );
|
||||
wxASSERT( aNormalOut );
|
||||
|
||||
bool hited = false;
|
||||
unsigned int hitIndex;
|
||||
float bestHitT;
|
||||
|
||||
for( unsigned int i = 0; i < 4; i++ )
|
||||
{
|
||||
float t;
|
||||
|
||||
if( aSegRay.IntersectSegment( m_segments[i], m_precalc_slope[i], &t ) )
|
||||
if( (hited == false) || ( t < bestHitT) )
|
||||
{
|
||||
hited = true;
|
||||
hitIndex = i;
|
||||
bestHitT = t;
|
||||
}
|
||||
}
|
||||
|
||||
if( hited )
|
||||
{
|
||||
wxASSERT( (bestHitT >= 0.0f) && (bestHitT <= 1.0f) );
|
||||
|
||||
*aOutT = bestHitT;
|
||||
*aNormalOut = m_seg_normal[hitIndex];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
INTERSECTION_RESULT CPOLYGON4PTS2D::IsBBoxInside( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
// !TODO:
|
||||
|
||||
return INTR_MISSES;
|
||||
}
|
||||
|
||||
|
||||
bool CPOLYGON4PTS2D::IsPointInside( const SFVEC2F &aPoint ) const
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int j = 4 - 1;
|
||||
bool oddNodes = false;
|
||||
|
||||
for( i = 0; i < 4; j = i++ )
|
||||
{
|
||||
const float polyJY = m_segments[j].y;
|
||||
const float polyIY = m_segments[i].y;
|
||||
|
||||
if( ((polyIY <= aPoint.y) && (polyJY >= aPoint.y)) ||
|
||||
((polyJY <= aPoint.y) && (polyIY >= aPoint.y))
|
||||
)
|
||||
{
|
||||
const float polyJX = m_segments[j].x;
|
||||
const float polyIX = m_segments[i].x;
|
||||
|
||||
if( (polyIX <= aPoint.x) || (polyJX <= aPoint.x) )
|
||||
{
|
||||
oddNodes ^= ( ( polyIX +
|
||||
( ( aPoint.y - polyIY ) / ( polyJY - polyIY ) ) *
|
||||
( polyJX - polyIX ) ) < aPoint.x );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return oddNodes;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -37,7 +37,7 @@
|
|||
* (rectangles, trapezoids, with rotation.etc)
|
||||
* This is a simplified version of the cpolygon2d class
|
||||
*/
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CPOLYGON4PTS2D : public COBJECT2D
|
||||
class CPOLYGON4PTS2D : public COBJECT2D
|
||||
{
|
||||
private:
|
||||
SFVEC2F m_segments[4];
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* 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 cring2d.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "cring2d.h"
|
||||
#include "../../../3d_fastmath.h"
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
||||
CRING2D::CRING2D( const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius,
|
||||
const BOARD_ITEM &aBoardItem ) : COBJECT2D( OBJ2D_RING, aBoardItem )
|
||||
{
|
||||
wxASSERT( aInnerRadius < aOuterRadius );
|
||||
|
||||
m_center = aCenter;
|
||||
m_inner_radius = aInnerRadius;
|
||||
m_outer_radius = aOuterRadius;
|
||||
|
||||
m_inner_radius_squared = aInnerRadius * aInnerRadius;
|
||||
m_outer_radius_squared = aOuterRadius * aOuterRadius;
|
||||
|
||||
m_bbox.Reset();
|
||||
m_bbox.Set( m_center - SFVEC2F( aOuterRadius, aOuterRadius ),
|
||||
m_center + SFVEC2F( aOuterRadius, aOuterRadius ) );
|
||||
m_bbox.ScaleNextUp();
|
||||
m_centroid = m_bbox.GetCenter();
|
||||
|
||||
|
||||
wxASSERT( m_bbox.IsInitialized() );
|
||||
}
|
||||
|
||||
|
||||
bool CRING2D::Overlaps( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
// NOT IMPLEMENTED
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CRING2D::Intersects( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
// !TODO: check the inside for a great improovment
|
||||
return aBBox.Intersects( m_center, m_outer_radius_squared );
|
||||
}
|
||||
|
||||
|
||||
bool CRING2D::Intersect( const RAYSEG2D &aSegRay,
|
||||
float *aOutT,
|
||||
SFVEC2F *aNormalOut ) const
|
||||
{
|
||||
// This code used directly from Steve Marschner's CS667 framework
|
||||
// http://cs665pd.googlecode.com/svn/trunk/photon/sphere.cpp
|
||||
|
||||
// Compute some factors used in computation
|
||||
const float qx = (aSegRay.m_Start.x - m_center.x);
|
||||
const float qy = (aSegRay.m_Start.y - m_center.y);
|
||||
|
||||
const float qd = qx * aSegRay.m_Dir.x + qy * aSegRay.m_Dir.y;
|
||||
const float qq = qx * qx + qy * qy;
|
||||
|
||||
// solving the quadratic equation for t at the pts of intersection
|
||||
// dd*t^2 + (2*qd)*t + (qq-r^2) = 0
|
||||
|
||||
const float discriminantsqr = qd * qd - qq;
|
||||
const float discriminantsqr_outter = discriminantsqr + m_outer_radius_squared;
|
||||
|
||||
// If the discriminant is less than zero, there is no intersection
|
||||
if( discriminantsqr_outter < FLT_EPSILON )
|
||||
return false;
|
||||
|
||||
// Otherwise check and make sure that the intersections occur on the ray (t
|
||||
// > 0) and return the closer one
|
||||
const float discriminant = sqrt( discriminantsqr_outter );
|
||||
float t = (-qd - discriminant);
|
||||
|
||||
if( (t > FLT_EPSILON) && (t < aSegRay.m_Length) )
|
||||
{
|
||||
SFVEC2F hitPoint = aSegRay.at( t );
|
||||
*aNormalOut = (hitPoint - m_center) / m_outer_radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float discriminantsqr_inter = discriminantsqr + m_inner_radius_squared;
|
||||
|
||||
if( discriminantsqr_inter > FLT_EPSILON )
|
||||
{
|
||||
const float discriminant_inner = sqrt( discriminantsqr_inter );
|
||||
|
||||
const float t2_inner = (-qd + discriminant_inner);
|
||||
|
||||
if( (t2_inner > FLT_EPSILON) && (t2_inner < aSegRay.m_Length) )
|
||||
{
|
||||
t = t2_inner;
|
||||
|
||||
const SFVEC2F hitPoint = aSegRay.at( t2_inner );
|
||||
|
||||
*aNormalOut = (m_center - hitPoint) / m_inner_radius;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
wxASSERT( (t > 0.0f) && (t <= aSegRay.m_Length) );
|
||||
|
||||
// Convert the intersection to a normalized 0.0 .. 1.0
|
||||
*aOutT = t / aSegRay.m_Length;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
INTERSECTION_RESULT CRING2D::IsBBoxInside( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
/*
|
||||
if( !m_bbox.Overlaps( aBBox ) )
|
||||
return INTR_MISSES;
|
||||
|
||||
SFVEC2F v[4];
|
||||
|
||||
v[0] = aBBox.Min() - m_center;
|
||||
v[1] = aBBox.Max() - m_center;
|
||||
v[2] = SFVEC2F( aBBox.Min().x, aBBox.Max().y ) - m_center;
|
||||
v[3] = SFVEC2F( aBBox.Max().x, aBBox.Min().y ) - m_center;
|
||||
|
||||
float s[4];
|
||||
|
||||
s[0] = v[0].x * v[0].x + v[0].y * v[0].y;
|
||||
s[1] = v[1].x * v[1].x + v[1].y * v[1].y;
|
||||
s[2] = v[2].x * v[2].x + v[2].y * v[2].y;
|
||||
s[3] = v[3].x * v[3].x + v[3].y * v[3].y;
|
||||
|
||||
bool isInside[4];
|
||||
|
||||
isInside[0] = s[0] <= m_radius_squared;
|
||||
isInside[1] = s[1] <= m_radius_squared;
|
||||
isInside[2] = s[2] <= m_radius_squared;
|
||||
isInside[3] = s[3] <= m_radius_squared;
|
||||
|
||||
// Check if all points are inside the circle
|
||||
if( isInside[0] &&
|
||||
isInside[1] &&
|
||||
isInside[2] &&
|
||||
isInside[3] )
|
||||
return INTR_FULL_INSIDE;
|
||||
|
||||
// Check if any point is inside the circle
|
||||
if( isInside[0] ||
|
||||
isInside[1] ||
|
||||
isInside[2] ||
|
||||
isInside[3] )
|
||||
return INTR_INTERSECTS;
|
||||
*/
|
||||
return INTR_MISSES;
|
||||
}
|
||||
|
||||
|
||||
bool CRING2D::IsPointInside( const SFVEC2F &aPoint ) const
|
||||
{
|
||||
const SFVEC2F v = m_center - aPoint;
|
||||
|
||||
const float dot = glm::dot( v, v );
|
||||
|
||||
if( (dot <= m_outer_radius_squared) &&
|
||||
(dot >= m_inner_radius_squared) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -32,7 +32,7 @@
|
|||
|
||||
#include "cobject2d.h"
|
||||
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CRING2D : public COBJECT2D
|
||||
class CRING2D : public COBJECT2D
|
||||
{
|
||||
public:
|
||||
const SFVEC2F &GetCenter() const { return m_center; }
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -31,30 +31,38 @@
|
|||
#include <wx/debug.h>
|
||||
|
||||
|
||||
CROUNDSEGMENT2D::CROUNDSEGMENT2D( const SFVEC2F &aStart, const SFVEC2F &aEnd, float aWidth,
|
||||
CROUNDSEGMENT2D::CROUNDSEGMENT2D( const SFVEC2F &aStart,
|
||||
const SFVEC2F &aEnd,
|
||||
float aWidth,
|
||||
const BOARD_ITEM &aBoardItem ) :
|
||||
COBJECT2D( OBJ2D_ROUNDSEG, aBoardItem ),
|
||||
m_segment( aStart, aEnd )
|
||||
{
|
||||
wxASSERT( aStart != aEnd );
|
||||
|
||||
m_radius = (aWidth / 2.0f);
|
||||
m_radius_squared = m_radius * m_radius;
|
||||
m_width = aWidth;
|
||||
|
||||
SFVEC2F leftRadiusOffset( -m_segment.m_Dir.y * m_radius, m_segment.m_Dir.x * m_radius);
|
||||
SFVEC2F leftRadiusOffset( -m_segment.m_Dir.y * m_radius,
|
||||
m_segment.m_Dir.x * m_radius );
|
||||
|
||||
m_leftStart = aStart + leftRadiusOffset;
|
||||
m_leftEnd = aEnd + leftRadiusOffset;
|
||||
m_leftEnd_minus_start = m_leftEnd - m_leftStart;
|
||||
m_leftDir = glm::normalize( m_leftEnd_minus_start );
|
||||
m_leftEndMinusStart = m_leftEnd - m_leftStart;
|
||||
m_leftDir = glm::normalize( m_leftEndMinusStart );
|
||||
|
||||
SFVEC2F rightRadiusOffset( -leftRadiusOffset.x, -leftRadiusOffset.y );
|
||||
SFVEC2F rightRadiusOffset( -leftRadiusOffset.x,
|
||||
-leftRadiusOffset.y );
|
||||
m_rightStart = aEnd + rightRadiusOffset;
|
||||
m_rightEnd = aStart + rightRadiusOffset;
|
||||
m_rightEnd_minus_start = m_rightEnd - m_rightStart;
|
||||
m_rightDir = glm::normalize( m_rightEnd_minus_start );
|
||||
m_rightEndMinusStart = m_rightEnd - m_rightStart;
|
||||
m_rightDir = glm::normalize( m_rightEndMinusStart );
|
||||
|
||||
m_bbox.Reset();
|
||||
m_bbox.Set( aStart, aEnd );
|
||||
m_bbox.Set( m_bbox.Min() - SFVEC2F( m_radius, m_radius ), m_bbox.Max() + SFVEC2F( m_radius, m_radius ) );
|
||||
m_bbox.Set( m_bbox.Min() - SFVEC2F( m_radius, m_radius ),
|
||||
m_bbox.Max() + SFVEC2F( m_radius, m_radius ) );
|
||||
m_bbox.ScaleNextUp();
|
||||
m_centroid = m_bbox.GetCenter();
|
||||
|
||||
|
@ -82,19 +90,37 @@ bool CROUNDSEGMENT2D::Intersects( const CBBOX2D &aBBox ) const
|
|||
v[3] = SFVEC2F( aBBox.Max().x, aBBox.Min().y );
|
||||
|
||||
// Test against the main rectangle segment
|
||||
if( IntersectSegment( m_leftStart, m_leftEnd_minus_start, v[0], v[1] - v[0] ) ) return true;
|
||||
if( IntersectSegment( m_leftStart, m_leftEnd_minus_start, v[1], v[2] - v[1] ) ) return true;
|
||||
if( IntersectSegment( m_leftStart, m_leftEnd_minus_start, v[2], v[3] - v[2] ) ) return true;
|
||||
if( IntersectSegment( m_leftStart, m_leftEnd_minus_start, v[3], v[0] - v[3] ) ) return true;
|
||||
if( IntersectSegment( m_leftStart, m_leftEndMinusStart, v[0], v[1] - v[0] ) )
|
||||
return true;
|
||||
|
||||
if( IntersectSegment( m_rightStart, m_rightEnd_minus_start, v[0], v[1] - v[0] ) ) return true;
|
||||
if( IntersectSegment( m_rightStart, m_rightEnd_minus_start, v[1], v[2] - v[1] ) ) return true;
|
||||
if( IntersectSegment( m_rightStart, m_rightEnd_minus_start, v[2], v[3] - v[2] ) ) return true;
|
||||
if( IntersectSegment( m_rightStart, m_rightEnd_minus_start, v[3], v[0] - v[3] ) ) return true;
|
||||
if( IntersectSegment( m_leftStart, m_leftEndMinusStart, v[1], v[2] - v[1] ) )
|
||||
return true;
|
||||
|
||||
if( IntersectSegment( m_leftStart, m_leftEndMinusStart, v[2], v[3] - v[2] ) )
|
||||
return true;
|
||||
|
||||
if( IntersectSegment( m_leftStart, m_leftEndMinusStart, v[3], v[0] - v[3] ) )
|
||||
return true;
|
||||
|
||||
|
||||
if( IntersectSegment( m_rightStart, m_rightEndMinusStart, v[0], v[1] - v[0] ) )
|
||||
return true;
|
||||
|
||||
if( IntersectSegment( m_rightStart, m_rightEndMinusStart, v[1], v[2] - v[1] ) )
|
||||
return true;
|
||||
|
||||
if( IntersectSegment( m_rightStart, m_rightEndMinusStart, v[2], v[3] - v[2] ) )
|
||||
return true;
|
||||
|
||||
if( IntersectSegment( m_rightStart, m_rightEndMinusStart, v[3], v[0] - v[3] ) )
|
||||
return true;
|
||||
|
||||
// Test the two circles
|
||||
if( aBBox.Intersects( m_segment.m_Start, m_radius_squared ) ) return true;
|
||||
if( aBBox.Intersects( m_segment.m_End, m_radius_squared ) ) return true;
|
||||
if( aBBox.Intersects( m_segment.m_Start, m_radius_squared ) )
|
||||
return true;
|
||||
|
||||
if( aBBox.Intersects( m_segment.m_End, m_radius_squared ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -107,13 +133,15 @@ bool CROUNDSEGMENT2D::Overlaps( const CBBOX2D &aBBox ) const
|
|||
}
|
||||
|
||||
|
||||
bool CROUNDSEGMENT2D::Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const
|
||||
bool CROUNDSEGMENT2D::Intersect( const RAYSEG2D &aSegRay,
|
||||
float *aOutT,
|
||||
SFVEC2F *aNormalOut ) const
|
||||
{
|
||||
wxASSERT( aOutT );
|
||||
wxASSERT( aNormalOut );
|
||||
|
||||
bool start_is_inside = IsPointInside( aSegRay.m_Start );
|
||||
bool end_is_inside = IsPointInside( aSegRay.m_End );
|
||||
const bool start_is_inside = IsPointInside( aSegRay.m_Start );
|
||||
const bool end_is_inside = IsPointInside( aSegRay.m_End );
|
||||
|
||||
// If segment if inside there are no hits
|
||||
if( start_is_inside && end_is_inside )
|
||||
|
@ -128,7 +156,9 @@ bool CROUNDSEGMENT2D::Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F
|
|||
SFVEC2F farHitNormal;
|
||||
|
||||
float leftSegT;
|
||||
bool leftSegmentHit = aSegRay.IntersectSegment( m_leftStart, m_leftEnd_minus_start, &leftSegT );
|
||||
const bool leftSegmentHit = aSegRay.IntersectSegment( m_leftStart,
|
||||
m_leftEndMinusStart,
|
||||
&leftSegT );
|
||||
|
||||
if( leftSegmentHit )
|
||||
{
|
||||
|
@ -141,7 +171,9 @@ bool CROUNDSEGMENT2D::Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F
|
|||
}
|
||||
|
||||
float rightSegT;
|
||||
bool rightSegmentHit = aSegRay.IntersectSegment( m_rightStart, m_rightEnd_minus_start, &rightSegT );
|
||||
const bool rightSegmentHit = aSegRay.IntersectSegment( m_rightStart,
|
||||
m_rightEndMinusStart,
|
||||
&rightSegT );
|
||||
|
||||
if( rightSegmentHit )
|
||||
{
|
||||
|
@ -167,9 +199,9 @@ bool CROUNDSEGMENT2D::Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F
|
|||
SFVEC2F circleStart_N0;
|
||||
SFVEC2F circleStart_N1;
|
||||
|
||||
bool startCircleHit = aSegRay.IntersectCircle( m_segment.m_Start, m_radius,
|
||||
&circleStart_T0, &circleStart_T1,
|
||||
&circleStart_N0, &circleStart_N1 );
|
||||
const bool startCircleHit = aSegRay.IntersectCircle( m_segment.m_Start, m_radius,
|
||||
&circleStart_T0, &circleStart_T1,
|
||||
&circleStart_N0, &circleStart_N1 );
|
||||
|
||||
if( startCircleHit )
|
||||
{
|
||||
|
@ -207,9 +239,9 @@ bool CROUNDSEGMENT2D::Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F
|
|||
SFVEC2F circleEnd_N0;
|
||||
SFVEC2F circleEnd_N1;
|
||||
|
||||
bool rightCircleHit = aSegRay.IntersectCircle( m_segment.m_End, m_radius,
|
||||
&circleEnd_T0, &circleEnd_T1,
|
||||
&circleEnd_N0, &circleEnd_N1 );
|
||||
const bool rightCircleHit = aSegRay.IntersectCircle( m_segment.m_End, m_radius,
|
||||
&circleEnd_T0, &circleEnd_T1,
|
||||
&circleEnd_N0, &circleEnd_N1 );
|
||||
if( rightCircleHit )
|
||||
{
|
||||
if( circleEnd_T0 > 0.0f )
|
||||
|
@ -251,9 +283,10 @@ bool CROUNDSEGMENT2D::Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F
|
|||
}
|
||||
else
|
||||
{
|
||||
wxASSERT( (farHitT > 0.0f) && (farHitT <= 1.0f) );
|
||||
wxASSERT( (farHitT >= 0.0f) && (farHitT <= 1.0f) );
|
||||
|
||||
*aOutT = farHitT;
|
||||
*aNormalOut = farHitNormal;
|
||||
*aNormalOut = -farHitNormal; // the normal started inside, so invert it
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -32,7 +32,7 @@
|
|||
|
||||
#include "cobject2d.h"
|
||||
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CROUNDSEGMENT2D : public COBJECT2D
|
||||
class CROUNDSEGMENT2D : public COBJECT2D
|
||||
{
|
||||
|
||||
friend class CROUNDSEG;
|
||||
|
@ -42,12 +42,12 @@ private:
|
|||
|
||||
SFVEC2F m_leftStart;
|
||||
SFVEC2F m_leftEnd;
|
||||
SFVEC2F m_leftEnd_minus_start;
|
||||
SFVEC2F m_leftEndMinusStart;
|
||||
SFVEC2F m_leftDir;
|
||||
|
||||
SFVEC2F m_rightStart;
|
||||
SFVEC2F m_rightEnd;
|
||||
SFVEC2F m_rightEnd_minus_start;
|
||||
SFVEC2F m_rightEndMinusStart;
|
||||
SFVEC2F m_rightDir;
|
||||
|
||||
float m_radius;
|
||||
|
@ -69,12 +69,12 @@ public:
|
|||
|
||||
const SFVEC2F &GetLeftStar() const { return m_leftStart; }
|
||||
const SFVEC2F &GetLeftEnd() const { return m_leftEnd; }
|
||||
const SFVEC2F &GetLeftEnd_minus_Start() const { return m_leftEnd_minus_start; }
|
||||
const SFVEC2F &GetLeftEnd_minus_Start() const { return m_leftEndMinusStart; }
|
||||
const SFVEC2F &GetLeftDir() const { return m_leftDir; }
|
||||
|
||||
const SFVEC2F &GetRightStar() const { return m_rightStart; }
|
||||
const SFVEC2F &GetRightEnd() const { return m_rightEnd; }
|
||||
const SFVEC2F &GetRightEnd_minus_Start() const { return m_rightEnd_minus_start; }
|
||||
const SFVEC2F &GetRightEnd_minus_Start() const { return m_rightEndMinusStart; }
|
||||
const SFVEC2F &GetRightDir() const { return m_rightDir; }
|
||||
|
||||
// Imported from COBJECT2D
|
||||
|
@ -85,5 +85,23 @@ public:
|
|||
bool IsPointInside( const SFVEC2F &aPoint ) const;
|
||||
};
|
||||
|
||||
static const float s_min_dot = (FLT_EPSILON * 4.0f) ;
|
||||
|
||||
/**
|
||||
* @brief Segment_is_a_circle - check if segment start and end is very close to each other
|
||||
* should used to check if the segment should be converted to a circle instead
|
||||
* @param aStart
|
||||
* @param aEnd
|
||||
* @return true is it is better to convert the segment to circle
|
||||
*/
|
||||
inline bool Is_segment_a_circle( const SFVEC2F &aStart, const SFVEC2F &aEnd )
|
||||
{
|
||||
const SFVEC2F vec = aEnd - aStart;
|
||||
|
||||
return (aStart == aEnd) ||
|
||||
// This is the same as calc the lenght squared (without the sqrt)
|
||||
// and compare with a small value
|
||||
( glm::dot( vec, vec ) <= s_min_dot );
|
||||
}
|
||||
|
||||
#endif // _CROUNDSEGMENT2D_H_
|
||||
|
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
* 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 ctriangle2d.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "ctriangle2d.h"
|
||||
#include <map>
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/smart_ptr/shared_array.hpp>
|
||||
#include <wx/debug.h>
|
||||
|
||||
#include <wx/glcanvas.h> // CALLBACK definition, needed on Windows
|
||||
// alse needed on OSX to define __DARWIN__
|
||||
|
||||
#include "../../../3d_fastmath.h"
|
||||
#include <poly2tri/poly2tri.h>
|
||||
|
||||
|
||||
CTRIANGLE2D::CTRIANGLE2D ( const SFVEC2F &aV1,
|
||||
const SFVEC2F &aV2,
|
||||
const SFVEC2F &aV3,
|
||||
const BOARD_ITEM &aBoardItem ) : COBJECT2D( OBJ2D_TRIANGLE,
|
||||
aBoardItem )
|
||||
{
|
||||
p1 = aV1;
|
||||
p2 = aV2;
|
||||
p3 = aV3;
|
||||
|
||||
// Pre-Calc values
|
||||
m_inv_denominator = 1.0f / ( (p2.y - p3.y) * (p1.x - p3.x) +
|
||||
(p3.x - p2.x) * (p1.y - p3.y));
|
||||
m_p2y_minus_p3y = (p2.y - p3.y);
|
||||
m_p3x_minus_p2x = (p3.x - p2.x);
|
||||
m_p3y_minus_p1y = (p3.y - p1.y);
|
||||
m_p1x_minus_p3x = (p1.x - p3.x);
|
||||
|
||||
m_bbox.Reset();
|
||||
m_bbox.Union( aV1 );
|
||||
m_bbox.Union( aV2 );
|
||||
m_bbox.Union( aV3 );
|
||||
m_bbox.ScaleNextUp();
|
||||
m_centroid = m_bbox.GetCenter();
|
||||
|
||||
wxASSERT( m_bbox.IsInitialized() );
|
||||
}
|
||||
|
||||
|
||||
bool CTRIANGLE2D::Intersects( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
if( !m_bbox.Intersects( aBBox ) )
|
||||
return false;
|
||||
//!TODO: Optimize
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CTRIANGLE2D::Overlaps( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
// NOT IMPLEMENTED
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CTRIANGLE2D::Intersect( const RAYSEG2D &aSegRay,
|
||||
float *aOutT,
|
||||
SFVEC2F *aNormalOut ) const
|
||||
{
|
||||
wxASSERT( aOutT );
|
||||
wxASSERT( aNormalOut );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
INTERSECTION_RESULT CTRIANGLE2D::IsBBoxInside( const CBBOX2D &aBBox ) const
|
||||
{
|
||||
if( !m_bbox.Intersects( aBBox ) )
|
||||
return INTR_MISSES;
|
||||
// !TODO:
|
||||
return INTR_MISSES;
|
||||
}
|
||||
|
||||
|
||||
bool CTRIANGLE2D::IsPointInside( const SFVEC2F &aPoint ) const
|
||||
{
|
||||
// http://totologic.blogspot.co.uk/2014/01/accurate-point-in-triangle-test.html
|
||||
|
||||
SFVEC2F point_minus_p3 = aPoint - p3;
|
||||
|
||||
// barycentric coordinate system
|
||||
const float a = ( m_p2y_minus_p3y * point_minus_p3.x +
|
||||
m_p3x_minus_p2x * point_minus_p3.y ) * m_inv_denominator;
|
||||
|
||||
if( 0.0f > a || a > 1.0f )
|
||||
return false;
|
||||
|
||||
const float b = ( m_p3y_minus_p1y * point_minus_p3.x +
|
||||
m_p1x_minus_p3x * point_minus_p3.y ) * m_inv_denominator;
|
||||
|
||||
if( 0.0f > b || b > 1.0f )
|
||||
return false;
|
||||
|
||||
const float c = 1.0f - a - b;
|
||||
|
||||
return 0.0f <= c && c <= 1.0f;
|
||||
/*
|
||||
return 0.0f <= a && a <= 1.0f &&
|
||||
0.0f <= b && b <= 1.0f &&
|
||||
0.0f <= c && c <= 1.0f;*/
|
||||
}
|
||||
|
||||
|
||||
template <class C> void FreeClear( C & cntr )
|
||||
{
|
||||
for( typename C::iterator it = cntr.begin();
|
||||
it != cntr.end();
|
||||
++it )
|
||||
{
|
||||
delete * it;
|
||||
}
|
||||
|
||||
cntr.clear();
|
||||
}
|
||||
|
||||
// Note: Please check edgeshrink.cpp in order to learn the EdgeShrink propose
|
||||
|
||||
#define APPLY_EDGE_SHRINK
|
||||
|
||||
#ifdef APPLY_EDGE_SHRINK
|
||||
extern void EdgeShrink( std::vector<SFVEC2I64> &aPath );
|
||||
|
||||
#define POLY_SCALE_FACT 256
|
||||
#define POLY_SCALE_FACT_INVERSE (1.0 / (double)(POLY_SCALE_FACT))
|
||||
#endif
|
||||
|
||||
void Convert_shape_line_polygon_to_triangles( const SHAPE_POLY_SET &aPolyList,
|
||||
CGENERICCONTAINER2D &aDstContainer,
|
||||
float aBiuTo3DunitsScale ,
|
||||
const BOARD_ITEM &aBoardItem )
|
||||
{
|
||||
unsigned int nOutlines = aPolyList.OutlineCount();
|
||||
|
||||
|
||||
for( unsigned int idx = 0; idx < nOutlines; ++idx )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN &outlinePath = aPolyList.COutline( idx );
|
||||
|
||||
wxASSERT( outlinePath.PointCount() >= 3 );
|
||||
|
||||
std::vector<SFVEC2I64> scaledOutline;
|
||||
scaledOutline.resize( outlinePath.PointCount() );
|
||||
|
||||
// printf("\nidx: %u\n", idx);
|
||||
|
||||
// Apply a scale to the points
|
||||
for( unsigned int i = 0;
|
||||
i < (unsigned int)outlinePath.PointCount();
|
||||
++i )
|
||||
{
|
||||
const VECTOR2I& a = outlinePath.CPoint( i );
|
||||
|
||||
#ifdef APPLY_EDGE_SHRINK
|
||||
scaledOutline[i] = SFVEC2I64( (glm::int64)a.x * POLY_SCALE_FACT,
|
||||
(glm::int64)a.y * POLY_SCALE_FACT );
|
||||
#else
|
||||
scaledOutline[i] = SFVEC2I64( (glm::int64)a.x,
|
||||
(glm::int64)a.y );
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef APPLY_EDGE_SHRINK
|
||||
// Apply a modification to the points
|
||||
EdgeShrink( scaledOutline );
|
||||
#endif
|
||||
// Copy to a array of pointers
|
||||
std::vector<p2t::Point*> polyline;
|
||||
polyline.resize( outlinePath.PointCount() );
|
||||
|
||||
for( unsigned int i = 0;
|
||||
i < (unsigned int)scaledOutline.size();
|
||||
++i )
|
||||
{
|
||||
const SFVEC2I64 &a = scaledOutline[i];
|
||||
|
||||
//printf("%lu %lu\n", a.x, a.y);
|
||||
|
||||
polyline[i] = new p2t::Point( (double)a.x,
|
||||
(double)a.y );
|
||||
}
|
||||
|
||||
// Start creating the structured to be triangulated
|
||||
p2t::CDT* cdt = new p2t::CDT( polyline );
|
||||
|
||||
// Add holes for this outline
|
||||
unsigned int nHoles = aPolyList.HoleCount( idx );
|
||||
|
||||
std::vector< std::vector<p2t::Point*> > polylineHoles;
|
||||
|
||||
polylineHoles.resize( nHoles );
|
||||
|
||||
for( unsigned int idxHole = 0; idxHole < nHoles; ++idxHole )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN &outlineHoles = aPolyList.CHole( idx,
|
||||
idxHole );
|
||||
|
||||
wxASSERT( outlineHoles.PointCount() >= 3 );
|
||||
|
||||
std::vector<SFVEC2I64> scaledHole;
|
||||
scaledHole.resize( outlineHoles.PointCount() );
|
||||
|
||||
// Apply a scale to the points
|
||||
for( unsigned int i = 0;
|
||||
i < (unsigned int)outlineHoles.PointCount();
|
||||
++i )
|
||||
{
|
||||
const VECTOR2I &h = outlineHoles.CPoint( i );
|
||||
#ifdef APPLY_EDGE_SHRINK
|
||||
scaledHole[i] = SFVEC2I64( (glm::int64)h.x * POLY_SCALE_FACT,
|
||||
(glm::int64)h.y * POLY_SCALE_FACT );
|
||||
#else
|
||||
scaledHole[i] = SFVEC2I64( (glm::int64)h.x,
|
||||
(glm::int64)h.y );
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef APPLY_EDGE_SHRINK
|
||||
// Apply a modification to the points
|
||||
EdgeShrink( scaledHole );
|
||||
#endif
|
||||
|
||||
// Resize and reserve space
|
||||
polylineHoles[idxHole].resize( outlineHoles.PointCount() );
|
||||
|
||||
for( unsigned int i = 0;
|
||||
i < (unsigned int)outlineHoles.PointCount();
|
||||
++i )
|
||||
{
|
||||
const SFVEC2I64 &h = scaledHole[i];
|
||||
|
||||
polylineHoles[idxHole][i] = new p2t::Point( h.x, h.y );
|
||||
}
|
||||
|
||||
cdt->AddHole( polylineHoles[idxHole] );
|
||||
}
|
||||
|
||||
// Triangulate
|
||||
cdt->Triangulate();
|
||||
|
||||
// Hint: if you find any crashes on the triangulation poly2tri library,
|
||||
// you can use the following site to debug the points and it will mark
|
||||
// the errors in the polygon:
|
||||
// http://r3mi.github.io/poly2tri.js/
|
||||
|
||||
|
||||
// Get and add triangles
|
||||
std::vector<p2t::Triangle*> triangles;
|
||||
triangles = cdt->GetTriangles();
|
||||
|
||||
#ifdef APPLY_EDGE_SHRINK
|
||||
const double conver_d = (double)aBiuTo3DunitsScale *
|
||||
POLY_SCALE_FACT_INVERSE;
|
||||
#else
|
||||
const double conver_d = (double)aBiuTo3DunitsScale;
|
||||
#endif
|
||||
for( unsigned int i = 0; i < triangles.size(); ++i )
|
||||
{
|
||||
p2t::Triangle& t = *triangles[i];
|
||||
|
||||
p2t::Point& a = *t.GetPoint( 0 );
|
||||
p2t::Point& b = *t.GetPoint( 1 );
|
||||
p2t::Point& c = *t.GetPoint( 2 );
|
||||
|
||||
aDstContainer.Add( new CTRIANGLE2D( SFVEC2F( a.x * conver_d,
|
||||
-a.y * conver_d ),
|
||||
SFVEC2F( b.x * conver_d,
|
||||
-b.y * conver_d ),
|
||||
SFVEC2F( c.x * conver_d,
|
||||
-c.y * conver_d ),
|
||||
aBoardItem ) );
|
||||
}
|
||||
|
||||
// Delete created data
|
||||
delete cdt;
|
||||
|
||||
// Free points
|
||||
FreeClear(polyline);
|
||||
|
||||
for( unsigned int idxHole = 0; idxHole < nHoles; ++idxHole )
|
||||
{
|
||||
FreeClear( polylineHoles[idxHole] );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -36,7 +36,7 @@
|
|||
#include <geometry/shape_poly_set.h>
|
||||
#include <clipper.hpp>
|
||||
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) CTRIANGLE2D : public COBJECT2D
|
||||
class CTRIANGLE2D : public COBJECT2D
|
||||
{
|
||||
private:
|
||||
SFVEC2F p1;
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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 edgeshrink.cpp
|
||||
* @brief The edgeShrink function was found in the project clip2tri by the:
|
||||
* Bitfighter project (http://bitfighter.org)
|
||||
* https://github.com/raptor/clip2tri
|
||||
* https://github.com/raptor/clip2tri/blob/f62a734d22733814b8a970ed8a68a4d94c24fa5f/clip2tri/clip2tri.cpp#L150
|
||||
*/
|
||||
|
||||
#include <plugins/3dapi/xv3d_types.h>
|
||||
#include <vector>
|
||||
|
||||
// clip2tri is Licenced under:
|
||||
|
||||
// The MIT License (MIT)
|
||||
|
||||
// Copyright (c) 2014 Bitfighter developers
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
|
||||
// Shrink large polygons by reducing each coordinate by 1 in the
|
||||
// general direction of the last point as we wind around
|
||||
//
|
||||
// This normally wouldn't work in every case, but our upscaled-by-1000 polygons
|
||||
// have little chance to create new duplicate points with this method.
|
||||
//
|
||||
// For information on why this was needed, see:
|
||||
//
|
||||
// https://github.com/greenm01/poly2tri/issues/90
|
||||
//
|
||||
|
||||
#define S_INC 1
|
||||
|
||||
void EdgeShrink( std::vector<SFVEC2I64> &aPath )
|
||||
{
|
||||
unsigned int prev = aPath.size() - 1;
|
||||
|
||||
for( unsigned int i = 0; i < aPath.size(); i++ )
|
||||
{
|
||||
// Adjust coordinate by 1 depending on the direction
|
||||
(aPath[i].x - aPath[prev].x) > 0 ? aPath[i].x -= S_INC :
|
||||
aPath[i].x += S_INC;
|
||||
|
||||
(aPath[i].y - aPath[prev].y) > 0 ? aPath[i].y -= S_INC :
|
||||
aPath[i].y += S_INC;
|
||||
|
||||
prev = i;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@gmail.com>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -26,11 +26,11 @@
|
|||
* @file cbbox.cpp
|
||||
* @brief Bounding Box class implementation
|
||||
*/
|
||||
#include "3d_math/3d_fastmath.h"
|
||||
#include "3d_fastmath.h"
|
||||
|
||||
#include "cbbox.h"
|
||||
#include <stdio.h>
|
||||
#include <wx/debug.h> // For the wxASSERT
|
||||
#include <wx/debug.h> // For the wxASSERT
|
||||
|
||||
|
||||
CBBOX::CBBOX()
|
||||
|
@ -57,6 +57,13 @@ CBBOX::~CBBOX()
|
|||
}
|
||||
|
||||
|
||||
void CBBOX::Set( const SFVEC3F &aPoint )
|
||||
{
|
||||
m_min = aPoint;
|
||||
m_max = aPoint;
|
||||
}
|
||||
|
||||
|
||||
void CBBOX::Set( const SFVEC3F &aPbMin, const SFVEC3F &aPbMax )
|
||||
{
|
||||
m_min.x = fminf( aPbMin.x, aPbMax.x );
|
||||
|
@ -111,8 +118,7 @@ void CBBOX::Union( const SFVEC3F &aPoint )
|
|||
|
||||
void CBBOX::Union( const CBBOX &aBBox )
|
||||
{
|
||||
if( !aBBox.IsInitialized() )
|
||||
return;
|
||||
wxASSERT( aBBox.IsInitialized() );
|
||||
|
||||
// get the minimun value between the added bounding box and the existent bounding box
|
||||
m_min.x = fmin( m_min.x, aBBox.m_min.x );
|
||||
|
@ -151,8 +157,10 @@ unsigned int CBBOX::MaxDimension() const
|
|||
|
||||
SFVEC3F extent = GetExtent();
|
||||
|
||||
if( extent.y > extent.x ) result = 1;
|
||||
if( extent.z > extent.y ) result = 2;
|
||||
if( extent.y > extent.x )
|
||||
result = 1;
|
||||
if( extent.z > extent.y )
|
||||
result = 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -164,8 +172,10 @@ float CBBOX::GetMaxDimension() const
|
|||
|
||||
SFVEC3F extent = GetExtent();
|
||||
|
||||
if( extent.y > extent.x ) max_dimensions_idx = 1;
|
||||
if( extent.z > extent.y ) max_dimensions_idx = 2;
|
||||
if( extent.y > extent.x )
|
||||
max_dimensions_idx = 1;
|
||||
if( extent.z > extent.y )
|
||||
max_dimensions_idx = 2;
|
||||
|
||||
return extent[max_dimensions_idx];
|
||||
}
|
||||
|
@ -288,14 +298,18 @@ bool CBBOX::Intersect( const RAY &aRay, float *aOutHitt0, float *aOutHitt1 )
|
|||
return false;
|
||||
}
|
||||
|
||||
if( aOutHitt0 ) *aOutHitt0 = t0;
|
||||
if( aOutHitt1 ) *aOutHitt1 = t1;
|
||||
if( aOutHitt0 )
|
||||
*aOutHitt0 = t0;
|
||||
if( aOutHitt1 )
|
||||
*aOutHitt1 = t1;
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
// https://github.com/mmp/pbrt-v2/blob/master/src/accelerators/bvh.cpp#L126
|
||||
bool CBBOX::Intersect( const RAY &aRay, float *aOutHitt0, float *aOutHitt1 ) const
|
||||
bool CBBOX::Intersect( const RAY &aRay,
|
||||
float *aOutHitt0,
|
||||
float *aOutHitt1 ) const
|
||||
{
|
||||
wxASSERT( aOutHitt0 );
|
||||
wxASSERT( aOutHitt1 );
|
||||
|
@ -303,8 +317,8 @@ bool CBBOX::Intersect( const RAY &aRay, float *aOutHitt0, float *aOutHitt1 ) con
|
|||
const SFVEC3F bounds[2] = {m_min, m_max};
|
||||
|
||||
// Check for ray intersection against x and y slabs
|
||||
float tmin = (bounds[ aRay.m_dirIsNeg[0]].x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
float tmax = (bounds[1 - aRay.m_dirIsNeg[0]].x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
float tmin = (bounds[ aRay.m_dirIsNeg[0]].x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
float tmax = (bounds[1 - aRay.m_dirIsNeg[0]].x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
float tymin = (bounds[ aRay.m_dirIsNeg[1]].y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
float tymax = (bounds[1 - aRay.m_dirIsNeg[1]].y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
|
||||
|
@ -315,8 +329,8 @@ bool CBBOX::Intersect( const RAY &aRay, float *aOutHitt0, float *aOutHitt1 ) con
|
|||
tmax = (tymax < tmax)? tymax : tmax;
|
||||
|
||||
// Check for ray intersection against z slab
|
||||
float tzmin = (bounds[ aRay.m_dirIsNeg[2]].z - aRay.m_Origin.z) * aRay.m_InvDir.z;
|
||||
float tzmax = (bounds[1 - aRay.m_dirIsNeg[2]].z - aRay.m_Origin.z) * aRay.m_InvDir.z;
|
||||
const float tzmin = (bounds[ aRay.m_dirIsNeg[2]].z - aRay.m_Origin.z) * aRay.m_InvDir.z;
|
||||
const float tzmax = (bounds[1 - aRay.m_dirIsNeg[2]].z - aRay.m_Origin.z) * aRay.m_InvDir.z;
|
||||
|
||||
if( (tmin > tzmax) || (tzmin > tmax) )
|
||||
return false;
|
||||
|
@ -338,8 +352,11 @@ void CBBOX::ApplyTransformation( glm::mat4 aTransformMatrix )
|
|||
{
|
||||
wxASSERT( IsInitialized() );
|
||||
|
||||
SFVEC3F v1 = SFVEC3F( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) );
|
||||
SFVEC3F v2 = SFVEC3F( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) );
|
||||
const SFVEC3F v1 = SFVEC3F( aTransformMatrix *
|
||||
glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) );
|
||||
|
||||
const SFVEC3F v2 = SFVEC3F( aTransformMatrix *
|
||||
glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) );
|
||||
|
||||
Reset();
|
||||
Union( v1 );
|
||||
|
@ -349,19 +366,27 @@ void CBBOX::ApplyTransformation( glm::mat4 aTransformMatrix )
|
|||
|
||||
void CBBOX::ApplyTransformationAA( glm::mat4 aTransformMatrix )
|
||||
{
|
||||
// XXX - CB - commented out because it spams the legacy renderer
|
||||
// wxASSERT( IsInitialized() );
|
||||
wxASSERT( IsInitialized() );
|
||||
|
||||
// apply the transformation matrix for each of vertices of the bounding box
|
||||
// and make a union with all vertices
|
||||
CBBOX tmpBBox = CBBOX( SFVEC3F( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_max.x, m_min.y, m_min.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_min.x, m_max.y, m_min.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_max.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_min.x, m_max.y, m_max.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_min.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_max.x, m_min.y, m_max.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) ) );
|
||||
CBBOX tmpBBox = CBBOX(
|
||||
SFVEC3F( aTransformMatrix *
|
||||
glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix *
|
||||
glm::vec4( m_max.x, m_min.y, m_min.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix *
|
||||
glm::vec4( m_min.x, m_max.y, m_min.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix *
|
||||
glm::vec4( m_min.x, m_min.y, m_max.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix *
|
||||
glm::vec4( m_min.x, m_max.y, m_max.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix *
|
||||
glm::vec4( m_max.x, m_max.y, m_min.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix *
|
||||
glm::vec4( m_max.x, m_min.y, m_max.z, 1.0f ) ) );
|
||||
tmpBBox.Union( SFVEC3F( aTransformMatrix *
|
||||
glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) ) );
|
||||
|
||||
m_min = tmpBBox.m_min;
|
||||
m_max = tmpBBox.m_max;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@gmail.com>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -30,15 +30,14 @@
|
|||
#ifndef _CBBOX_H_
|
||||
#define _CBBOX_H_
|
||||
|
||||
#include "plugins/3dapi/xv3d_types.h"
|
||||
#include "3d_rendering/3d_render_raytracing/ray.h"
|
||||
#include <fctsys.h> // For the DBG(
|
||||
#include "../ray.h"
|
||||
#include <fctsys.h> // For the DBG(
|
||||
|
||||
/**
|
||||
* Class CBBOX
|
||||
* manages a bounding box defined by two SFVEC3F min max points.
|
||||
*/
|
||||
GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) CBBOX
|
||||
struct CBBOX
|
||||
{
|
||||
|
||||
public:
|
||||
|
@ -54,7 +53,7 @@ public:
|
|||
* Initialize a bounding box with a given point
|
||||
* @param aPbInit a point for the bounding box initialization
|
||||
*/
|
||||
CBBOX( const SFVEC3F &aPbInit );
|
||||
explicit CBBOX( const SFVEC3F &aPbInit );
|
||||
|
||||
/**
|
||||
* Constructor CBBOX
|
||||
|
@ -77,6 +76,13 @@ public:
|
|||
|
||||
void Set( const CBBOX &aBBox );
|
||||
|
||||
/**
|
||||
* @brief Set
|
||||
* @param aPbMin
|
||||
* @param aPbMax
|
||||
*/
|
||||
void Set( const SFVEC3F &aPoint );
|
||||
|
||||
/**
|
||||
* Function Union
|
||||
* recalculate the bounding box adding a point
|
||||
|
@ -246,8 +252,8 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
SFVEC3F m_min; ///< (12) point of the lower position of the bounding box
|
||||
SFVEC3F m_max; ///< (12) point of the higher position of the bounding box
|
||||
SFVEC3F m_min; ///< (12) point of the lower position of the bounding box
|
||||
SFVEC3F m_max; ///< (12) point of the higher position of the bounding box
|
||||
};
|
||||
|
||||
#endif // CBBox_h
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@gmail.com>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -45,19 +45,21 @@
|
|||
|
||||
bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
||||
{
|
||||
switch ( aRay.m_Classification )
|
||||
switch( aRay.m_Classification )
|
||||
{
|
||||
case MMM:
|
||||
{
|
||||
if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0)
|
||||
|| ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0)
|
||||
|| ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
if( ( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.y < m_min.y ) ||
|
||||
( aRay.m_Origin.z < m_min.z )
|
||||
|| ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0)
|
||||
|| ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0)
|
||||
|| ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
// compute the intersection distance
|
||||
|
||||
|
@ -79,15 +81,17 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case MMP:
|
||||
{
|
||||
if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0)
|
||||
|| ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0)
|
||||
|| ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
if( ( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.y < m_min.y ) ||
|
||||
( aRay.m_Origin.z > m_max.z )
|
||||
|| ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0)
|
||||
|| ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0)
|
||||
|| ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -106,15 +110,17 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case MPM:
|
||||
{
|
||||
if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0)
|
||||
|| ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0)
|
||||
|| ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
if( ( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.y > m_max.y ) ||
|
||||
( aRay.m_Origin.z < m_min.z )
|
||||
|| ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0)
|
||||
|| ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0)
|
||||
|| ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -133,15 +139,17 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case MPP:
|
||||
{
|
||||
if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0)
|
||||
|| ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0)
|
||||
|| ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
if( ( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.y > m_max.y ) ||
|
||||
( aRay.m_Origin.z > m_max.z )
|
||||
|| ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0)
|
||||
|| ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0)
|
||||
|| ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -160,15 +168,17 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case PMM:
|
||||
{
|
||||
if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0)
|
||||
|| ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0)
|
||||
|| ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
if( ( aRay.m_Origin.x > m_max.x ) ||
|
||||
( aRay.m_Origin.y < m_min.y ) ||
|
||||
( aRay.m_Origin.z < m_min.z )
|
||||
|| ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0)
|
||||
|| ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0)
|
||||
|| ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -188,15 +198,17 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case PMP:
|
||||
{
|
||||
if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0)
|
||||
|| ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0)
|
||||
|| ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
if( ( aRay.m_Origin.x > m_max.x ) ||
|
||||
( aRay.m_Origin.y < m_min.y ) ||
|
||||
( aRay.m_Origin.z > m_max.z )
|
||||
|| ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0)
|
||||
|| ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0)
|
||||
|| ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -215,15 +227,17 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case PPM:
|
||||
{
|
||||
if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0)
|
||||
|| ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0)
|
||||
|| ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
if( ( aRay.m_Origin.x > m_max.x ) ||
|
||||
( aRay.m_Origin.y > m_max.y ) ||
|
||||
( aRay.m_Origin.z < m_min.z )
|
||||
|| ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0)
|
||||
|| ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0)
|
||||
|| ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -242,15 +256,17 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case PPP:
|
||||
{
|
||||
if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0)
|
||||
|| ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0)
|
||||
|| ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
if( ( aRay.m_Origin.x > m_max.x ) ||
|
||||
( aRay.m_Origin.y > m_max.y ) ||
|
||||
( aRay.m_Origin.z > m_max.z )
|
||||
|| ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0)
|
||||
|| ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0)
|
||||
|| ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -269,12 +285,13 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case OMM:
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.x > m_max.x )
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
|
||||
|
@ -288,12 +305,13 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case OMP:
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.x > m_max.x )
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
|
||||
|
@ -307,12 +325,12 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case OPM:
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
|
||||
|
@ -326,12 +344,12 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case OPP:
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
|
||||
|
@ -346,12 +364,12 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case MOM:
|
||||
{
|
||||
if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -366,12 +384,12 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case MOP:
|
||||
{
|
||||
if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -385,12 +403,12 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case POM:
|
||||
{
|
||||
if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -405,12 +423,12 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case POP:
|
||||
{
|
||||
if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -424,12 +442,12 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case MMO:
|
||||
{
|
||||
if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y)
|
||||
|| ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y)
|
||||
|| ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -443,12 +461,12 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case MPO:
|
||||
{
|
||||
if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -463,12 +481,12 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case PMO:
|
||||
{
|
||||
if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y)
|
||||
|| ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y)
|
||||
|| ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -482,12 +500,12 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case PPO:
|
||||
{
|
||||
if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -502,11 +520,11 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case MOO:
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.x < m_min.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -515,11 +533,11 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case POO:
|
||||
{
|
||||
if(( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x;
|
||||
|
||||
|
@ -528,11 +546,11 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case OMO:
|
||||
{
|
||||
if(( aRay.m_Origin.y < m_min.y)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.y < m_min.y)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
|
||||
|
@ -541,11 +559,11 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case OPO:
|
||||
{
|
||||
if(( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y;
|
||||
|
||||
|
@ -555,11 +573,11 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case OOM:
|
||||
{
|
||||
if(( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_max.z - aRay.m_Origin.z) * aRay.m_InvDir.z;
|
||||
|
||||
|
@ -568,11 +586,11 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
case OOP:
|
||||
{
|
||||
if(( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
)
|
||||
return false;
|
||||
if(( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
)
|
||||
return false;
|
||||
|
||||
*t = (m_min.z - aRay.m_Origin.z) * aRay.m_InvDir.z;
|
||||
|
||||
|
@ -586,11 +604,13 @@ bool CBBOX::Intersect( const RAY &aRay, float *t ) const
|
|||
|
||||
bool CBBOX::Intersect( const RAY &aRay ) const
|
||||
{
|
||||
switch ( aRay.m_Classification )
|
||||
switch( aRay.m_Classification )
|
||||
{
|
||||
case MMM:
|
||||
{
|
||||
if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
{
|
||||
if( ( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.y < m_min.y ) ||
|
||||
( aRay.m_Origin.z < m_min.z )
|
||||
|| ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0)
|
||||
|| ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0)
|
||||
|
@ -599,14 +619,15 @@ bool CBBOX::Intersect( const RAY &aRay ) const
|
|||
|| ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
case MMP:
|
||||
{
|
||||
if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
{
|
||||
if( ( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.y < m_min.y ) ||
|
||||
( aRay.m_Origin.z > m_max.z )
|
||||
|| ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0)
|
||||
|| ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0)
|
||||
|
@ -615,13 +636,14 @@ bool CBBOX::Intersect( const RAY &aRay ) const
|
|||
|| ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case MPM:
|
||||
{
|
||||
if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
{
|
||||
if( ( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.y > m_max.y ) ||
|
||||
( aRay.m_Origin.z < m_min.z )
|
||||
|| ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0)
|
||||
|| ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0)
|
||||
|
@ -630,13 +652,14 @@ bool CBBOX::Intersect( const RAY &aRay ) const
|
|||
|| ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case MPP:
|
||||
{
|
||||
if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
{
|
||||
if( ( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.y > m_max.y ) ||
|
||||
( aRay.m_Origin.z > m_max.z )
|
||||
|| ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0)
|
||||
|| ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0)
|
||||
|
@ -645,13 +668,14 @@ bool CBBOX::Intersect( const RAY &aRay ) const
|
|||
|| ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case PMM:
|
||||
{
|
||||
if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
{
|
||||
if( ( aRay.m_Origin.x > m_max.x ) ||
|
||||
( aRay.m_Origin.y < m_min.y ) ||
|
||||
( aRay.m_Origin.z < m_min.z )
|
||||
|| ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0)
|
||||
|| ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0)
|
||||
|
@ -660,14 +684,15 @@ bool CBBOX::Intersect( const RAY &aRay ) const
|
|||
|| ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
case PMP:
|
||||
{
|
||||
if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
{
|
||||
if( ( aRay.m_Origin.x > m_max.x ) ||
|
||||
( aRay.m_Origin.y < m_min.y ) ||
|
||||
( aRay.m_Origin.z > m_max.z )
|
||||
|| ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0)
|
||||
|| ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0)
|
||||
|
@ -676,13 +701,14 @@ bool CBBOX::Intersect( const RAY &aRay ) const
|
|||
|| ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case PPM:
|
||||
{
|
||||
if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
{
|
||||
if( ( aRay.m_Origin.x > m_max.x ) ||
|
||||
( aRay.m_Origin.y > m_max.y ) ||
|
||||
( aRay.m_Origin.z < m_min.z )
|
||||
|| ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0)
|
||||
|| ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0)
|
||||
|
@ -691,13 +717,14 @@ bool CBBOX::Intersect( const RAY &aRay ) const
|
|||
|| ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case PPP:
|
||||
{
|
||||
if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
{
|
||||
if( ( aRay.m_Origin.x > m_max.x ) ||
|
||||
( aRay.m_Origin.y > m_max.y ) ||
|
||||
( aRay.m_Origin.z > m_max.z )
|
||||
|| ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0)
|
||||
|| ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0)
|
||||
|
@ -706,225 +733,209 @@ bool CBBOX::Intersect( const RAY &aRay ) const
|
|||
|| ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case OMM:
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0)
|
||||
)
|
||||
{
|
||||
if( ( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.x > m_max.x )
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case OMP:
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.x > m_max.x )
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0)
|
||||
|| ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case OPM:
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.x > m_max.x )
|
||||
|| ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case OPP:
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x ) ||
|
||||
( aRay.m_Origin.x > m_max.x )
|
||||
|| ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0)
|
||||
|| ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
case MOM:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
case MOP:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case POM:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0)
|
||||
|| ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
case POP:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0)
|
||||
|| ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case MMO:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y)
|
||||
|| ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case MPO:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
case PMO:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y)
|
||||
|| ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0)
|
||||
|| ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case PPO:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0)
|
||||
|| ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
case MOO:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.x < m_min.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case POO:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case OMO:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.y < m_min.y)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case OPO:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.y > m_max.y)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
case OOM:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.z < m_min.z)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case OOP:
|
||||
{
|
||||
{
|
||||
if(( aRay.m_Origin.z > m_max.z)
|
||||
|| ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x)
|
||||
|| ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y)
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* 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 ccylinder.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "3d_fastmath.h"
|
||||
#include "ccylinder.h"
|
||||
|
||||
|
||||
CVCYLINDER::CVCYLINDER( SFVEC2F aCenterPoint,
|
||||
float aZmin,
|
||||
float aZmax,
|
||||
float aRadius ) : COBJECT( OBJ3D_CYLINDER )
|
||||
{
|
||||
m_center = aCenterPoint;
|
||||
m_radius_squared = aRadius * aRadius;
|
||||
m_inv_radius = 1.0f / aRadius;
|
||||
|
||||
m_bbox.Set( SFVEC3F( aCenterPoint.x - aRadius,
|
||||
aCenterPoint.y - aRadius,
|
||||
aZmin ),
|
||||
SFVEC3F( aCenterPoint.x + aRadius,
|
||||
aCenterPoint.y + aRadius,
|
||||
aZmax ) );
|
||||
m_bbox.ScaleNextUp();
|
||||
m_centroid = m_bbox.GetCenter();
|
||||
}
|
||||
|
||||
|
||||
bool CVCYLINDER::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
|
||||
{
|
||||
// Based on:
|
||||
// http://www.cs.utah.edu/~lha/Code%206620%20/Ray4/Cylinder.cpp
|
||||
// Ray-sphere intersection: geometric
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
const double OCx_Start = aRay.m_Origin.x - m_center.x;
|
||||
const double OCy_Start = aRay.m_Origin.y - m_center.y;
|
||||
|
||||
const double p_dot_p = OCx_Start * OCx_Start + OCy_Start * OCy_Start;
|
||||
|
||||
const double a = (double)aRay.m_Dir.x * (double)aRay.m_Dir.x +
|
||||
(double)aRay.m_Dir.y * (double)aRay.m_Dir.y;
|
||||
const double b = (double)aRay.m_Dir.x * (double)OCx_Start +
|
||||
(double)aRay.m_Dir.y * (double)OCy_Start;
|
||||
const double c = p_dot_p - m_radius_squared;
|
||||
|
||||
const float delta = (float)(b * b - a * c);
|
||||
|
||||
bool hitResult = false;
|
||||
|
||||
if( delta > FLT_EPSILON )
|
||||
{
|
||||
const float inv_a = 1.0 / a;
|
||||
|
||||
const float sdelta = sqrtf( delta );
|
||||
const float t = (-b - sdelta) * inv_a;
|
||||
const float z = aRay.m_Origin.z + t * aRay.m_Dir.z;
|
||||
|
||||
if( (z >= m_bbox.Min().z) &&
|
||||
(z <= m_bbox.Max().z) )
|
||||
{
|
||||
if( t < aHitInfo.m_tHit )
|
||||
{
|
||||
hitResult = true;
|
||||
aHitInfo.m_tHit = t;
|
||||
}
|
||||
}
|
||||
|
||||
if( !hitResult )
|
||||
{
|
||||
const float t1 = (-b + sdelta) * inv_a;
|
||||
const float z1 = aRay.m_Origin.z + t1 * aRay.m_Dir.z;
|
||||
|
||||
if( (z1 > m_bbox.Min().z ) &&
|
||||
(z1 < m_bbox.Max().z ) )
|
||||
{
|
||||
if( t1 < aHitInfo.m_tHit )
|
||||
{
|
||||
hitResult = true;
|
||||
aHitInfo.m_tHit = t1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( hitResult )
|
||||
{
|
||||
const SFVEC2F hitPoint2D = aRay.at2D( aHitInfo.m_tHit );
|
||||
//aHitInfo.m_HitPoint =
|
||||
aHitInfo.m_HitNormal = SFVEC3F( -(hitPoint2D.x - m_center.x) * m_inv_radius,
|
||||
-(hitPoint2D.y - m_center.y) * m_inv_radius,
|
||||
0.0f );
|
||||
aHitInfo.pHitObject = this;
|
||||
}
|
||||
|
||||
return hitResult;
|
||||
}
|
||||
|
||||
|
||||
bool CVCYLINDER::IntersectP(const RAY &aRay , float aMaxDistance ) const
|
||||
{
|
||||
// Based on:
|
||||
// http://www.cs.utah.edu/~lha/Code%206620%20/Ray4/Cylinder.cpp
|
||||
// Ray-sphere intersection: geometric
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
const double OCx_Start = aRay.m_Origin.x - m_center.x;
|
||||
const double OCy_Start = aRay.m_Origin.y - m_center.y;
|
||||
|
||||
const double p_dot_p = OCx_Start * OCx_Start + OCy_Start * OCy_Start;
|
||||
|
||||
const double a = (double)aRay.m_Dir.x * (double)aRay.m_Dir.x +
|
||||
(double)aRay.m_Dir.y * (double)aRay.m_Dir.y;
|
||||
const double b = (double)aRay.m_Dir.x * (double)OCx_Start +
|
||||
(double)aRay.m_Dir.y * (double)OCy_Start;
|
||||
const double c = p_dot_p - m_radius_squared;
|
||||
|
||||
const float delta = (float)(b * b - a * c);
|
||||
|
||||
if( delta > FLT_EPSILON )
|
||||
{
|
||||
const float inv_a = 1.0 / a;
|
||||
|
||||
const float sdelta = sqrtf( delta );
|
||||
const float t = (-b - sdelta) * inv_a;
|
||||
const float z = aRay.m_Origin.z + t * aRay.m_Dir.z;
|
||||
|
||||
if( (z >= m_bbox.Min().z) &&
|
||||
(z <= m_bbox.Max().z) )
|
||||
{
|
||||
if( t < aMaxDistance )
|
||||
return true;
|
||||
}
|
||||
|
||||
const float t1 = (-b + sdelta) * inv_a;
|
||||
const float z1 = aRay.m_Origin.z + t1 * aRay.m_Dir.z;
|
||||
|
||||
if( (z1 > m_bbox.Min().z ) &&
|
||||
(z1 < m_bbox.Max().z ) )
|
||||
{
|
||||
if( t1 < aMaxDistance )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CVCYLINDER::Intersects( const CBBOX &aBBox ) const
|
||||
{
|
||||
// !TODO: improove
|
||||
return m_bbox.Intersects( aBBox );
|
||||
}
|
||||
|
||||
SFVEC3F CVCYLINDER::GetDiffuseColor( const HITINFO &aHitInfo ) const
|
||||
{
|
||||
(void)aHitInfo; // unused
|
||||
|
||||
return m_diffusecolor;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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 ccylinder.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef _CCYLINDER_H_
|
||||
#define _CCYLINDER_H_
|
||||
|
||||
#include "cobject.h"
|
||||
|
||||
/**
|
||||
* A vertical cylinder
|
||||
*/
|
||||
class CVCYLINDER : public COBJECT
|
||||
{
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor CVCYLINDER
|
||||
* @param aCenterPoint = position of the center of the plane
|
||||
* @param aXSize = size by X axis
|
||||
* @param aYSize = size by Y axis
|
||||
*/
|
||||
CVCYLINDER( SFVEC2F aCenterPoint, float aZmin, float aZmax, float aRadius );
|
||||
|
||||
void SetColor( SFVEC3F aObjColor ) { m_diffusecolor = aObjColor; }
|
||||
|
||||
// Imported from COBJECT
|
||||
bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const;
|
||||
bool IntersectP(const RAY &aRay , float aMaxDistance ) const;
|
||||
bool Intersects( const CBBOX &aBBox ) const;
|
||||
SFVEC3F GetDiffuseColor( const HITINFO &aHitInfo ) const;
|
||||
|
||||
private:
|
||||
SFVEC2F m_center;
|
||||
float m_radius_squared;
|
||||
float m_inv_radius;
|
||||
SFVEC3F m_diffusecolor;
|
||||
};
|
||||
|
||||
|
||||
#endif // _CCYLINDER_H_
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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 cdummyblock.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "cdummyblock.h"
|
||||
|
||||
|
||||
CDUMMYBLOCK::CDUMMYBLOCK( const CBBOX &aBBox ) : COBJECT( OBJ3D_DUMMYBLOCK )
|
||||
{
|
||||
m_centroid = aBBox.GetCenter();
|
||||
m_bbox.Reset();
|
||||
m_bbox.Set( aBBox );
|
||||
}
|
||||
|
||||
|
||||
bool CDUMMYBLOCK::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
|
||||
{
|
||||
float t;
|
||||
|
||||
if( !m_bbox.Intersect( aRay, &t ) )
|
||||
return false;
|
||||
|
||||
if( t < aHitInfo.m_tHit )
|
||||
{
|
||||
aHitInfo.m_tHit = t;
|
||||
//aHitInfo.m_HitPoint = aRay.at( t );
|
||||
if( aRay.m_dirIsNeg[2] )
|
||||
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f );
|
||||
else
|
||||
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f,-1.0f );
|
||||
aHitInfo.pHitObject = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CDUMMYBLOCK::IntersectP(const RAY &aRay , float aMaxDistance ) const
|
||||
{
|
||||
float t;
|
||||
|
||||
if( !m_bbox.Intersect( aRay, &t ) )
|
||||
return false;
|
||||
|
||||
if( t < aMaxDistance )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CDUMMYBLOCK::Intersects( const CBBOX &aBBox ) const
|
||||
{
|
||||
return m_bbox.Intersects( aBBox );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CDUMMYBLOCK::GetDiffuseColor( const HITINFO &aHitInfo ) const
|
||||
{
|
||||
(void)aHitInfo; // unused
|
||||
|
||||
return m_diffusecolor;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 cdummyblock.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef _CDUMMYBLOCK_H_
|
||||
#define _CDUMMYBLOCK_H_
|
||||
|
||||
#include "cobject.h"
|
||||
|
||||
/**
|
||||
* A dummy block is used to fill the polygons. It will only will be intersepted
|
||||
* from top or from bottom
|
||||
*/
|
||||
class CDUMMYBLOCK : public COBJECT
|
||||
{
|
||||
|
||||
public:
|
||||
explicit CDUMMYBLOCK( const CBBOX &aBBox );
|
||||
|
||||
void SetColor( SFVEC3F aObjColor ) { m_diffusecolor = aObjColor; }
|
||||
|
||||
// Imported from COBJECT
|
||||
bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const;
|
||||
bool IntersectP(const RAY &aRay , float aMaxDistance ) const;
|
||||
bool Intersects( const CBBOX &aBBox ) const;
|
||||
SFVEC3F GetDiffuseColor( const HITINFO &aHitInfo ) const;
|
||||
private:
|
||||
SFVEC3F m_diffusecolor;
|
||||
};
|
||||
|
||||
|
||||
#endif // _CDUMMYBLOCK_H_
|
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
* 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 clayeritem.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "clayeritem.h"
|
||||
#include "3d_fastmath.h"
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
||||
CLAYERITEM::CLAYERITEM( const COBJECT2D *aObject2D, float aZMin, float aZMax ) :
|
||||
COBJECT( OBJ3D_LAYERITEM ),
|
||||
m_object2d(aObject2D)
|
||||
{
|
||||
wxASSERT( aObject2D );
|
||||
|
||||
CBBOX2D bbox2d = m_object2d->GetBBox();
|
||||
bbox2d.ScaleNextUp();
|
||||
bbox2d.ScaleNextUp();
|
||||
|
||||
m_bbox.Reset();
|
||||
m_bbox.Set( SFVEC3F( bbox2d.Min().x, bbox2d.Min().y, aZMin ),
|
||||
SFVEC3F( bbox2d.Max().x, bbox2d.Max().y, aZMax ) );
|
||||
m_bbox.ScaleNextUp();
|
||||
m_centroid = SFVEC3F( aObject2D->GetCentroid().x,
|
||||
aObject2D->GetCentroid().y,
|
||||
(aZMax + aZMin) * 0.5f );
|
||||
}
|
||||
|
||||
|
||||
bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
|
||||
{
|
||||
float tBBoxStart;
|
||||
float tBBoxEnd;
|
||||
|
||||
if( !m_bbox.Intersect( aRay, &tBBoxStart, &tBBoxEnd ) )
|
||||
return false;
|
||||
|
||||
if( tBBoxStart >= aHitInfo.m_tHit )
|
||||
return false;
|
||||
|
||||
if( fabs(tBBoxStart - tBBoxEnd) < FLT_EPSILON )
|
||||
return false;
|
||||
|
||||
bool startedInside = m_bbox.Inside( aRay.m_Origin );
|
||||
|
||||
if( !startedInside )
|
||||
{
|
||||
float tTop = FLT_MAX;
|
||||
float tBot = FLT_MAX;
|
||||
bool hit_top = false;
|
||||
bool hit_bot = false;
|
||||
|
||||
if( (float)fabs(aRay.m_Dir.z) > FLT_EPSILON )
|
||||
{
|
||||
tBot = (m_bbox.Min().z - aRay.m_Origin.z) * aRay.m_InvDir.z;
|
||||
tTop = (m_bbox.Max().z - aRay.m_Origin.z) * aRay.m_InvDir.z;
|
||||
|
||||
float tBBoxStartAdjusted = NextFloatUp( tBBoxStart );
|
||||
|
||||
if( tBot > FLT_EPSILON )
|
||||
{
|
||||
hit_bot = tBot <= tBBoxStartAdjusted;
|
||||
tBot = NextFloatDown( tBot );
|
||||
}
|
||||
|
||||
if( tTop > FLT_EPSILON )
|
||||
{
|
||||
hit_top = tTop <= tBBoxStartAdjusted;
|
||||
tTop = NextFloatDown( tTop );
|
||||
}
|
||||
}
|
||||
|
||||
tBBoxStart = NextFloatDown( tBBoxStart );
|
||||
tBBoxEnd = NextFloatUp( tBBoxEnd );
|
||||
|
||||
SFVEC2F topHitPoint2d;
|
||||
SFVEC2F botHitPoint2d;
|
||||
|
||||
if( hit_top )
|
||||
topHitPoint2d = SFVEC2F( aRay.m_Origin.x + aRay.m_Dir.x * tTop,
|
||||
aRay.m_Origin.y + aRay.m_Dir.y * tTop );
|
||||
|
||||
if( hit_bot )
|
||||
botHitPoint2d = SFVEC2F( aRay.m_Origin.x + aRay.m_Dir.x * tBot,
|
||||
aRay.m_Origin.y + aRay.m_Dir.y * tBot );
|
||||
|
||||
if( hit_top && hit_bot )
|
||||
{
|
||||
if( tBot < tTop )
|
||||
{
|
||||
if( m_object2d->IsPointInside( botHitPoint2d ) )
|
||||
{
|
||||
if( tBot < aHitInfo.m_tHit )
|
||||
{
|
||||
aHitInfo.m_tHit = tBot;
|
||||
//aHitInfo.m_HitPoint = aRay.at( tBot );
|
||||
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, -1.0f );
|
||||
aHitInfo.pHitObject = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_object2d->IsPointInside( topHitPoint2d ) )
|
||||
{
|
||||
if( tTop < aHitInfo.m_tHit )
|
||||
{
|
||||
aHitInfo.m_tHit = tTop;
|
||||
//aHitInfo.m_HitPoint = aRay.at( tTop );
|
||||
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f );
|
||||
aHitInfo.pHitObject = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( hit_top )
|
||||
{
|
||||
if( tTop < tBot )
|
||||
{
|
||||
if( m_object2d->IsPointInside( topHitPoint2d ) )
|
||||
{
|
||||
if( tTop < aHitInfo.m_tHit )
|
||||
{
|
||||
aHitInfo.m_tHit = tTop;
|
||||
//aHitInfo.m_HitPoint = aRay.at( tTop );
|
||||
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f );
|
||||
aHitInfo.pHitObject = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( hit_bot )
|
||||
{
|
||||
if( tBot < tTop )
|
||||
{
|
||||
if( m_object2d->IsPointInside( botHitPoint2d ) )
|
||||
{
|
||||
if( tBot < aHitInfo.m_tHit )
|
||||
{
|
||||
aHitInfo.m_tHit = tBot;
|
||||
//aHitInfo.m_HitPoint = aRay.at( tBot );
|
||||
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, -1.0f );
|
||||
aHitInfo.pHitObject = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// At this point, the ray miss the two planes but it still
|
||||
// hits the box. It means that the rays are "(almost)paralell"
|
||||
// to the planes, so must calc the intersection
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F boxHitPointStart = aRay.at( tBBoxStart );
|
||||
SFVEC3F boxHitPointEnd = aRay.at( tBBoxEnd );
|
||||
|
||||
SFVEC2F boxHitPointStart2D( boxHitPointStart.x, boxHitPointStart.y );
|
||||
//SFVEC2F boxHitPointStart2D( m_bbox.GetCenter().x, m_bbox.GetCenter().y );
|
||||
|
||||
SFVEC2F boxHitPointEnd2D( boxHitPointEnd.x, boxHitPointEnd.y );
|
||||
|
||||
float tOut;
|
||||
SFVEC2F outNormal;
|
||||
RAYSEG2D raySeg( boxHitPointStart2D, boxHitPointEnd2D );
|
||||
|
||||
if( m_object2d->Intersect( raySeg, &tOut, &outNormal ) )
|
||||
{
|
||||
// The hitT is a hit value for the segment length 'start' - 'end',
|
||||
// so it ranges from 0.0 - 1.0. We now convert it to a 3D hit position
|
||||
// and calculate the real hitT of the ray.
|
||||
SFVEC3F hitPoint = boxHitPointStart +
|
||||
(boxHitPointEnd - boxHitPointStart) * tOut;
|
||||
const float t = glm::length( hitPoint - aRay.m_Origin );
|
||||
|
||||
if( t < aHitInfo.m_tHit )
|
||||
{
|
||||
aHitInfo.m_tHit = t;
|
||||
//aHitInfo.m_HitPoint = hitPoint;
|
||||
aHitInfo.m_HitNormal = SFVEC3F( outNormal.x, outNormal.y, 0.0f );
|
||||
aHitInfo.pHitObject = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Started inside
|
||||
|
||||
const SFVEC3F boxHitPointStart = aRay.at( tBBoxStart );
|
||||
const SFVEC3F boxHitPointEnd = aRay.at( tBBoxEnd );
|
||||
|
||||
const SFVEC2F boxHitPointStart2D( boxHitPointStart.x, boxHitPointStart.y );
|
||||
|
||||
const SFVEC2F boxHitPointEnd2D( boxHitPointEnd.x, boxHitPointEnd.y );
|
||||
|
||||
if(!(m_object2d->IsPointInside( boxHitPointStart2D ) &&
|
||||
m_object2d->IsPointInside( boxHitPointEnd2D ) ) )
|
||||
return false;
|
||||
|
||||
float tOut;
|
||||
SFVEC2F outNormal;
|
||||
RAYSEG2D raySeg( boxHitPointStart2D, boxHitPointEnd2D );
|
||||
|
||||
if( (m_object2d->IsPointInside( boxHitPointStart2D ) &&
|
||||
m_object2d->IsPointInside( boxHitPointEnd2D ) ) )
|
||||
{
|
||||
if( tBBoxEnd < aHitInfo.m_tHit )
|
||||
{
|
||||
aHitInfo.m_tHit = tBBoxEnd;
|
||||
|
||||
if( aRay.m_Dir.z > 0.0f )
|
||||
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, -1.0f );
|
||||
else
|
||||
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f );
|
||||
|
||||
aHitInfo.pHitObject = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_object2d->Intersect( raySeg, &tOut, &outNormal ) )
|
||||
{
|
||||
// The hitT is a hit value for the segment length 'start' - 'end',
|
||||
// so it ranges from 0.0 - 1.0. We now convert it to a 3D hit position
|
||||
// and calculate the real hitT of the ray.
|
||||
const SFVEC3F hitPoint = boxHitPointStart +
|
||||
(boxHitPointEnd - boxHitPointStart) * tOut;
|
||||
const float t = glm::length( hitPoint - aRay.m_Origin );
|
||||
|
||||
if( t < aHitInfo.m_tHit )
|
||||
{
|
||||
aHitInfo.m_tHit = t;
|
||||
//aHitInfo.m_HitPoint = hitPoint;
|
||||
aHitInfo.m_HitNormal = SFVEC3F( outNormal.x, outNormal.y, 0.0f );
|
||||
aHitInfo.pHitObject = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CLAYERITEM::IntersectP(const RAY &aRay , float aMaxDistance ) const
|
||||
{
|
||||
float tBBoxStart;
|
||||
float tBBoxEnd;
|
||||
|
||||
if( !m_bbox.Intersect( aRay, &tBBoxStart, &tBBoxEnd ) )
|
||||
return false;
|
||||
|
||||
if( ( tBBoxStart > aMaxDistance ) ||
|
||||
//( tBBoxEnd < FLT_EPSILON )
|
||||
( fabs(tBBoxStart - tBBoxEnd) < FLT_EPSILON ) )
|
||||
return false;
|
||||
|
||||
float tTop = FLT_MAX;
|
||||
float tBot = FLT_MAX;
|
||||
bool hit_top = false;
|
||||
bool hit_bot = false;
|
||||
|
||||
if( (float)fabs(aRay.m_Dir.z) > FLT_EPSILON )
|
||||
{
|
||||
tBot = (m_bbox.Min().z - aRay.m_Origin.z) * aRay.m_InvDir.z;
|
||||
tTop = (m_bbox.Max().z - aRay.m_Origin.z) * aRay.m_InvDir.z;
|
||||
|
||||
const float tBBoxStartAdjusted = NextFloatUp( tBBoxStart );
|
||||
|
||||
if( tBot > FLT_EPSILON )
|
||||
{
|
||||
hit_bot = tBot <= tBBoxStartAdjusted;
|
||||
tBot = NextFloatDown( tBot );
|
||||
}
|
||||
|
||||
if( tTop > FLT_EPSILON )
|
||||
{
|
||||
hit_top = tTop <= tBBoxStartAdjusted;
|
||||
tTop = NextFloatDown( tTop );
|
||||
}
|
||||
}
|
||||
|
||||
tBBoxStart = NextFloatDown( tBBoxStart );
|
||||
tBBoxEnd = NextFloatUp( tBBoxEnd );
|
||||
|
||||
SFVEC2F topHitPoint2d;
|
||||
SFVEC2F botHitPoint2d;
|
||||
|
||||
if( hit_top )
|
||||
topHitPoint2d = SFVEC2F( aRay.m_Origin.x + aRay.m_Dir.x * tTop,
|
||||
aRay.m_Origin.y + aRay.m_Dir.y * tTop );
|
||||
|
||||
if( hit_bot )
|
||||
botHitPoint2d = SFVEC2F( aRay.m_Origin.x + aRay.m_Dir.x * tBot,
|
||||
aRay.m_Origin.y + aRay.m_Dir.y * tBot );
|
||||
|
||||
if( hit_top && hit_bot )
|
||||
{
|
||||
if( tBot < tTop )
|
||||
{
|
||||
if( m_object2d->IsPointInside( botHitPoint2d ) )
|
||||
{
|
||||
if( tBot < aMaxDistance )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_object2d->IsPointInside( topHitPoint2d ) )
|
||||
{
|
||||
if( tTop < aMaxDistance )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( hit_top )
|
||||
{
|
||||
if( tTop < tBot )
|
||||
{
|
||||
if( m_object2d->IsPointInside( topHitPoint2d ) )
|
||||
{
|
||||
if( tTop < aMaxDistance )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( hit_bot )
|
||||
{
|
||||
if( tBot < tTop )
|
||||
{
|
||||
if( m_object2d->IsPointInside( botHitPoint2d ) )
|
||||
{
|
||||
if( tBot < aMaxDistance )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// At this point, the ray miss the two planes but it still
|
||||
// hits the box. It means that the rays are "(almost)paralell"
|
||||
// to the planes, so must calc the intersection
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SFVEC3F boxHitPointStart = aRay.at( tBBoxStart );
|
||||
SFVEC3F boxHitPointEnd = aRay.at( tBBoxEnd );
|
||||
|
||||
SFVEC2F boxHitPointStart2D( boxHitPointStart.x, boxHitPointStart.y );
|
||||
|
||||
SFVEC2F boxHitPointEnd2D( boxHitPointEnd.x, boxHitPointEnd.y );
|
||||
|
||||
float tOut;
|
||||
SFVEC2F outNormal;
|
||||
RAYSEG2D raySeg( boxHitPointStart2D, boxHitPointEnd2D );
|
||||
|
||||
if( m_object2d->Intersect( raySeg, &tOut, &outNormal ) )
|
||||
{
|
||||
//if( (tOut > FLT_EPSILON) && (tOut < 1.0f) )
|
||||
{
|
||||
// The hitT is a hit value for the segment length 'start' - 'end',
|
||||
// so it ranges from 0.0 - 1.0. We now convert it to a 3D hit position
|
||||
// and calculate the real hitT of the ray.
|
||||
const SFVEC3F hitPoint = boxHitPointStart +
|
||||
(boxHitPointEnd - boxHitPointStart) * tOut;
|
||||
const float t = glm::length( hitPoint - aRay.m_Origin );
|
||||
|
||||
if( (t < 1.0f) && ( t > FLT_EPSILON ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CLAYERITEM::Intersects( const CBBOX &aBBox ) const
|
||||
{
|
||||
if( !m_bbox.Intersects( aBBox ) )
|
||||
return false;
|
||||
|
||||
const CBBOX2D bbox2D( SFVEC2F( aBBox.Min().x, aBBox.Min().y),
|
||||
SFVEC2F( aBBox.Max().x, aBBox.Max().y) );
|
||||
|
||||
return m_object2d->Intersects( bbox2D );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CLAYERITEM::GetDiffuseColor( const HITINFO &aHitInfo ) const
|
||||
{
|
||||
(void)aHitInfo; // unused
|
||||
|
||||
return m_diffusecolor;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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 clayeritem.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef _CLAYERITEM_H_
|
||||
#define _CLAYERITEM_H_
|
||||
|
||||
#include "cobject.h"
|
||||
#include "../shapes2D/cobject2d.h"
|
||||
|
||||
|
||||
class CLAYERITEM : public COBJECT
|
||||
{
|
||||
protected:
|
||||
const COBJECT2D *m_object2d;
|
||||
|
||||
public:
|
||||
|
||||
CLAYERITEM( const COBJECT2D *aObject2D, float aZMin, float aZMax );
|
||||
|
||||
void SetColor( SFVEC3F aObjColor ) { m_diffusecolor = aObjColor; }
|
||||
|
||||
// Imported from COBJECT
|
||||
bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const;
|
||||
bool IntersectP(const RAY &aRay , float aMaxDistance ) const;
|
||||
bool Intersects( const CBBOX &aBBox ) const;
|
||||
SFVEC3F GetDiffuseColor( const HITINFO &aHitInfo ) const;
|
||||
|
||||
private:
|
||||
SFVEC3F m_diffusecolor;
|
||||
};
|
||||
|
||||
#endif // _CLAYERITEM_H_
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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 cobject.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "cobject.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
COBJECT3D_STATS *COBJECT3D_STATS::s_instance = 0;
|
||||
|
||||
static const CBLINN_PHONG_MATERIAL s_defaultMaterial = CBLINN_PHONG_MATERIAL();
|
||||
|
||||
COBJECT::COBJECT( OBJECT3D_TYPE aObjType )
|
||||
{
|
||||
m_obj_type = aObjType;
|
||||
COBJECT3D_STATS::Instance().AddOne( aObjType );
|
||||
m_material = &s_defaultMaterial;
|
||||
}
|
||||
|
||||
|
||||
static const char *OBJECT3D_STR[OBJ3D_MAX] =
|
||||
{
|
||||
"OBJ3D_CYLINDER",
|
||||
"OBJ3D_DUMMYBLOCK",
|
||||
"OBJ3D_LAYERITEM",
|
||||
"OBJ3D_XYPLANE",
|
||||
"OBJ3D_ROUNDSEG",
|
||||
"OBJ3D_TRIANGLE"
|
||||
};
|
||||
|
||||
|
||||
void COBJECT3D_STATS::PrintStats()
|
||||
{
|
||||
printf( "OBJ3D Statistics:\n" );
|
||||
|
||||
for( unsigned int i = 0; i < OBJ3D_MAX; ++i )
|
||||
{
|
||||
printf( " %20s %u\n", OBJECT3D_STR[i], m_counter[i] );
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
|
@ -30,7 +30,6 @@
|
|||
#ifndef _COBJECT_H_
|
||||
#define _COBJECT_H_
|
||||
|
||||
#include "plugins/3dapi/xv3d_types.h"
|
||||
#include "cbbox.h"
|
||||
#include "../hitinfo.h"
|
||||
#include "../cmaterial.h"
|
||||
|
@ -47,7 +46,7 @@ enum OBJECT3D_TYPE
|
|||
OBJ3D_MAX
|
||||
};
|
||||
|
||||
class GLM_ALIGN(CLASS_ALIGNMENT) COBJECT
|
||||
class COBJECT
|
||||
{
|
||||
protected:
|
||||
CBBOX m_bbox;
|
||||
|
@ -57,7 +56,7 @@ protected:
|
|||
|
||||
public:
|
||||
|
||||
COBJECT( OBJECT3D_TYPE aObjType );
|
||||
explicit COBJECT( OBJECT3D_TYPE aObjType );
|
||||
|
||||
void SetMaterial( const CMATERIAL *aMaterial ) { m_material = aMaterial; }
|
||||
const CMATERIAL *GetMaterial() const { return m_material; }
|
||||
|
@ -103,7 +102,9 @@ class COBJECT3D_STATS
|
|||
{
|
||||
public:
|
||||
|
||||
void ResetStats() { memset( m_counter, 0, sizeof(unsigned int) * OBJ3D_MAX ); }
|
||||
void ResetStats() { memset( m_counter,
|
||||
0,
|
||||
sizeof( unsigned int ) * OBJ3D_MAX ); }
|
||||
|
||||
unsigned int GetCountOf( OBJECT3D_TYPE aObjType ) const { return m_counter[aObjType]; }
|
||||
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* 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 cplane.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "cplane.h"
|
||||
|
||||
|
||||
CXYPLANE::CXYPLANE( const CBBOX &aBBox ) : COBJECT( OBJ3D_XYPLANE )
|
||||
{
|
||||
m_centerPoint = aBBox.GetCenter();
|
||||
m_centroid = m_centerPoint;
|
||||
|
||||
m_bbox.Reset();
|
||||
m_bbox.Set( aBBox );
|
||||
m_xsize = aBBox.GetExtent().x;
|
||||
m_ysize = aBBox.GetExtent().y;
|
||||
m_xsize_inv2 = 1.0f / (2.0f * m_xsize);
|
||||
m_ysize_inv2 = 1.0f / (2.0f * m_ysize);
|
||||
}
|
||||
|
||||
|
||||
CXYPLANE::CXYPLANE( SFVEC3F aCenterPoint,
|
||||
float aXSize,
|
||||
float aYSize ) : COBJECT( OBJ3D_XYPLANE )
|
||||
{
|
||||
m_centerPoint = aCenterPoint;
|
||||
m_xsize = aXSize;
|
||||
m_ysize = aYSize;
|
||||
m_xsize_inv2 = 1.0f / (2.0f * aXSize);
|
||||
m_ysize_inv2 = 1.0f / (2.0f * aYSize);
|
||||
m_bbox.Set( SFVEC3F( aCenterPoint.x - aXSize / 2.0f,
|
||||
aCenterPoint.y - aYSize / 2.0f,
|
||||
aCenterPoint.z ),
|
||||
SFVEC3F( aCenterPoint.x + aXSize / 2.0f,
|
||||
aCenterPoint.y + aYSize / 2.0f,
|
||||
aCenterPoint.z ) );
|
||||
m_centroid = aCenterPoint;
|
||||
}
|
||||
|
||||
|
||||
bool CXYPLANE::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
|
||||
{
|
||||
const float t = (m_centerPoint.z - aRay.m_Origin.z) * aRay.m_InvDir.z;
|
||||
|
||||
if( ( t < FLT_EPSILON ) ||
|
||||
( t >= aHitInfo.m_tHit ) )
|
||||
return false;
|
||||
|
||||
const float vSU = t * aRay.m_Dir.x + aRay.m_Origin.x - m_centerPoint.x;
|
||||
|
||||
if( (vSU < -m_xsize) || (vSU > m_xsize) )
|
||||
return false;
|
||||
|
||||
const float vSV = t * aRay.m_Dir.y + aRay.m_Origin.y - m_centerPoint.y;
|
||||
|
||||
if( (vSV < -m_ysize) || (vSV > m_ysize) )
|
||||
return false;
|
||||
|
||||
aHitInfo.m_tHit = t;
|
||||
//aHitInfo.m_HitPoint = aRay.at( t );
|
||||
aHitInfo.pHitObject = this;
|
||||
|
||||
if( aRay.m_dirIsNeg[2] )
|
||||
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f );
|
||||
else
|
||||
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f,-1.0f );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CXYPLANE::IntersectP(const RAY &aRay , float aMaxDistance ) const
|
||||
{
|
||||
const float t = (m_centerPoint.z - aRay.m_Origin.z) * aRay.m_InvDir.z;
|
||||
|
||||
if( ( t < FLT_EPSILON ) ||
|
||||
( t >= aMaxDistance ) )
|
||||
return false;
|
||||
|
||||
const float vSU = t * aRay.m_Dir.x + aRay.m_Origin.x - m_centerPoint.x;
|
||||
|
||||
if( (vSU < -m_xsize) || (vSU > m_xsize) )
|
||||
return false;
|
||||
|
||||
const float vSV = t * aRay.m_Dir.y + aRay.m_Origin.y - m_centerPoint.y;
|
||||
|
||||
if( (vSV < -m_ysize) || (vSV > m_ysize) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CXYPLANE::Intersects( const CBBOX &aBBox ) const
|
||||
{
|
||||
return m_bbox.Intersects( aBBox );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CXYPLANE::GetDiffuseColor( const HITINFO &aHitInfo ) const
|
||||
{
|
||||
(void)aHitInfo; // unused
|
||||
|
||||
return m_diffusecolor;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue