Work in progress: implementing SG translation for VRML1 models

This commit is contained in:
Cirilo Bernardo 2016-01-06 15:34:14 +11:00
parent 38543ab94f
commit 6b873ed46b
22 changed files with 632 additions and 293 deletions

View File

@ -616,8 +616,12 @@ void PANEL_PREV_3D::UpdateModelName( wxString const& aModelName )
#endif
wxSizer* ws = new wxBoxSizer( wxHORIZONTAL );
ws->Add( canvas, 10, wxEXPAND );
preview->SetSizerAndFit( ws );
canvas->Set3DModel( *model );
ws->Add( canvas, 1, wxEXPAND );
preview->SetSizer( ws );
preview->Layout();
ws->FitInside( preview );
return;
}
canvas->Set3DModel( *model );

View File

@ -15,13 +15,11 @@ add_library( kicad_3dsg SHARED
sg_coords.cpp
sg_normals.cpp
sg_index.cpp
sg_colorindex.cpp
sg_coordindex.cpp
ifsg_node.cpp
ifsg_transform.cpp
ifsg_appearance.cpp
ifsg_index.cpp
ifsg_colorindex.cpp
ifsg_coordindex.cpp
ifsg_colors.cpp
ifsg_coords.cpp

View File

@ -173,7 +173,7 @@ bool IFSG_COLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
}
bool IFSG_COLORS::SetColorList( size_t& aListSize, const SGCOLOR* aColorList )
bool IFSG_COLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
{
if( NULL == m_node )
{

View File

@ -35,7 +35,6 @@ SGFACESET::SGFACESET( SGNODE* aParent ) : SGNODE( aParent )
{
m_SGtype = S3D::SGTYPE_FACESET;
m_Colors = NULL;
m_ColorIndices = NULL;
m_Coords = NULL;
m_CoordIndices = NULL;
m_Normals = NULL;
@ -107,13 +106,6 @@ SGFACESET::~SGFACESET()
m_Normals = NULL;
}
if( m_ColorIndices )
{
m_ColorIndices->SetParent( NULL, false );
delete m_ColorIndices;
m_ColorIndices = NULL;
}
if( m_CoordIndices )
{
m_CoordIndices->SetParent( NULL, false );
@ -173,14 +165,6 @@ SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller)
return np;
}
if( m_ColorIndices )
{
np = m_ColorIndices->FindNode( aNodeName, this );
if( np )
return np;
}
if( m_Coords )
{
np = m_Coords->FindNode( aNodeName, this );
@ -241,12 +225,6 @@ void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild )
return;
}
if( aNode == m_ColorIndices )
{
m_ColorIndices = NULL;
return;
}
if( aNode == m_CoordIndices )
{
m_CoordIndices = NULL;
@ -377,21 +355,6 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
return true;
}
if( S3D::SGTYPE_COLORINDEX == aNode->GetNodeType() )
{
if( m_ColorIndices )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] assigning multiple ColorIndex nodes\n";
return false;
}
m_ColorIndices = (SGCOLORINDEX*)aNode;
m_ColorIndices->SetParent( this );
return true;
}
if( S3D::SGTYPE_COORDINDEX == aNode->GetNodeType() )
{
if( m_CoordIndices )
@ -440,9 +403,6 @@ void SGFACESET::ReNameNodes( void )
if( m_Colors )
m_Colors->ReNameNodes();
if( m_ColorIndices )
m_ColorIndices->ReNameNodes();
// rename all Coordinates and Indices
if( m_Coords )
m_Coords->ReNameNodes();
@ -510,9 +470,6 @@ bool SGFACESET::WriteVRML( std::ofstream& aFile, bool aReuseFlag )
if( m_RColors )
m_RColors->WriteVRML( aFile, aReuseFlag );
if( m_ColorIndices )
m_ColorIndices->WriteVRML( aFile, aReuseFlag );
aFile << "}\n";
return true;
@ -553,7 +510,7 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
}
aFile << "[" << GetName() << "]";
#define NITEMS 8
#define NITEMS 7
bool items[NITEMS];
int i;
@ -588,10 +545,6 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
if( NULL != m_RColors )
items[i] = true;
++i;
if( NULL != m_ColorIndices )
items[i] = true;
for( int i = 0; i < NITEMS; ++i )
aFile.write( (char*)&items[i], sizeof(bool) );
@ -616,9 +569,6 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
if( items[6] )
aFile << "[" << m_RColors->GetName() << "]";
if( items[7] )
m_ColorIndices->WriteCache( aFile, this );
if( aFile.fail() )
return false;
@ -629,7 +579,7 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
bool SGFACESET::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
{
if( m_Coords || m_RCoords || m_CoordIndices
|| m_Colors || m_RColors || m_ColorIndices
|| m_Colors || m_RColors
|| m_Normals || m_RNormals )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
@ -637,7 +587,7 @@ bool SGFACESET::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
return false;
}
#define NITEMS 8
#define NITEMS 7
bool items[NITEMS];
for( int i = 0; i < NITEMS; ++i )
@ -838,28 +788,6 @@ bool SGFACESET::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
m_RColors->addNodeRef( this );
}
if( items[7] )
{
if( S3D::SGTYPE_COLORINDEX != S3D::ReadTag( aFile, name ) )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] corrupt data; bad color index tag at position ";
std::cerr << aFile.tellg() << "\n";
return false;
}
m_ColorIndices = new SGCOLORINDEX( this );
m_ColorIndices->SetName( name.c_str() );
if( !m_ColorIndices->ReadCache( aFile, this ) )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] corrupt data while reading color index '";
std::cerr << name << "'\n";
return false;
}
}
if( aFile.fail() )
return false;
@ -969,62 +897,10 @@ bool SGFACESET::validate( void )
if( NULL != pColors )
{
if( NULL == m_ColorIndices )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad model; no color indices\n";
#endif
validated = true;
valid = false;
return false;
}
// we must have at least 1 color in the list
// we must have at least as many colors as vertices
size_t nColor = 0;
SGCOLOR* pColor = NULL;
pColors->GetColorList( nColor, pColor );
if( nColor < 1 )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad model; no colors\n";
#endif
validated = true;
valid = false;
return false;
}
size_t nCLIdx = 0;
int* pCLIdx = NULL;
m_ColorIndices->GetIndices( nCLIdx, pCLIdx );
if( nCLIdx != nCoords )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad model; color indices do not match number of vertices\n";
#endif
validated = true;
valid = false;
return false;
}
// check that color[n] >= 0 and < nColors
for( size_t i = 0; i < nCLIdx; ++i )
{
if( pCLIdx[i] < 0 || pCLIdx[i] >= nCLIdx )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad model; color index out of bounds\n";
#endif
validated = true;
valid = false;
return false;
}
}
}
validated = true;

View File

@ -51,7 +51,6 @@ private:
public:
// owned objects
SGCOLORS* m_Colors;
SGCOLORINDEX* m_ColorIndices;
SGCOORDS* m_Coords;
SGCOORDINDEX* m_CoordIndices;
SGNORMALS* m_Normals;

View File

@ -624,7 +624,6 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
}
SGCOLORS* pc = pf->m_Colors;
SGCOLORINDEX* cidx = pf->m_ColorIndices;
SGCOORDS* pv = pf->m_Coords;
SGCOORDINDEX* vidx = pf->m_CoordIndices;
SGNORMALS* pn = pf->m_Normals;
@ -643,6 +642,24 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
SGPOINT* pCoords = NULL;
pv->GetCoordsList( nCoords, pCoords );
size_t nColors = 0;
SGCOLOR* pColors = NULL;
if( pc )
{
// check the vertex colors
pc->GetColorList( nColors, pColors );
if( nColors < nCoords )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad model; not enough colors per vertex\n";
#endif
return true;
}
}
// set the vertex indices
size_t nvidx = 0;
int* lv = NULL;
@ -673,18 +690,40 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
return true;
}
// construct the final vertex list
// construct the final vertex/color list
SFVEC3F* lColors = NULL;
SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ];
double red, green, blue;
int ti, ii;
if( pc )
{
SFVEC3F* lColors = new SFVEC3F[vertices.size()];
m.m_Color = lColors;
}
if( pc )
{
for( size_t i = 0; i < vertices.size(); ++i )
{
ti = vertices[i];
glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
pt = (*aTransform) * pt;
pColors[ti].GetColor( lColors[i].x, lColors[i].y, lColors[i].z );
lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
}
}
else
{
for( size_t i = 0; i < vertices.size(); ++i )
{
ti = vertices[i];
glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
pt = (*aTransform) * pt;
lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
}
}
m.m_VertexSize = (unsigned int) vertices.size();
m.m_Positions = lCoords;
@ -718,30 +757,6 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
}
m.m_Normals = lNorms;
// use per-vertex colors if available
if( pc )
{
size_t ncidx = 0;
int* lcidx = NULL;
cidx->GetIndices( ncidx, lcidx );
// set the vertex colors
size_t nColors = 0;
SGCOLOR* pColors = NULL;
pc->GetColorList( nColors, pColors );
SFVEC3F* lColors = new SFVEC3F[ vertices.size() ];
double red, green, blue;
for( size_t i = 0; i < vertices.size(); ++i )
{
ti = vertices[i];
pColors[ lcidx[ti] ].GetColor( lColors[i].x, lColors[i].y, lColors[i].z );
}
m.m_Color = lColors;
}
meshes.push_back( m );
return true;

View File

@ -31,7 +31,6 @@
#include "plugins/3dapi/ifsg_colors.h"
#include "plugins/3dapi/ifsg_coords.h"
#include "plugins/3dapi/ifsg_faceset.h"
#include "plugins/3dapi/ifsg_colorindex.h"
#include "plugins/3dapi/ifsg_coordindex.h"
#include "plugins/3dapi/ifsg_normals.h"
#include "plugins/3dapi/ifsg_shape.h"

View File

@ -50,7 +50,7 @@ public:
bool NewNode( IFSG_NODE& aParent );
bool GetColorList( size_t& aListSize, SGCOLOR*& aColorList );
bool SetColorList( size_t& aListSize, const SGCOLOR* aColorList );
bool SetColorList( size_t aListSize, const SGCOLOR* aColorList );
bool AddColor( double aRedValue, double aGreenValue, double aBlueValue );
bool AddColor( const SGCOLOR& aColor );
};

View File

@ -27,6 +27,7 @@
#include "vrml1_base.h"
#include "vrml1_faceset.h"
#include "vrml1_coords.h"
#include "vrml1_material.h"
#include "plugins/3dapi/ifsg_all.h"
@ -172,6 +173,34 @@ bool WRL1FACESET::Read( WRLPROC& proc, WRL1BASE* aTopNode )
return false;
}
}
else if( !glob.compare( "normalIndex" ) )
{
if( !proc.ReadMFInt( normIndex ) )
{
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] invalid normalIndex at line " << line << ", column ";
std::cerr << column << "\n";
std::cerr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
std::cerr << " * [INFO] message: '" << proc.GetError() << "'\n";
#endif
return false;
}
}
else if( !glob.compare( "textureCoordIndex" ) )
{
if( !proc.ReadMFInt( texIndex ) )
{
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] invalid textureCoordIndex at line " << line << ", column ";
std::cerr << column << "\n";
std::cerr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
std::cerr << " * [INFO] message: '" << proc.GetError() << "'\n";
#endif
return false;
}
}
else
{
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
@ -191,39 +220,74 @@ bool WRL1FACESET::Read( WRLPROC& proc, WRL1BASE* aTopNode )
SGNODE* WRL1FACESET::TranslateToSG( SGNODE* aParent, bool calcNormals )
{
#ifdef NOGO
S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
if( NULL != aParent && ptype != S3D::SGTYPE_SHAPE )
{
#ifdef DEBUG_VRML1
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] IndexedFaceSet does not have a Shape parent (parent ID: ";
std::cerr << ptype << ")\n";
#endif
return NULL;
}
if( m_sgNode )
{
if( NULL != aParent )
{
if( NULL == S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
{
if( NULL != aParent && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
return NULL;
}
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{
return NULL;
}
}
return m_sgNode;
}
if( m_Parent )
{
WRL1STATUS* cp = m_Parent->GetCurrentSettings();
if( NULL != cp )
m_current = *cp;
else
return NULL;
}
else
{
return NULL;
}
if( NULL == m_current.coord || NULL == m_current.mat )
return NULL;
// 1. create the vertex/normals/colors lists
std::vector< SGPOINT > vlist;
std::vector< SGVECTOR > nlist;
std::vector< SGCOLOR > colorlist;
SGCOLOR partColor;
SGNODE* sgcolor = NULL;
int nface = 1;
switch( m_current.matbind )
{
case BIND_OVERALL:
// use the first (non-default) appearance definition
sgcolor = m_current.mat->GetAppearance( 1 );
break;
case BIND_PER_FACE:
case BIND_PER_VERTEX:
case BIND_PER_FACE_INDEXED:
case BIND_PER_VERTEX_INDEXED:
// take the first color definition from the material
m_current.mat->GetColor( &partColor, 1 );
break;
default:
// use the default appearance definition
sgcolor = m_current.mat->GetAppearance( 0 );
break;
}
WRLVEC3F* pts;
size_t npts;
m_current.coord->GetCoords( pts, npts );
//while()
//qwerty;
#ifdef NOGO
size_t vsize = coordIndex.size();
if( NULL == coord || vsize < 3 )

View File

@ -44,6 +44,8 @@ class WRL1FACESET : public WRL1NODE
private:
std::vector< int > coordIndex;
std::vector< int > matIndex;
std::vector< int > normIndex;
std::vector< int > texIndex;
public:
WRL1FACESET( NAMEREGISTER* aDictionary );

View File

@ -57,6 +57,13 @@ WRL1MATERIAL::~WRL1MATERIAL()
std::cerr << " * [INFO] Destroying Material node\n";
#endif
// destroy any orphaned color nodes
for( int i = 0; i < 2; ++i )
{
if( NULL != colors[i] && NULL == S3D::GetSGNodeParent( colors[i] ) )
S3D::DestroyNode( colors[i] );
}
return;
}
@ -84,6 +91,9 @@ void WRL1MATERIAL::setDefaults( void )
shininess.push_back( 0.2 );
transparency.push_back( 0.0 );
colors[0] = NULL;
colors[1] = NULL;
return;
}
@ -297,3 +307,209 @@ SGNODE* WRL1MATERIAL::TranslateToSG( SGNODE* aParent, bool calcNormals )
return NULL;
}
SGNODE* WRL1MATERIAL::GetAppearance( int aIndex )
{
// invalid indices result in the default colors
if( aIndex != 0 && aIndex != 1 )
aIndex = 0;
if( NULL != colors[ aIndex ] )
return colors[ aIndex ];
IFSG_APPEARANCE app( true );
float red, green, blue, val;
if( aIndex > (int)transparency.size() )
val = transparency[0];
else
val = transparency[aIndex];
checkRange( val );
app.SetTransparency( val );
if( aIndex > (int)shininess.size() )
val = shininess[0];
else
val = shininess[aIndex];
checkRange( val );
app.SetShininess( val );
if( aIndex > (int)ambientColor.size() )
{
red = ambientColor[0].x;
green = ambientColor[0].y;
blue = ambientColor[0].z;
}
else
{
red = ambientColor[aIndex].x;
green = ambientColor[aIndex].y;
blue = ambientColor[aIndex].z;
}
checkRange( red );
checkRange( green );
checkRange( blue );
val = (red + green + blue)/3.0;
app.SetAmbient( val );
if( aIndex > (int)diffuseColor.size() )
{
red = diffuseColor[0].x;
green = diffuseColor[0].y;
blue = diffuseColor[0].z;
}
else
{
red = diffuseColor[aIndex].x;
green = diffuseColor[aIndex].y;
blue = diffuseColor[aIndex].z;
}
checkRange( red );
checkRange( green );
checkRange( blue );
app.SetDiffuse( red, green, blue );
if( aIndex > (int)emissiveColor.size() )
{
red = emissiveColor[0].x;
green = emissiveColor[0].y;
blue = emissiveColor[0].z;
}
else
{
red = emissiveColor[aIndex].x;
green = emissiveColor[aIndex].y;
blue = emissiveColor[aIndex].z;
}
checkRange( red );
checkRange( green );
checkRange( blue );
app.SetEmissive( red, green, blue );
if( aIndex > (int)specularColor.size() )
{
red = specularColor[0].x;
green = specularColor[0].y;
blue = specularColor[0].z;
}
else
{
red = specularColor[aIndex].x;
green = specularColor[aIndex].y;
blue = specularColor[aIndex].z;
}
checkRange( red );
checkRange( green );
checkRange( blue );
app.SetSpecular( red, green, blue );
colors[aIndex] = app.GetRawPtr();
return colors[aIndex];
}
void WRL1MATERIAL::GetColor( SGCOLOR* aColor, int aIndex )
{
if( NULL == aColor )
return;
// Calculate the color based on the given index.
// If the index points to a valid diffuse and emissive colors,
// take the higher value of each component.
float red, blue, green;
float eRed, eBlue, eGreen;
if( aIndex <= 0 || ( aIndex >= (int)diffuseColor.size()
&& aIndex >= (int)emissiveColor.size() ) )
{
// If the index is out of bounds, use the default diffuse color.
red = diffuseColor[0].x;
green = diffuseColor[0].y;
blue = diffuseColor[0].z;
checkRange( red );
checkRange( green );
checkRange( blue );
aColor->SetColor( red, green, blue );
return;
}
if( aIndex >= (int)diffuseColor.size() )
{
red = emissiveColor[aIndex].x;
green = emissiveColor[aIndex].y;
blue = emissiveColor[aIndex].z;
checkRange( red );
checkRange( green );
checkRange( blue );
aColor->SetColor( red, green, blue );
return;
}
if( aIndex >= (int)emissiveColor.size() )
{
red = diffuseColor[aIndex].x;
green = diffuseColor[aIndex].y;
blue = diffuseColor[aIndex].z;
checkRange( red );
checkRange( green );
checkRange( blue );
aColor->SetColor( red, green, blue );
return;
}
red = diffuseColor[aIndex].x;
green = diffuseColor[aIndex].y;
blue = diffuseColor[aIndex].z;
eRed = emissiveColor[aIndex].x;
eGreen = emissiveColor[aIndex].y;
eBlue = emissiveColor[aIndex].z;
checkRange( red );
checkRange( green );
checkRange( blue );
checkRange( eRed );
checkRange( eGreen );
checkRange( eBlue );
if( eRed > red )
red = eRed;
if( eGreen > green )
green = eGreen;
if( eBlue > blue )
blue = eBlue;
aColor->SetColor( red, green, blue );
return;
}
void WRL1MATERIAL::checkRange( float& aValue )
{
if( aValue < 0.0 )
aValue = 0.0;
else if( aValue > 1.0 )
aValue = 1.0;
return;
}

View File

@ -30,10 +30,12 @@
#define VRML1_MATERIAL_H
#include <vector>
#include <map>
#include "vrml1_node.h"
class WRL1BASE;
class SGNODE;
struct SGCOLOR;
/**
* Class WRL1MATERIAL
@ -48,7 +50,10 @@ private:
std::vector< float > shininess;
std::vector< float > transparency;
SGNODE* colors[2];
void setDefaults( void );
void checkRange( float& aValue );
public:
WRL1MATERIAL( NAMEREGISTER* aDictionary );
@ -61,7 +66,18 @@ public:
bool AddChildNode( WRL1NODE* aNode );
SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals );
// XXX - requires a function to create/retrieve a color
/**
* Function GetAppearance
* returns an SGAPPEARANCE node representing the appearance
* for an IndexedFaceSet
*/
SGNODE* GetAppearance( int aIndex );
/**
* Function GetColor
* computes an SGCOLOR representing the appearance of a vertex or face
*/
void GetColor( SGCOLOR* aColor, int aIndex );
};
#endif // VRML1_MATERIAL_H

View File

@ -286,6 +286,12 @@ WRL1NODES WRL1NODE::getNodeTypeID( const std::string aNodeName )
}
size_t WRL1NODE::GetNItems( void ) const
{
return m_Items.size();
}
std::string WRL1NODE::GetError( void )
{
return m_error;

View File

@ -220,6 +220,8 @@ public:
const char* GetNodeTypeName( WRL1NODES aNodeType ) const;
size_t GetNItems( void ) const;
/**
* Function FindNode searches the tree of linked nodes and returns a
* reference to the current node with the given name. The reference

View File

@ -140,20 +140,26 @@ SGNODE* WRL1SEPARATOR::TranslateToSG( SGNODE* aParent, bool calcNormals )
std::cerr << m_Items.size() << " items)\n";
#endif
return NULL;
if( !m_Parent )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] Separator has no parent\n";
/*
if( m_Children.empty() && m_Refs.empty() )
return NULL;
}
if( WRL1_BASE != m_Parent->GetNodeType() )
m_current = *( m_Parent->GetCurrentSettings() );
else
m_current.Init();
S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM )
{
#ifdef DEBUG_VRML1
#ifdef DEBUG_VRML2
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] Separator does not have a Separator parent (parent ID: ";
std::cerr << " * [BUG] Separator does not have a Transform parent (parent ID: ";
std::cerr << ptype << ")\n";
#endif
@ -162,80 +168,38 @@ SGNODE* WRL1SEPARATOR::TranslateToSG( SGNODE* aParent, bool calcNormals )
if( m_sgNode )
{
if( NULL != aParent )
{
if( NULL == S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
{
if( NULL == aParent )
return NULL;
}
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{
if( !S3D::AddSGNodeRef( aParent, m_sgNode ) )
return NULL;
}
}
return m_sgNode;
}
IFSG_TRANSFORM txNode( aParent );
bool hasContent = false;
std::list< WRL1NODE* >::iterator sC = m_Children.begin();
std::list< WRL1NODE* >::iterator eC = m_Children.end();
WRL1NODES type;
std::list< WRL1NODE* >::iterator sI = m_Items.begin();
std::list< WRL1NODE* >::iterator eI = m_Items.end();
// Include only the following in a Separator node:
// Shape
// Switch
// Separator
// Inline
bool test = false; // set to true if there are any subnodes for display
SGNODE* node = txNode.GetRawPtr();
for( int i = 0; i < 2; ++i )
while( sI != eI )
{
while( sC != eC )
{
type = (*sC)->GetNodeType();
if( NULL != (*sI)->TranslateToSG( node, calcNormals ) )
hasContent = true;
switch( type )
{
case WRL1_SHAPE:
case WRL1_SWITCH:
case WRL1_INLINE:
case WRL1_SEPARATOR:
if( NULL != (*sC)->TranslateToSG( txNode.GetRawPtr(), calcNormals ) )
test = true;
break;
default:
break;
++sI;
}
++ sC;
}
sC = m_Refs.begin();
eC = m_Refs.end();
}
if( false == test )
if( !hasContent )
{
txNode.Destroy();
return NULL;
}
txNode.SetScale( SGPOINT( scale.x, scale.y, scale.z ) );
txNode.SetCenter( SGPOINT( center.x, center.y, center.z ) );
txNode.SetTranslation( SGPOINT( translation.x, translation.y, translation.z ) );
txNode.SetScaleOrientation( SGVECTOR( scaleOrientation.x, scaleOrientation.y,
scaleOrientation.z ), scaleOrientation.w );
txNode.SetRotation( SGVECTOR( rotation.x, rotation.y, rotation.z), rotation.w );
m_sgNode = node;
m_sgNode = txNode.GetRawPtr();
return m_sgNode;
*/
return node;
}

View File

@ -189,7 +189,8 @@ SGNODE* WRL1SWITCH::TranslateToSG( SGNODE* aParent, bool calcNormals )
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
std::cerr << " * [INFO] Translating Switch with " << m_Children.size();
std::cerr << " children, " << m_Refs.size() << " references and ";
std::cerr << m_BackPointers.size() << " backpointers\n";
std::cerr << m_BackPointers.size() << " backpointers (total ";
std::cerr << m_Items.size() << " items)\n";
#endif
if( m_Items.empty() )
@ -201,7 +202,12 @@ SGNODE* WRL1SWITCH::TranslateToSG( SGNODE* aParent, bool calcNormals )
std::list< WRL1NODE* >::iterator ip = m_Items.begin();
std::advance( ip, whichChild );
IFSG_TRANSFORM txNode( aParent );
if( WRL1_BASE != m_Parent->GetNodeType() )
m_current = *( m_Parent->GetCurrentSettings() );
else
m_current.Init();
return (*ip)->TranslateToSG( aParent, calcNormals );
}

View File

@ -194,3 +194,30 @@ SGNODE* WRL2COLOR::TranslateToSG( SGNODE* aParent, bool calcNormals )
// any data manipulation must be performed by the parent node
return NULL;
}
bool WRL2COLOR::HasColors( void )
{
if( colors.empty() )
return false;
return true;
}
void WRL2COLOR::GetColor( int aIndex, float& red, float& green, float& blue )
{
if( aIndex < 0 || aIndex >= colors.size() )
{
red = 0.8;
green = 0.8;
blue = 0.8;
return;
}
red = colors[aIndex].x;
green = colors[aIndex].x;
blue = colors[aIndex].x;
return;
}

View File

@ -59,6 +59,18 @@ public:
bool AddRefNode( WRL2NODE* aNode );
bool AddChildNode( WRL2NODE* aNode );
SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals );
/**
* Function HasColors
* returns true if the color set is non-empty
*/
bool HasColors( void );
/**
* Function GetColor
* retrieves the given color (or default 0.8, 0.8, 0.8 if index is invalid)
*/
void GetColor( int aIndex, float& red, float& green, float& blue );
};
#endif // VRML2_COLOR_H

View File

@ -27,6 +27,7 @@
#include "vrml2_base.h"
#include "vrml2_faceset.h"
#include "vrml2_coords.h"
#include "vrml2_color.h"
#include "plugins/3dapi/ifsg_all.h"
@ -632,8 +633,11 @@ SGNODE* WRL2FACESET::TranslateToSG( SGNODE* aParent, bool calcNormals )
std::vector< int > lCIdx; // coordinate index list for SG node (must be triads)
std::vector< SGVECTOR > lCNorm; // per-vertex normals
std::vector< int > faces; // tracks the number of polygons for the entire set
std::vector< SGCOLOR > lColors; // colors points (if any) for SG node
int nfaces = 0; // number of triangles for each face in the list
if( NULL == color )
{
// assuming convex polygons, create triangles for the SG node
for( idx = 3; idx < vsize; )
{
@ -672,6 +676,98 @@ SGNODE* WRL2FACESET::TranslateToSG( SGNODE* aParent, bool calcNormals )
return NULL;
}
}
}
else
{
int cIndex;
WRL2COLOR* cn = (WRL2COLOR*) color;
SGCOLOR pc1, pc2, pc3;
WRLVEC3F tc;
cn->GetColor( 0, tc.x, tc.y, tc.z );
pc1.SetColor( tc.x, tc.y, tc.z );
if( colorPerVertex )
{
cIndex = 3;
cn->GetColor( 1, tc.x, tc.y, tc.z );
pc2.SetColor( tc.x, tc.y, tc.z );
cn->GetColor( 2, tc.x, tc.y, tc.z );
pc3.SetColor( tc.x, tc.y, tc.z );
}
else
{
cIndex = 1;
pc2.SetColor( tc.x, tc.y, tc.z );
pc3.SetColor( tc.x, tc.y, tc.z );
}
// assuming convex polygons, create triangles for the SG node
for( idx = 3; idx < vsize; )
{
lCIdx.push_back( i1 );
lColors.push_back( pc1 );
lColors.push_back( pc2 );
lColors.push_back( pc3 );
if( ccw )
{
lCIdx.push_back( i2 );
lCIdx.push_back( i3 );
}
else
{
lCIdx.push_back( i3 );
lCIdx.push_back( i2 );
}
++nfaces;
i2 = i3;
i3 = coordIndex[idx++];
if( colorPerVertex && i1 >= 0 && i2 >= 0 && i3 >= 0 )
{
pc1.SetColor( pc2 );
pc2.SetColor( pc3 );
cn->GetColor( cIndex++, tc.x, tc.y, tc.z );
pc3.SetColor( tc.x, tc.y, tc.z );
}
while( ( i1 < 0 || i2 < 0 || i3 < 0 ) && ( idx < vsize ) )
{
if( i3 < 0 )
{
faces.push_back( nfaces );
nfaces = 0;
if( !colorPerVertex )
{
cn->GetColor( cIndex++, tc.x, tc.y, tc.z );
pc1.SetColor( tc.x, tc.y, tc.z );
pc2.SetColor( tc.x, tc.y, tc.z );
pc3.SetColor( tc.x, tc.y, tc.z );
}
}
i1 = i2;
i2 = i3;
i3 = coordIndex[idx++];
if( colorPerVertex )
{
pc1.SetColor( pc2 );
pc2.SetColor( pc3 );
cn->GetColor( cIndex++, tc.x, tc.y, tc.z );
pc3.SetColor( tc.x, tc.y, tc.z );
}
// any invalid polygons shall void the entire faceset; this is a requirement
// to ensure correct handling of the normals
if( ( i1 < 0 && i2 < 0 ) || ( i1 < 0 && i3 < 0 ) || ( i2 < 0 && i3 < 0 ) )
return NULL;
}
}
}
if( lCIdx.empty() )
return NULL;
@ -755,6 +851,12 @@ SGNODE* WRL2FACESET::TranslateToSG( SGNODE* aParent, bool calcNormals )
IFSG_NORMALS nmNode( fsNode );
nmNode.SetNormalList( lCNorm.size(), &lCNorm[0] );
if( !lColors.empty() )
{
IFSG_COLORS nmColor( fsNode );
nmColor.SetColorList( lColors.size(), &lColors[0] );
}
m_sgNode = fsNode.GetRawPtr();
return m_sgNode;
@ -805,3 +907,12 @@ void WRL2FACESET::unlinkRefNode( const WRL2NODE* aNode )
WRL2NODE::unlinkRefNode( aNode );
return;
}
bool WRL2FACESET::HasColors( void )
{
if( NULL == color )
return false;
return ((WRL2COLOR*) color)->HasColors();
}

View File

@ -88,6 +88,12 @@ public:
bool AddRefNode( WRL2NODE* aNode );
bool AddChildNode( WRL2NODE* aNode );
SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals );
/**
* Function HasColors
* returns true if the face set has a color node
*/
bool HasColors( void );
};
#endif // VRML2_FACESET_H

View File

@ -27,6 +27,7 @@
#include "vrml2_base.h"
#include "vrml2_shape.h"
#include "plugins/3dapi/ifsg_all.h"
#include "vrml2_faceset.h"
WRL2SHAPE::WRL2SHAPE() : WRL2NODE()
@ -318,9 +319,20 @@ bool WRL2SHAPE::Read( WRLPROC& proc, WRL2BASE* aTopNode )
SGNODE* WRL2SHAPE::TranslateToSG( SGNODE* aParent, bool calcNormals )
{
if( NULL == appearance || NULL == geometry )
// XXX - TO BE IMPLEMENTED:
if( NULL == geometry )
return NULL;
// if there is no appearance, make use of the per vertex colors if available
if( NULL == appearance )
{
if( WRL2_INDEXEDFACESET != geometry->GetNodeType() )
return NULL;
if( !((WRL2FACESET*)geometry)->HasColors() )
return NULL;
}
S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM )
@ -356,10 +368,13 @@ SGNODE* WRL2SHAPE::TranslateToSG( SGNODE* aParent, bool calcNormals )
IFSG_SHAPE shNode( aParent );
SGNODE* pShape = shNode.GetRawPtr();
SGNODE* pApp = appearance->TranslateToSG( pShape, calcNormals );
SGNODE* pGeom = geometry->TranslateToSG( pShape, calcNormals );
SGNODE* pApp = NULL;
if( NULL == pApp || NULL == pGeom )
if( NULL != appearance )
pApp = appearance->TranslateToSG( pShape, calcNormals );
if( ( NULL != appearance && NULL == pApp ) || NULL == pGeom )
{
if( pGeom )
{

View File

@ -87,14 +87,15 @@ enum WRL1NODES
};
// VRML1 Material/Normal Binding values
// note: PART/FACE have the same meaning in the specification
enum WRL1_BINDING
{
BIND_DEFAULT = 0,
BIND_OVERALL,
BIND_PER_PART,
BIND_PER_FACE = BIND_PER_PART,
BIND_PER_PART_INDEXED,
BIND_PER_FACE,
BIND_PER_FACE_INDEXED,
BIND_PER_FACE_INDEXED = BIND_PER_PART_INDEXED,
BIND_PER_VERTEX,
BIND_PER_VERTEX_INDEXED,
BIND_END