2013-03-27 18:34:23 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2013 Tuomas Vaherkoski <tuomasvaherkoski@gmail.com>
|
|
|
|
* Copyright (C) 1992-2013 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 x3dmodelparser.cpp
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <fctsys.h>
|
|
|
|
#include <macros.h>
|
|
|
|
#include <info3d_visu.h>
|
|
|
|
#include <wx/xml/xml.h>
|
|
|
|
#include <wx/tokenzr.h>
|
|
|
|
#include <wx/string.h>
|
|
|
|
#include <map>
|
|
|
|
#include <queue>
|
|
|
|
#include <vector>
|
|
|
|
|
2014-01-08 01:34:04 +00:00
|
|
|
#include <3d_struct.h>
|
|
|
|
#include <modelparsers.h>
|
|
|
|
#include <xnode.h>
|
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
X3D_MODEL_PARSER::X3D_MODEL_PARSER( S3D_MASTER* aMaster ) :
|
|
|
|
S3D_MODEL_PARSER( aMaster )
|
2013-03-27 18:34:23 +00:00
|
|
|
{}
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
X3D_MODEL_PARSER::~X3D_MODEL_PARSER()
|
|
|
|
{}
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
void X3D_MODEL_PARSER::Load( const wxString aFilename )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
2013-03-28 16:51:22 +00:00
|
|
|
wxXmlDocument doc;
|
|
|
|
|
|
|
|
if( !doc.Load( aFilename ) )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
2014-01-08 01:34:04 +00:00
|
|
|
wxLogError( wxT( "Error while parsing file '%s'" ), GetChars( aFilename ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( doc.GetRoot()->GetName() != wxT( "X3D" ) )
|
|
|
|
{
|
2014-01-08 01:34:04 +00:00
|
|
|
wxLogError( wxT( "Filetype is not X3D '%s'" ), GetChars( aFilename ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Shapes are inside of Transform nodes
|
2013-03-28 16:51:22 +00:00
|
|
|
// Transform node contains information about
|
2013-03-27 18:34:23 +00:00
|
|
|
// transition, scale and rotation of the shape
|
|
|
|
NODE_LIST transforms;
|
|
|
|
GetChildsByName( doc.GetRoot(), wxT( "Transform" ), transforms );
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
for( NODE_LIST::iterator node_it = transforms.begin();
|
|
|
|
node_it != transforms.end();
|
2013-03-28 16:51:22 +00:00
|
|
|
node_it++ )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
readTransform( *node_it );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
wxString X3D_MODEL_PARSER::VRML_representation()
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
wxString output;
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
for( unsigned i = 0; i < vrml_points.size(); i++ )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
2014-01-08 01:34:04 +00:00
|
|
|
output +=
|
|
|
|
wxT( "Shape {\n"
|
|
|
|
" appearance Appearance {\n"
|
|
|
|
" material Material {\n" ) +
|
|
|
|
vrml_materials[i] +
|
|
|
|
wxT( " }\n"
|
|
|
|
" }\n"
|
|
|
|
" geometry IndexedFaceSet {\n"
|
|
|
|
" solid TRUE\n"
|
|
|
|
" coord Coordinate {\n"
|
|
|
|
" point [\n") +
|
|
|
|
vrml_points[i] +
|
|
|
|
wxT( " ]\n"
|
|
|
|
" }\n"
|
|
|
|
" coordIndex [\n" ) +
|
|
|
|
vrml_coord_indexes[i] +
|
|
|
|
wxT( " ]\n"
|
|
|
|
" }\n"
|
|
|
|
"},\n" );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
void X3D_MODEL_PARSER::GetChildsByName( wxXmlNode* aParent,
|
|
|
|
const wxString aName,
|
|
|
|
std::vector< wxXmlNode* >& aResult )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
// Breadth-first search (BFS)
|
|
|
|
std::queue< wxXmlNode* > found;
|
2014-01-08 01:34:04 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
found.push( aParent );
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
while( !found.empty() )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
wxXmlNode *elem = found.front();
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
for( wxXmlNode *child = elem->GetChildren();
|
2013-03-28 16:51:22 +00:00
|
|
|
child != NULL;
|
2013-03-27 18:34:23 +00:00
|
|
|
child = child->GetNext() )
|
|
|
|
{
|
2013-03-28 16:51:22 +00:00
|
|
|
if( child->GetName() == aName )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
aResult.push_back( child );
|
|
|
|
}
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
found.push( child );
|
|
|
|
}
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
found.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
void X3D_MODEL_PARSER::GetNodeProperties( wxXmlNode* aNode, PROPERTY_MAP& aProps )
|
|
|
|
{
|
2014-01-08 01:34:04 +00:00
|
|
|
wxXmlAttribute* prop;
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
for( prop = aNode->GetAttributes();
|
|
|
|
prop != NULL;
|
2013-03-27 18:34:23 +00:00
|
|
|
prop = prop->GetNext() )
|
|
|
|
{
|
|
|
|
aProps[ prop->GetName() ] = prop->GetValue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Private ----- */
|
|
|
|
|
|
|
|
void X3D_MODEL_PARSER::readTransform( wxXmlNode* aTransformNode )
|
|
|
|
{
|
|
|
|
NODE_LIST childnodes;
|
|
|
|
GetChildsByName( aTransformNode, wxT( "Material" ), childnodes );
|
|
|
|
|
|
|
|
for( NODE_LIST::iterator node = childnodes.begin();
|
|
|
|
node != childnodes.end();
|
2013-03-28 16:51:22 +00:00
|
|
|
node++ )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
readMaterial( *node );
|
|
|
|
}
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
childnodes.clear();
|
|
|
|
|
|
|
|
PROPERTY_MAP properties;
|
2014-01-08 01:34:04 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
GetNodeProperties( aTransformNode, properties );
|
|
|
|
GetChildsByName( aTransformNode, wxT("IndexedFaceSet"), childnodes );
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
for( NODE_LIST::iterator node = childnodes.begin();
|
|
|
|
node != childnodes.end();
|
2013-03-28 16:51:22 +00:00
|
|
|
node++ )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
readIndexedFaceSet( *node, properties );
|
|
|
|
}
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
childnodes.clear();
|
|
|
|
}
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
void X3D_MODEL_PARSER::readMaterial( wxXmlNode* aMatNode )
|
|
|
|
{
|
|
|
|
PROPERTY_MAP properties;
|
|
|
|
GetNodeProperties( aMatNode, properties );
|
|
|
|
|
|
|
|
// DEFine new Material named as value of DEF
|
2013-03-28 16:51:22 +00:00
|
|
|
if( properties.find( wxT( "DEF" ) ) != properties.end() )
|
|
|
|
{
|
2013-03-27 18:34:23 +00:00
|
|
|
double amb, shine, transp;
|
|
|
|
|
|
|
|
S3D_MATERIAL* material = new S3D_MATERIAL( GetMaster(), properties[ wxT( "DEF" ) ] );
|
|
|
|
GetMaster()->Insert( material );
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
if( !parseDoubleTriplet( properties[ wxT( "diffuseColor" ) ],
|
|
|
|
material->m_DiffuseColor ) )
|
|
|
|
{
|
2013-09-10 08:47:42 +00:00
|
|
|
DBG( printf("diffuseColor parsing error") );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
if( !parseDoubleTriplet( properties[ wxT( "specularColor" ) ],
|
|
|
|
material->m_SpecularColor ) )
|
|
|
|
{
|
2013-09-10 08:47:42 +00:00
|
|
|
DBG( printf("specularColor parsing error") );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if( !parseDoubleTriplet( properties[ wxT( "emissiveColor" ) ],
|
|
|
|
material->m_EmissiveColor ) )
|
2013-03-28 16:51:22 +00:00
|
|
|
{
|
2013-09-10 08:47:42 +00:00
|
|
|
DBG( printf("emissiveColor parsing error") );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
wxStringTokenizer values;
|
|
|
|
values.SetString( properties[ wxT( "ambientIntensity" ) ] );
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
if( values.GetNextToken().ToDouble( &amb ) )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
material->m_AmbientIntensity = amb;
|
2013-03-28 16:51:22 +00:00
|
|
|
}
|
|
|
|
else
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
2013-09-10 08:47:42 +00:00
|
|
|
DBG( printf( "ambienterror" ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
values.SetString( properties[ wxT( "shininess" ) ] );
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
if( values.GetNextToken().ToDouble( &shine ) )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
material->m_Shininess = shine;
|
2013-03-28 16:51:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-09-10 08:47:42 +00:00
|
|
|
DBG( printf( "shininess error" ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
values.SetString( properties[ wxT( "transparency" ) ] );
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
if( values.GetNextToken().ToDouble( &transp ) )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
material->m_Transparency = transp;
|
2013-03-28 16:51:22 +00:00
|
|
|
}
|
2013-03-27 18:34:23 +00:00
|
|
|
else
|
2013-03-28 16:51:22 +00:00
|
|
|
{
|
2013-09-10 08:47:42 +00:00
|
|
|
DBG( printf( "trans error") );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
material->SetMaterial();
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
// VRML
|
|
|
|
wxString vrml_material;
|
|
|
|
PROPERTY_MAP::const_iterator p = ++properties.begin(); // skip DEF
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2014-01-08 01:34:04 +00:00
|
|
|
for( ; p != properties.end(); p++ )
|
2013-03-28 16:51:22 +00:00
|
|
|
{
|
|
|
|
vrml_material.Append( p->first + wxT( " " ) + p->second + wxT( "\n" ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
vrml_materials.push_back( vrml_material );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
// USE existing material named by value of USE
|
2013-03-28 16:51:22 +00:00
|
|
|
else if( properties.find( wxT( "USE" ) ) != properties.end() )
|
|
|
|
{
|
2013-03-27 18:34:23 +00:00
|
|
|
S3D_MATERIAL* material = NULL;
|
|
|
|
wxString mat_name = properties[ wxT( "USE" ) ];
|
|
|
|
|
|
|
|
for( material = GetMaster()->m_Materials; material; material = material->Next() )
|
|
|
|
{
|
|
|
|
if( material->m_Name == mat_name )
|
|
|
|
{
|
|
|
|
wxString vrml_material;
|
2014-01-08 01:34:04 +00:00
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
vrml_material.Append( wxString::Format( wxT( "specularColor %f %f %f\n" ),
|
|
|
|
material->m_SpecularColor.x,
|
|
|
|
material->m_SpecularColor.y,
|
|
|
|
material->m_SpecularColor.z ) );
|
|
|
|
|
|
|
|
vrml_material.Append( wxString::Format( wxT( "diffuseColor %f %f %f\n" ),
|
|
|
|
material->m_DiffuseColor.x,
|
|
|
|
material->m_DiffuseColor.y,
|
|
|
|
material->m_DiffuseColor.z ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
vrml_material.Append( wxString::Format( wxT( "emissiveColor %f %f %f\n" ),
|
|
|
|
material->m_EmissiveColor.x,
|
|
|
|
material->m_EmissiveColor.y,
|
|
|
|
material->m_EmissiveColor.z ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
vrml_material.Append( wxString::Format( wxT( "ambientIntensity %f\n"),
|
|
|
|
material->m_AmbientIntensity ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
vrml_material.Append( wxString::Format( wxT( "shininess %f\n"),
|
|
|
|
material->m_Shininess ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
vrml_material.Append( wxString::Format( wxT( "transparency %f\n"),
|
|
|
|
material->m_Transparency ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
vrml_materials.push_back( vrml_material );
|
2013-03-27 18:34:23 +00:00
|
|
|
|
|
|
|
material->SetMaterial();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-10 08:47:42 +00:00
|
|
|
DBG( printf( "ReadMaterial error: material not found\n" ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
bool X3D_MODEL_PARSER::parseDoubleTriplet( const wxString& aData,
|
2013-03-27 18:34:23 +00:00
|
|
|
S3D_VERTEX& aResult )
|
|
|
|
{
|
|
|
|
wxStringTokenizer tokens(aData);
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
return tokens.GetNextToken().ToDouble( &aResult.x ) &&
|
|
|
|
tokens.GetNextToken().ToDouble( &aResult.y ) &&
|
2013-03-28 16:51:22 +00:00
|
|
|
tokens.GetNextToken().ToDouble( &aResult.z );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
void X3D_MODEL_PARSER::rotate( S3D_VERTEX& aV,
|
|
|
|
S3D_VERTEX& aU,
|
|
|
|
double angle )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
S3D_VERTEX rotated;
|
2013-03-28 16:51:22 +00:00
|
|
|
double C = cos( angle );
|
|
|
|
double S = sin( angle );
|
2013-03-27 18:34:23 +00:00
|
|
|
double t = 1.0 - C;
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
rotated.x = ( t * aU.x * aU.x + C ) * aV.x +
|
|
|
|
( t * aU.x * aU.y - S * aU.z ) * aV.y +
|
2013-03-27 18:34:23 +00:00
|
|
|
( t * aU.x * aU.z + S * aU.y ) * aV.z;
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
rotated.y = ( t * aU.x * aU.y + S * aU.z ) * aV.x +
|
|
|
|
( t * aU.y * aU.y + C ) * aV.y +
|
2013-03-27 18:34:23 +00:00
|
|
|
( t * aU.y * aU.z - S * aU.x ) * aV.z;
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
rotated.z = ( t * aU.x * aU.z - S * aU.y ) * aV.x +
|
|
|
|
( t * aU.y * aU.z + S * aU.x ) * aV.y +
|
2013-03-27 18:34:23 +00:00
|
|
|
( t * aU.z * aU.z + C) * aV.z;
|
|
|
|
|
|
|
|
aV.x = rotated.x;
|
|
|
|
aV.y = rotated.y;
|
|
|
|
aV.z = rotated.z;
|
|
|
|
}
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
/* Steps:
|
|
|
|
* 1. Read transform data
|
2013-03-28 16:51:22 +00:00
|
|
|
* 2. Read vertex triplets
|
2013-03-27 18:34:23 +00:00
|
|
|
* 3. Read coordinate indexes
|
|
|
|
* 4. Apply geometry to Master object
|
|
|
|
*/
|
2013-03-28 16:51:22 +00:00
|
|
|
void X3D_MODEL_PARSER::readIndexedFaceSet( wxXmlNode* aFaceNode,
|
2013-03-27 18:34:23 +00:00
|
|
|
PROPERTY_MAP& aTransformProps)
|
|
|
|
{
|
|
|
|
/* Step 1: Read transform data
|
|
|
|
* --------------------------- */
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
S3D_VERTEX translation;
|
2013-03-28 16:51:22 +00:00
|
|
|
parseDoubleTriplet( aTransformProps[ wxT( "translation" ) ], translation );
|
2013-03-27 18:34:23 +00:00
|
|
|
|
|
|
|
S3D_VERTEX scale;
|
|
|
|
parseDoubleTriplet( aTransformProps[ wxT( "scale" ) ], scale );
|
|
|
|
|
|
|
|
S3D_VERTEX rotation;
|
|
|
|
double angle = 0.0;
|
|
|
|
wxStringTokenizer tokens(aTransformProps[ wxT( "rotation" ) ]);
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
if( !(tokens.GetNextToken().ToDouble( &rotation.x ) &&
|
|
|
|
tokens.GetNextToken().ToDouble( &rotation.y ) &&
|
|
|
|
tokens.GetNextToken().ToDouble( &rotation.z ) &&
|
|
|
|
tokens.GetNextToken().ToDouble( &angle ) ) )
|
|
|
|
{
|
2013-09-10 08:47:42 +00:00
|
|
|
DBG( printf("rotation read error") );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
double vrmlunits_to_3Dunits = g_Parm_3D_Visu.m_BiuTo3Dunits *
|
2013-03-27 18:34:23 +00:00
|
|
|
UNITS3D_TO_UNITSPCB;
|
|
|
|
|
|
|
|
/* Step 2: Read all coordinate points
|
|
|
|
* ---------------------------- */
|
|
|
|
std::vector< double > points;
|
|
|
|
NODE_LIST coordinates;
|
|
|
|
GetChildsByName( aFaceNode, wxT( "Coordinate" ), coordinates);
|
|
|
|
|
|
|
|
PROPERTY_MAP coordinate_properties;
|
|
|
|
// IndexedFaceSet has one Coordinate child node
|
|
|
|
GetNodeProperties( coordinates[0], coordinate_properties );
|
|
|
|
|
|
|
|
// Save points to vector as doubles
|
|
|
|
wxStringTokenizer point_tokens( coordinate_properties[ wxT("point") ] );
|
|
|
|
double point = 0.0;
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
while( point_tokens.HasMoreTokens() )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
if( point_tokens.GetNextToken().ToDouble( &point ) )
|
|
|
|
{
|
|
|
|
points.push_back( point );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wxLogError( wxT( "Error converting to double" ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
if( points.size() % 3 != 0 )
|
|
|
|
{
|
2013-09-10 08:47:42 +00:00
|
|
|
DBG( printf( "Number of points is incorrect" ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create 3D vertex from 3 points and
|
2013-03-28 16:51:22 +00:00
|
|
|
* apply transforms in order of SCALE, ROTATION, TRANSLATION
|
2013-03-27 18:34:23 +00:00
|
|
|
*/
|
|
|
|
wxString vrml_pointlist;
|
|
|
|
std::vector< S3D_VERTEX > triplets;
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
for( unsigned id = 0; id < points.size() / 3; id++ )
|
|
|
|
{
|
|
|
|
int triplet_indx = id * 3;
|
2013-03-28 16:51:22 +00:00
|
|
|
S3D_VERTEX point( points[ triplet_indx ],
|
|
|
|
points[ triplet_indx + 1 ],
|
2013-03-27 18:34:23 +00:00
|
|
|
points[ triplet_indx + 2 ] );
|
|
|
|
|
|
|
|
point.x *= scale.x;
|
|
|
|
point.y *= scale.y;
|
|
|
|
point.z *= scale.z;
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
rotate( point, rotation, angle );
|
2013-03-27 18:34:23 +00:00
|
|
|
|
|
|
|
point.x += translation.x;
|
|
|
|
point.y += translation.y;
|
|
|
|
point.z += translation.z;
|
|
|
|
|
|
|
|
triplets.push_back(point);
|
|
|
|
|
|
|
|
// VRML
|
2013-03-28 16:51:22 +00:00
|
|
|
vrml_pointlist.Append( wxString::Format( wxT( "%f %f %f\n" ), point.x, point.y, point.z ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
vrml_points.push_back( vrml_pointlist );
|
2013-03-27 18:34:23 +00:00
|
|
|
|
|
|
|
/* -- Read coordinate indexes -- */
|
|
|
|
PROPERTY_MAP faceset_properties;
|
|
|
|
GetNodeProperties( aFaceNode, faceset_properties );
|
|
|
|
|
|
|
|
std::vector< S3D_VERTEX > vertices;
|
|
|
|
std::vector< int > coordIndex;
|
|
|
|
|
|
|
|
wxString coordIndex_str = faceset_properties[ wxT( "coordIndex" ) ];
|
|
|
|
wxStringTokenizer index_tokens( coordIndex_str );
|
|
|
|
|
|
|
|
wxString vrml_coord_indx_list;
|
2013-03-28 16:51:22 +00:00
|
|
|
|
|
|
|
while( index_tokens.HasMoreTokens() )
|
2013-03-27 18:34:23 +00:00
|
|
|
{
|
|
|
|
long index = 0;
|
2014-01-08 01:34:04 +00:00
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
index_tokens.GetNextToken().ToLong( &index );
|
2013-03-27 18:34:23 +00:00
|
|
|
|
|
|
|
// -1 marks the end of polygon
|
|
|
|
if( index < 0 )
|
|
|
|
{
|
|
|
|
/* Step 4: Apply geometry to Master object
|
|
|
|
* --------------------------------------- */
|
|
|
|
std::vector<int>::const_iterator id;
|
2013-03-28 16:51:22 +00:00
|
|
|
|
2013-03-27 18:34:23 +00:00
|
|
|
for( id = coordIndex.begin();
|
|
|
|
id != coordIndex.end();
|
|
|
|
id++ )
|
|
|
|
{
|
2013-03-28 16:51:22 +00:00
|
|
|
vertices.push_back( triplets.at( *id ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GetMaster()->Set_Object_Coords( vertices );
|
|
|
|
Set_Object_Data( vertices, vrmlunits_to_3Dunits );
|
|
|
|
|
|
|
|
vertices.clear();
|
|
|
|
coordIndex.clear();
|
2013-03-28 16:51:22 +00:00
|
|
|
vrml_coord_indx_list.Append( wxT( "-1\n" ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
coordIndex.push_back( index );
|
2013-03-28 16:51:22 +00:00
|
|
|
vrml_coord_indx_list.Append( wxString::Format( wxT( "%u " ), index ) );
|
2013-03-27 18:34:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-28 16:51:22 +00:00
|
|
|
vrml_coord_indexes.push_back( vrml_coord_indx_list );
|
|
|
|
}
|