+ Rework S3D_CACHE::Prepare() to take only a filename and return

non-transformed S3DMODEL for rendering.
+ S3D_CACHE now caches S3DMODEL and returns a pointer to a single
  instance of the S3DMODEL for repeated calls to Prepare()
+ Beginning the VRML Plugin
This commit is contained in:
Cirilo Bernardo 2015-12-16 20:01:44 +11:00
parent 580f7aecfc
commit c0fcb15e3a
14 changed files with 480 additions and 84 deletions

View File

@ -134,12 +134,14 @@ public:
unsigned char md5sum[16];
SCENEGRAPH* sceneData;
S3DMODEL* renderData;
};
S3D_CACHE_ENTRY::S3D_CACHE_ENTRY()
{
sceneData = NULL;
renderData = NULL;
memset( md5sum, 0, 16 );
}
@ -148,6 +150,9 @@ S3D_CACHE_ENTRY::~S3D_CACHE_ENTRY()
{
if( NULL != sceneData )
delete sceneData;
if( NULL != renderData )
S3D::Destroy3DModel( &renderData );
}
@ -197,8 +202,11 @@ S3D_CACHE::~S3D_CACHE()
}
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile )
SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr )
{
if( aCachePtr )
*aCachePtr = NULL;
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile );
if( full3Dpath.empty() )
@ -214,15 +222,29 @@ SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile )
mi = m_CacheMap.find( full3Dpath );
if( mi != m_CacheMap.end() )
{
if( NULL != aCachePtr )
*aCachePtr = mi->second;
return mi->second->sceneData;
}
// a cache item does not exist; search the Filename->Cachename map
return checkCache( full3Dpath );
return checkCache( full3Dpath, aCachePtr );
}
SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName )
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile )
{
return load( aModelFile );
}
SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr )
{
if( aCachePtr )
*aCachePtr = NULL;
unsigned char md5sum[16];
if( !getMD5( aFileName, md5sum ) || m_CacheDir.empty() )
@ -245,6 +267,10 @@ SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName )
else
{
std::cerr << " * [3D Model] [0] added cached name '" << aFileName.ToUTF8() << "'\n";
if( aCachePtr )
*aCachePtr = ep;
}
return NULL;
@ -268,6 +294,9 @@ SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName )
std::cerr << " * [3D Model] [1] added cached name '" << aFileName.ToUTF8() << "'\n";
}
if( aCachePtr )
*aCachePtr = ep;
ep->SetMD5( md5sum );
wxString bname = ep->GetCacheBaseName();
@ -596,41 +625,27 @@ void S3D_CACHE::ClosePlugins( void )
return;
}
// notes:
// 1. aModelEntry:
// + rotation: degrees, model space X, Y, Z; rotations are specified in sequence
//
S3DMODEL* S3D_CACHE::Prepare( S3D_INFO const* aModelEntry,
const SGPOINT& aRotation, const SGPOINT& aOffset )
S3DMODEL* S3D_CACHE::Prepare( const wxString& aModelFileName )
{
SCENEGRAPH* sp = Load( aModelEntry->filename );
S3D_CACHE_ENTRY* cp = NULL;
SCENEGRAPH* sp = load( aModelFileName, &cp );
if( !sp )
return NULL;
// create a single transform entity to apply to the models
glm::dmat4 t0 = glm::translate( glm::dvec3( 25.4 * aModelEntry->offset.x,
25.4 * aModelEntry->offset.y, 25.4 * aModelEntry->offset.z ) );
if( !cp )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] model loaded with no associated S3D_CACHE_ENTRY\n";
return NULL;
}
glm::dmat4 rX = glm::rotate( glm::radians( aModelEntry->rotation.x ),
glm::dvec3( 1.0, 0.0, 0.0 ) );
glm::dmat4 rY = glm::rotate( glm::radians( -aModelEntry->rotation.y ),
glm::dvec3( 0.0, 1.0, 0.0 ) );
glm::dmat4 rZ = glm::rotate( glm::radians( aModelEntry->rotation.z ),
glm::dvec3( 0.0, 0.0, 1.0 ) );
if( cp->renderData )
return cp->renderData;
glm::dmat4 s0 = glm::scale( glm::dvec3( aModelEntry->scale.x, aModelEntry->scale.y,
aModelEntry->scale.z ) );
S3DMODEL* mp = S3D::Prepare( sp );
cp->renderData = mp;
glm::dmat4 m0 = rZ * rY * rX * s0 * t0;
rX = glm::rotate( glm::radians( aRotation.x ), glm::dvec3( 1.0, 0.0, 0.0 ) );
rY = glm::rotate( glm::radians( aRotation.y ), glm::dvec3( 0.0, 1.0, 0.0 ) );
rZ = glm::rotate( glm::radians( aRotation.z ), glm::dvec3( 0.0, 0.0, 1.0 ) );
glm::dmat4 t1 = glm::translate( glm::dvec3( aOffset.x, aOffset.y, aOffset.z ) );
glm::dmat4 m1 = t1 * rZ * rY * rX * m0;
return S3D::Prepare( sp, &m1 );
return mp;
}

View File

@ -82,18 +82,10 @@ private:
* @param aFileName [in] is a partial or full file path; a partial path is accepted
* so that a cached model may be used in cases where the user has moved or deleted
* the original model file.
* @param aModelEntry [in, out] is the model entry for which we are retrieving
* scene data.
* @param aMD5Sum [in] is an optional MD5 sum; if this parameter is supplied and its value
* differs from the cached file then the function will fail and the flag aMD5Mismatch
* will be set to true. If the parameter is not supplied then the cache model is used
* if available and with no regard to the MD5 sum.
* @param aMD5Mismatch [out] if the function succeeds then this flag is set to false;
* the flag is set true if aMD5Sum is specified and differs from the cached object's
* md5sum.
* @param [out] if not NULL will hold a pointer to the cache entry for the model
* @return on success a pointer to a SCENEGRAPH, otherwise NULL
*/
SCENEGRAPH* checkCache( const wxString& aFileName );
SCENEGRAPH* checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr = NULL );
/**
* Function getMD5
@ -111,6 +103,9 @@ private:
// save scene data to a cache file
bool saveCacheData( S3D_CACHE_ENTRY* aCacheItem );
// the real load function (can supply a cache entry pointer to member functions)
SCENEGRAPH* load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr = NULL );
public:
S3D_CACHE();
virtual ~S3D_CACHE();
@ -192,23 +187,10 @@ public:
* attempts to load the scene data for a model and to translate it
* into an S3D_MODEL structure for display by a renderer
*
* @param aModelEntry is the structure containing the model name,
* scale, offset, and rotation. Note that by kicad convention the
* operations are Offset-Scale-Rotation, the Y value of the offset
* is negative (Left-hand coordinate system), and the units of the
* offset is inches. Application of the Offset, Scale. Rotation
* within the aModelEntry structure places the model into a nominal
* (0, 0, 0) position and orientation. Final positioning of the
* model instance is determined by the aOffset, aAxis, and aAngle
* parameters.
* @ aRotation is a X, Y, Z rotation to calculate the final orientation
* of the model instance
* @param aOffset is an offset to apply to obtain the final position
* of the model instance; this offset is applied after the aAxis/aAngle
* orientation in the common Rotation-Scale-Translation order of transforms.
* @param aModelFileName is the full path to the model to be loaded
* @return is a pointer to the render data or NULL if not available
*/
S3DMODEL* Prepare( S3D_INFO const* aModelEntry,
const SGPOINT& aRotation, const SGPOINT& aOffset );
S3DMODEL* Prepare( const wxString& aModelFileName );
};
#endif // CACHE_3D_H

View File

@ -325,8 +325,7 @@ PANEL_PREV_3D::~PANEL_PREV_3D()
canvas->Update();
}
if( model )
S3D::Destroy3DModel( &model );
model = NULL;
return;
}
@ -576,16 +575,13 @@ void PANEL_PREV_3D::UpdateModelName( wxString const& aModelName )
canvas->Update();
}
if( model )
S3D::Destroy3DModel( &model );
model = NULL;
if( currentModelFile.empty() )
return;
}
SGPOINT rot;
SGPOINT trans;
model = m_ModelManager->Prepare( &modelInfo, rot, trans );
model = m_ModelManager->Prepare( modelInfo.filename );
if( NULL == model )
{
@ -683,13 +679,7 @@ void PANEL_PREV_3D::updateOrientation( wxCommandEvent &event )
canvas->Clear3DModel();
if( model )
S3D::Destroy3DModel( &model );
SGPOINT rot;
SGPOINT trans;
model = m_ModelManager->Prepare( &modelInfo, rot, trans );
model = m_ModelManager->Prepare( modelInfo.filename );
if( model )
{

View File

@ -304,8 +304,14 @@ SGNODE* S3D::ReadCache( const wxString& aFileName )
}
S3DMODEL* S3D::Prepare( SCENEGRAPH* aNode, const glm::dmat4* aTransform )
S3DMODEL* S3D::Prepare( SCENEGRAPH* aNode )
{
if( NULL == aNode )
return NULL;
if( aNode->GetNodeType() != S3D::SGTYPE_TRANSFORM )
return NULL;
S3D::MATLIST materials;
std::vector< SMESH > meshes;
@ -324,7 +330,7 @@ S3DMODEL* S3D::Prepare( SCENEGRAPH* aNode, const glm::dmat4* aTransform )
materials.matorder.push_back( &app );
materials.matmap.insert( std::pair< SGAPPEARANCE const*, int >( &app, 0 ) );
if( aNode->Prepare( aTransform, materials, meshes ) )
if( aNode->Prepare( NULL, materials, meshes ) )
{
if( meshes.empty() )
return NULL;

View File

@ -582,7 +582,12 @@ bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform,
rotation_axis.GetVector( rX, rY, rZ );
glm::dmat4 rM = glm::rotate( glm::degrees( rotation_angle ), glm::dvec3( rX, rY, rZ ) );
glm::dmat4 tM = glm::translate( glm::dvec3( translation.x, translation.y, translation.z ) );
glm::dmat4 tx0 = (*aTransform) * tM * rM;
glm::dmat4 tx0;
if( NULL != aTransform )
tx0 = (*aTransform) * tM * rM;
else
tx0 = tM * rM;
bool ok = true;

View File

@ -276,8 +276,8 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
glScaled( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor, modelunit_to_3d_units_factor);
//const SFVEC3F model_center = m_ogl_3dmodel->GetBBox().GetCenter();
//glTranslatef( -model_center.x, -model_center.y, -model_center.z );
const SFVEC3F model_center = m_ogl_3dmodel->GetBBox().GetCenter();
glTranslatef( -model_center.x, -model_center.y, -model_center.z );
m_ogl_3dmodel->Draw_opaque();
//m_ogl_3dmodel->Draw_transparent();

View File

@ -30,7 +30,6 @@
#define IFSG_API_H
#include <wx/string.h>
#include <glm/glm.hpp>
#include "plugins/3dapi/sg_types.h"
#include "plugins/3dapi/sg_base.h"
@ -132,15 +131,12 @@ namespace S3D
/**
* Function Prepare
* creates an S3DMODEL representation of aNode transformed by aTransform.
* creates an S3DMODEL representation of aNode (raw data, no transforms)
*
* @param aNode is the node to be transcribed into an S3DMODEL representation
* @param aTransform is the transform (Translation * Rotation * Scale) to apply
* to the representation of aNode; it must be a pointer to a glm::dmat4 entity
*
* @return an S3DMODEL representation of aNode on success, otherwise NULL
*/
SGLIB_API S3DMODEL* Prepare( SCENEGRAPH* aNode, const glm::dmat4* aTransform );
SGLIB_API S3DMODEL* Prepare( SCENEGRAPH* aNode );
/**
* Function Destroy3DModel

View File

@ -1,2 +1,3 @@
add_subdirectory( demo )
#add_subdirectory( demo )
add_subdirectory( idf )
add_subdirectory( vrml )

View File

@ -0,0 +1,17 @@
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
)
add_library( s3d_plugin_vrml MODULE
vrml.cpp
vrml1.cpp
vrml2.cpp
)
target_link_libraries( s3d_plugin_vrml kicad_3dsg ${OPENGL_LIBRARIES} ${wxWidgets_LIBRARIES} )
install( TARGETS
s3d_plugin_vrml
DESTINATION ${KICAD_USER_PLUGIN}/3d
COMPONENT binary
)

201
plugins/3d/vrml/vrml.cpp Normal file
View File

@ -0,0 +1,201 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
* Description:
* This plugin implements the legacy kicad VRML1/VRML2 parsers.
* This VRML plugin will invoke a VRML1 or VRML2 parser depending
* on the identifying information in the file header:
*
* #VRML V1.0 ascii
* #VRML V2.0 utf8
*/
#include <fstream>
#include <iostream>
#include <cmath>
#include <string>
#include <wx/string.h>
#include <wx/filename.h>
#include "plugins/3d/3d_plugin.h"
#include "plugins/3dapi/ifsg_all.h"
#include "vrml1.h"
#include "vrml2.h"
#define PLUGIN_VRML_MAJOR 1
#define PLUGIN_VRML_MINOR 0
#define PLUGIN_VRML_PATCH 0
#define PLUGIN_VRML_REVNO 0
const char* GetKicadPluginName( void )
{
return "PLUGIN_3D_VRML";
}
void GetPluginVersion( unsigned char* Major,
unsigned char* Minor, unsigned char* Patch, unsigned char* Revision )
{
if( Major )
*Major = PLUGIN_VRML_MAJOR;
if( Minor )
*Minor = PLUGIN_VRML_MINOR;
if( Patch )
*Patch = PLUGIN_VRML_PATCH;
if( Revision )
*Revision = PLUGIN_VRML_REVNO;
return;
}
// number of extensions supported
#ifdef _WIN32
#define NEXTS 1
#else
#define NEXTS 2
#endif
// number of filter sets supported
#define NFILS 1
static char ext0[] = "wrl";
#ifdef _WIN32
static char fil0[] = "VRML 1.0/2.0 (*.wrl)|*.wrl";
#else
static char ext1[] = "WRL";
static char fil0[] = "VRML 1.0/2.0 (*.wrl;*.WRL)|*.wrl;*.WRL";
#endif
static struct FILE_DATA
{
char const* extensions[NEXTS];
char const* filters[NFILS];
FILE_DATA()
{
extensions[0] = ext0;
filters[0] = fil0;
#ifndef _WIN32
extensions[1] = ext1;
#endif
return;
}
} file_data;
int GetNExtensions( void )
{
return NEXTS;
}
char const* GetModelExtension( int aIndex )
{
if( aIndex < 0 || aIndex >= NEXTS )
return NULL;
return file_data.extensions[aIndex];
}
int GetNFilters( void )
{
return NFILS;
}
char const* GetFileFilter( int aIndex )
{
if( aIndex < 0 || aIndex >= NFILS )
return NULL;
return file_data.filters[aIndex];
}
bool CanRender( void )
{
// this plugin supports rendering of IDF component outlines
return true;
}
class LOCALESWITCH
{
public:
LOCALESWITCH()
{
setlocale( LC_NUMERIC, "C" );
}
~LOCALESWITCH()
{
setlocale( LC_NUMERIC, "" );
}
};
SCENEGRAPH* Load( char const* aFileName )
{
if( NULL == aFileName )
return NULL;
wxString fname = wxString::FromUTF8Unchecked( aFileName );
if( !wxFileName::FileExists( fname ) )
return NULL;
LOCALESWITCH switcher;
std::ifstream ifile;
ifile.open( fname.ToUTF8() );
if( !ifile.is_open() )
return NULL;
std::string iline;
std::getline( ifile, iline );
if( iline.find( "#VRML V1.0 ascii" ) == 0 )
{
PARSER_3D_VRML1 parser;
return parser.Load( ifile );
}
if( iline.find( "#VRML V2.0 utf8" ) == 0 )
{
PARSER_3D_VRML2 parser;
return parser.Load( ifile );
}
return NULL;
}

50
plugins/3d/vrml/vrml1.cpp Normal file
View File

@ -0,0 +1,50 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
* Description:
* This module implements a VRML1 parser
*/
#include "vrml1.h"
PARSER_3D_VRML1::PARSER_3D_VRML1()
{
// XXX - TO BE IMPLEMENTED
return;
}
PARSER_3D_VRML1::~PARSER_3D_VRML1()
{
// XXX - TO BE IMPLEMENTED
return;
}
SCENEGRAPH* PARSER_3D_VRML1::Load( std::ifstream& aModelFile )
{
// XXX - TO BE IMPLEMENTED
return NULL;
}

41
plugins/3d/vrml/vrml1.h Normal file
View File

@ -0,0 +1,41 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vrml1.h
*/
#include <fstream>
class SCENEGRAPH;
class PARSER_3D_VRML1
{
public:
PARSER_3D_VRML1();
~PARSER_3D_VRML1();
SCENEGRAPH* Load( std::ifstream& aModelFile );
};

51
plugins/3d/vrml/vrml2.cpp Normal file
View File

@ -0,0 +1,51 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
* Description:
* This module implements a VRML2 parser which supports only
* the features required for rendering static models.
*/
#include "vrml2.h"
PARSER_3D_VRML2::PARSER_3D_VRML2()
{
// XXX - TO BE IMPLEMENTED
return;
}
PARSER_3D_VRML2::~PARSER_3D_VRML2()
{
// XXX - TO BE IMPLEMENTED
return;
}
SCENEGRAPH* PARSER_3D_VRML2::Load( std::ifstream& aModelFile )
{
// XXX - TO BE IMPLEMENTED
return NULL;
}

41
plugins/3d/vrml/vrml2.h Normal file
View File

@ -0,0 +1,41 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vrml2.h
*/
#include <fstream>
class SCENEGRAPH;
class PARSER_3D_VRML2
{
public:
PARSER_3D_VRML2();
~PARSER_3D_VRML2();
SCENEGRAPH* Load( std::ifstream& aModelFile );
};