Initial introduction of improved VRML normals calculations; working on VRML1
This commit is contained in:
parent
8dd744f635
commit
55c7c61458
|
@ -5,12 +5,13 @@ include_directories(
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/v2
|
||||
)
|
||||
|
||||
add_definitions( -DDEBUG_VRML1=2 -DDEBUG_VRML2=2 )
|
||||
add_definitions( -DDEBUG_VRML1=4 -DDEBUG_VRML2=1 )
|
||||
|
||||
add_library( s3d_plugin_vrml MODULE
|
||||
${CMAKE_SOURCE_DIR}/common/richio.cpp
|
||||
vrml.cpp
|
||||
wrlproc.cpp
|
||||
wrlfacet.cpp
|
||||
v2/vrml2_node.cpp
|
||||
v2/vrml2_base.cpp
|
||||
v2/vrml2_transform.cpp
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "vrml1_faceset.h"
|
||||
#include "vrml1_coords.h"
|
||||
#include "vrml1_material.h"
|
||||
#include "wrlfacet.h"
|
||||
#include "plugins/3dapi/ifsg_all.h"
|
||||
|
||||
|
||||
|
@ -286,13 +287,14 @@ SGNODE* WRL1FACESET::TranslateToSG( SGNODE* aParent, WRL1STATUS* sp )
|
|||
std::vector< SGVECTOR > nlist;
|
||||
std::vector< SGCOLOR > colorlist;
|
||||
SGNODE* sgcolor = NULL;
|
||||
|
||||
WRL1_BINDING mbind = m_current.matbind;
|
||||
size_t matSize = matIndex.size();
|
||||
|
||||
switch( mbind )
|
||||
{
|
||||
case BIND_PER_FACE:
|
||||
case BIND_PER_VERTEX:
|
||||
case BIND_PER_VERTEX_INDEXED:
|
||||
break;
|
||||
|
||||
case BIND_PER_FACE_INDEXED:
|
||||
|
@ -310,22 +312,6 @@ SGNODE* WRL1FACESET::TranslateToSG( SGNODE* aParent, WRL1STATUS* sp )
|
|||
|
||||
break;
|
||||
|
||||
case BIND_PER_VERTEX_INDEXED:
|
||||
|
||||
if( matIndex.size() < 3 )
|
||||
{
|
||||
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||
std::cerr << " * [INFO] bad model: per vertex indexed but indexsize = ";
|
||||
std::cerr << matIndex.size() << "\n";
|
||||
#endif
|
||||
|
||||
// support bad models by temporarily switching bindings
|
||||
mbind = BIND_OVERALL;
|
||||
sgcolor = m_current.mat->GetAppearance( 0 );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
// use the first appearance definition
|
||||
|
@ -333,387 +319,155 @@ SGNODE* WRL1FACESET::TranslateToSG( SGNODE* aParent, WRL1STATUS* sp )
|
|||
break;
|
||||
}
|
||||
|
||||
// create the index list and make sure we have >3 points
|
||||
size_t idx;
|
||||
int i1 = coordIndex[0];
|
||||
int i2 = coordIndex[1];
|
||||
int i3 = coordIndex[2];
|
||||
// copy the data into FACET structures
|
||||
|
||||
// check that all indices are valid
|
||||
for( idx = 0; idx < vsize; ++idx )
|
||||
SHAPE lShape;
|
||||
FACET* fp = NULL;
|
||||
size_t iCoord;
|
||||
int idx; // coordinate index
|
||||
size_t cidx = 0; // color index
|
||||
SGCOLOR pc1;
|
||||
|
||||
if( mbind == BIND_OVERALL || mbind == BIND_DEFAULT )
|
||||
{
|
||||
if( coordIndex[idx] < 0 )
|
||||
continue;
|
||||
|
||||
if( coordIndex[idx] >= (int)coordsize )
|
||||
// no per-vertex colors; we can save a few CPU cycles
|
||||
for( iCoord = 0; iCoord < vsize; ++iCoord )
|
||||
{
|
||||
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||
std::cerr << " * [INFO] bad model: index out of bounds (index = ";
|
||||
std::cerr << coordIndex[idx] << ", npts = " << coordsize << ")\n";
|
||||
#endif
|
||||
idx = coordIndex[iCoord];
|
||||
|
||||
m_current.mat->Reclaim( sgcolor );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// if the indices are defective just give up
|
||||
if( i1 < 0 || i2 < 0 || i3 < 0
|
||||
|| i1 == i2 || i1 == i3 || i2 == i3 )
|
||||
{
|
||||
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||
std::cerr << " * [INFO] bad model: defective indices: " << i1;
|
||||
std::cerr << ", " << i2 << ", " << i3 << "\n";
|
||||
#endif
|
||||
|
||||
m_current.mat->Reclaim( sgcolor );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::vector< SGPOINT > lCPts; // coordinate points for SG node
|
||||
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( BIND_OVERALL == mbind || BIND_DEFAULT == mbind )
|
||||
{
|
||||
// no color list
|
||||
// assuming convex polygons, create triangles for the SG node
|
||||
for( idx = 3; idx <= vsize; )
|
||||
{
|
||||
switch( m_current.order )
|
||||
if( idx < 0 )
|
||||
{
|
||||
case ORD_CCW:
|
||||
lCIdx.push_back( i1 );
|
||||
lCIdx.push_back( i2 );
|
||||
lCIdx.push_back( i3 );
|
||||
break;
|
||||
|
||||
case ORD_CLOCKWISE:
|
||||
lCIdx.push_back( i1 );
|
||||
lCIdx.push_back( i3 );
|
||||
lCIdx.push_back( i2 );
|
||||
break;
|
||||
|
||||
default:
|
||||
lCIdx.push_back( i1 );
|
||||
lCIdx.push_back( i2 );
|
||||
lCIdx.push_back( i3 );
|
||||
lCIdx.push_back( i1 );
|
||||
lCIdx.push_back( i3 );
|
||||
lCIdx.push_back( i2 );
|
||||
break;
|
||||
}
|
||||
|
||||
++nfaces;
|
||||
i2 = i3;
|
||||
|
||||
if( idx == vsize )
|
||||
break;
|
||||
|
||||
i3 = coordIndex[idx++];
|
||||
|
||||
while( ( i1 < 0 || i2 < 0 || i3 < 0 ) && ( idx < vsize ) )
|
||||
{
|
||||
if( i3 < 0 )
|
||||
if( NULL != fp )
|
||||
{
|
||||
faces.push_back( nfaces );
|
||||
nfaces = 0;
|
||||
if( fp->HasMinPoints() )
|
||||
fp = NULL;
|
||||
else
|
||||
fp->Init();
|
||||
}
|
||||
|
||||
i1 = i2;
|
||||
i2 = i3;
|
||||
i3 = coordIndex[idx++];
|
||||
|
||||
// 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 ) )
|
||||
{
|
||||
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||
std::cerr << " * [INFO] bad model: defective indices: " << i1;
|
||||
std::cerr << ", " << i2 << ", " << i3 << "\n";
|
||||
#endif
|
||||
|
||||
m_current.mat->Reclaim( sgcolor );
|
||||
return NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if( i1 < 0 || i2 < 0 || i3 < 0 )
|
||||
break;
|
||||
// if the coordinate is bad then skip it
|
||||
if( idx >= (int)coordsize )
|
||||
continue;
|
||||
|
||||
if( NULL == fp )
|
||||
fp = lShape.NewFacet();
|
||||
|
||||
// push the vertex value and index
|
||||
WRLVEC3F vf;
|
||||
glm::vec4 pt = glm::vec4( pcoords[idx].x, pcoords[idx].y, pcoords[idx].z, 1.0 );
|
||||
pt = m_current.txmatrix * pt;
|
||||
vf.x = pt.x;
|
||||
vf.y = pt.y;
|
||||
vf.z = pt.z;
|
||||
|
||||
fp->AddVertex( vf, idx );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// the entity requires a color list
|
||||
int cIndex;
|
||||
SGCOLOR pc1, pc2, pc3;
|
||||
|
||||
switch( mbind )
|
||||
for( iCoord = 0; iCoord < vsize; ++iCoord )
|
||||
{
|
||||
case BIND_PER_VERTEX:
|
||||
cIndex = 3;
|
||||
m_current.mat->GetColor( &pc1, 0 );
|
||||
m_current.mat->GetColor( &pc2, 1 );
|
||||
m_current.mat->GetColor( &pc3, 2 );
|
||||
break;
|
||||
idx = coordIndex[iCoord];
|
||||
|
||||
case BIND_PER_VERTEX_INDEXED:
|
||||
cIndex = 3;
|
||||
|
||||
if( matIndex.size() < vsize )
|
||||
if( idx < 0 )
|
||||
{
|
||||
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * [INFO] bad file; colorIndex.size() < coordIndex.size()\n";
|
||||
#endif
|
||||
if( NULL != fp )
|
||||
{
|
||||
if( fp->HasMinPoints() )
|
||||
fp = NULL;
|
||||
else
|
||||
fp->Init();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
if( mbind == BIND_PER_FACE || mbind == BIND_PER_FACE_INDEXED )
|
||||
++cidx;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
m_current.mat->GetColor( &pc1, matIndex[0] );
|
||||
m_current.mat->GetColor( &pc2, matIndex[1] );
|
||||
m_current.mat->GetColor( &pc3, matIndex[2] );
|
||||
break;
|
||||
// if the coordinate is bad then skip it
|
||||
if( idx >= (int)coordsize )
|
||||
continue;
|
||||
|
||||
case BIND_PER_FACE:
|
||||
cIndex = 1;
|
||||
m_current.mat->GetColor( &pc1, 0 );
|
||||
pc2.SetColor( pc1 );
|
||||
pc3.SetColor( pc1 );
|
||||
break;
|
||||
if( NULL == fp )
|
||||
fp = lShape.NewFacet();
|
||||
|
||||
default:
|
||||
// BIND_PER_FACE_INDEXED
|
||||
cIndex = 1;
|
||||
m_current.mat->GetColor( &pc1, matIndex[0] );
|
||||
pc2.SetColor( pc1 );
|
||||
pc3.SetColor( pc1 );
|
||||
break;
|
||||
}
|
||||
// push the vertex value and index
|
||||
WRLVEC3F vf;
|
||||
glm::vec4 pt = glm::vec4( pcoords[idx].x, pcoords[idx].y, pcoords[idx].z, 1.0 );
|
||||
pt = m_current.txmatrix * pt;
|
||||
vf.x = pt.x;
|
||||
vf.y = pt.y;
|
||||
vf.z = pt.z;
|
||||
|
||||
// assuming convex polygons, create triangles for the SG node
|
||||
int cMaxIdx = (int) matIndex.size();
|
||||
fp->AddVertex( vf, idx );
|
||||
|
||||
bool colorPerVertex = false;
|
||||
|
||||
if( BIND_PER_VERTEX == mbind
|
||||
|| BIND_PER_VERTEX_INDEXED == mbind )
|
||||
colorPerVertex = true;
|
||||
|
||||
bool noidx = false;
|
||||
|
||||
if( matIndex.empty() )
|
||||
noidx = true;
|
||||
|
||||
for( idx = 3; idx <= vsize; )
|
||||
{
|
||||
switch( m_current.order )
|
||||
// push the color if appropriate
|
||||
switch( mbind )
|
||||
{
|
||||
case ORD_CCW:
|
||||
lCIdx.push_back( i1 );
|
||||
lCIdx.push_back( i2 );
|
||||
lCIdx.push_back( i3 );
|
||||
lColors.push_back( pc1 );
|
||||
lColors.push_back( pc2 );
|
||||
lColors.push_back( pc3 );
|
||||
case BIND_PER_FACE:
|
||||
|
||||
if( !fp->HasColors() )
|
||||
{
|
||||
m_current.mat->GetColor( &pc1, cidx );
|
||||
fp->AddColor( pc1 );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ORD_CLOCKWISE:
|
||||
lCIdx.push_back( i1 );
|
||||
lCIdx.push_back( i3 );
|
||||
lCIdx.push_back( i2 );
|
||||
lColors.push_back( pc1 );
|
||||
lColors.push_back( pc3 );
|
||||
lColors.push_back( pc2 );
|
||||
case BIND_PER_VERTEX:
|
||||
m_current.mat->GetColor( &pc1, idx );
|
||||
fp->AddColor( pc1 );
|
||||
++cidx;
|
||||
break;
|
||||
|
||||
case BIND_PER_FACE_INDEXED:
|
||||
if( !fp->HasColors() )
|
||||
{
|
||||
if( cidx >= matSize )
|
||||
m_current.mat->GetColor( &pc1, matIndex.back() );
|
||||
else
|
||||
m_current.mat->GetColor( &pc1, matIndex[cidx] );
|
||||
|
||||
fp->AddColor( pc1 );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BIND_PER_VERTEX_INDEXED:
|
||||
|
||||
if( matIndex.empty() )
|
||||
{
|
||||
int ic = coordIndex[iCoord];
|
||||
|
||||
if( ic >= (int)matSize )
|
||||
m_current.mat->GetColor( &pc1, matIndex.back() );
|
||||
else
|
||||
m_current.mat->GetColor( &pc1, matIndex[ic] );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( iCoord >= matSize )
|
||||
m_current.mat->GetColor( &pc1, matIndex.back() );
|
||||
else
|
||||
m_current.mat->GetColor( &pc1, matIndex[iCoord] );
|
||||
}
|
||||
|
||||
fp->AddColor( pc1 );
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
lCIdx.push_back( i1 );
|
||||
lCIdx.push_back( i2 );
|
||||
lCIdx.push_back( i3 );
|
||||
lCIdx.push_back( i1 );
|
||||
lCIdx.push_back( i3 );
|
||||
lCIdx.push_back( i2 );
|
||||
lColors.push_back( pc1 );
|
||||
lColors.push_back( pc2 );
|
||||
lColors.push_back( pc3 );
|
||||
lColors.push_back( pc1 );
|
||||
lColors.push_back( pc3 );
|
||||
lColors.push_back( pc2 );
|
||||
break;
|
||||
}
|
||||
|
||||
++nfaces;
|
||||
i2 = i3;
|
||||
|
||||
if( idx == vsize )
|
||||
break;
|
||||
|
||||
i3 = coordIndex[idx++];
|
||||
|
||||
if( colorPerVertex && i1 >= 0 && i2 >= 0 && i3 >= 0 )
|
||||
{
|
||||
pc1.SetColor( pc2 );
|
||||
pc2.SetColor( pc3 );
|
||||
|
||||
if( noidx || cIndex >= cMaxIdx )
|
||||
m_current.mat->GetColor( &pc3, cIndex++ );
|
||||
else
|
||||
m_current.mat->GetColor( &pc3, matIndex[cIndex++] );
|
||||
|
||||
}
|
||||
|
||||
while( ( i1 < 0 || i2 < 0 || i3 < 0 ) && ( idx < vsize ) )
|
||||
{
|
||||
if( i3 < 0 )
|
||||
{
|
||||
faces.push_back( nfaces );
|
||||
nfaces = 0;
|
||||
|
||||
if( !colorPerVertex )
|
||||
{
|
||||
if( noidx || cIndex >= cMaxIdx )
|
||||
m_current.mat->GetColor( &pc1, cIndex++ );
|
||||
else
|
||||
m_current.mat->GetColor( &pc1, matIndex[cIndex++] );
|
||||
|
||||
pc2.SetColor( pc1 );
|
||||
pc3.SetColor( pc1 );
|
||||
}
|
||||
}
|
||||
|
||||
i1 = i2;
|
||||
i2 = i3;
|
||||
i3 = coordIndex[idx++];
|
||||
|
||||
if( colorPerVertex )
|
||||
{
|
||||
pc1.SetColor( pc2 );
|
||||
pc2.SetColor( pc3 );
|
||||
|
||||
if( noidx || cIndex >= cMaxIdx )
|
||||
m_current.mat->GetColor( &pc3, cIndex++ );
|
||||
else
|
||||
m_current.mat->GetColor( &pc3, matIndex[cIndex++] );
|
||||
|
||||
}
|
||||
|
||||
// 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 ) )
|
||||
{
|
||||
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||
std::cerr << " * [INFO] bad model: defective indices: " << i1;
|
||||
std::cerr << ", " << i2 << ", " << i3 << "\n";
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( i1 < 0 || i2 < 0 || i3 < 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( lCIdx.empty() )
|
||||
{
|
||||
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||
std::cerr << " * [INFO] bad model: no points in final index list\n";
|
||||
#endif
|
||||
// extract the final data set
|
||||
SGNODE* np = lShape.CalcShape( aParent, sgcolor, m_current.order, m_current.creaseAngle );
|
||||
|
||||
m_current.mat->Reclaim( sgcolor );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// create a vertex list for per-face per-vertex normals
|
||||
do {
|
||||
std::vector< int >::iterator sI = lCIdx.begin();
|
||||
std::vector< int >::iterator eI = lCIdx.end();
|
||||
|
||||
while( sI != eI )
|
||||
{
|
||||
glm::vec4 pt = glm::vec4( pcoords[*sI].x, pcoords[*sI].y, pcoords[*sI].z, 1.0 );
|
||||
pt = m_current.txmatrix * pt;
|
||||
lCPts.push_back( SGPOINT( pt.x, pt.y, pt.z ) );
|
||||
++sI;
|
||||
}
|
||||
|
||||
switch( m_current.order )
|
||||
{
|
||||
case ORD_CCW:
|
||||
|
||||
for( size_t i = 0; i < lCPts.size(); i += 3 )
|
||||
{
|
||||
SGVECTOR sv = S3D::CalcTriNorm( lCPts[i], lCPts[i+1], lCPts[i+2] );
|
||||
lCNorm.push_back( sv );
|
||||
lCNorm.push_back( sv );
|
||||
lCNorm.push_back( sv );
|
||||
}
|
||||
break;
|
||||
|
||||
case ORD_CLOCKWISE:
|
||||
|
||||
for( size_t i = 0; i < lCPts.size(); i += 3 )
|
||||
{
|
||||
SGVECTOR sv = S3D::CalcTriNorm( lCPts[i], lCPts[i+2], lCPts[i+1] );
|
||||
lCNorm.push_back( sv );
|
||||
lCNorm.push_back( sv );
|
||||
lCNorm.push_back( sv );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
for( size_t i = 0; i < lCPts.size(); i += 6 )
|
||||
{
|
||||
SGVECTOR sv = S3D::CalcTriNorm( lCPts[i], lCPts[i+1], lCPts[i+2] );
|
||||
lCNorm.push_back( sv );
|
||||
lCNorm.push_back( sv );
|
||||
lCNorm.push_back( sv );
|
||||
sv = S3D::CalcTriNorm( lCPts[i], lCPts[i+2], lCPts[i+1] );
|
||||
lCNorm.push_back( sv );
|
||||
lCNorm.push_back( sv );
|
||||
lCNorm.push_back( sv );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
// create the hierarchy:
|
||||
// Shape
|
||||
// + (option) Appearance
|
||||
// + FaceSet
|
||||
IFSG_SHAPE shapeNode( aParent );
|
||||
|
||||
if( sgcolor )
|
||||
{
|
||||
if( NULL == S3D::GetSGNodeParent( sgcolor ) )
|
||||
shapeNode.AddChildNode( sgcolor );
|
||||
else
|
||||
shapeNode.AddRefNode( sgcolor );
|
||||
}
|
||||
|
||||
IFSG_FACESET fsNode( shapeNode );
|
||||
IFSG_COORDS cpNode( fsNode );
|
||||
cpNode.SetCoordsList( lCPts.size(), &lCPts[0] );
|
||||
IFSG_COORDINDEX ciNode( fsNode );
|
||||
|
||||
for( int i = 0; i < (int)lCPts.size(); ++i )
|
||||
ciNode.AddIndex( i );
|
||||
|
||||
IFSG_NORMALS nmNode( fsNode );
|
||||
nmNode.SetNormalList( lCNorm.size(), &lCNorm[0] );
|
||||
|
||||
if( !lColors.empty() )
|
||||
{
|
||||
IFSG_COLORS nmColor( fsNode );
|
||||
nmColor.SetColorList( lColors.size(), &lColors[0] );
|
||||
}
|
||||
|
||||
return fsNode.GetRawPtr();
|
||||
return np;
|
||||
}
|
||||
|
|
|
@ -80,6 +80,8 @@ struct WRL1STATUS
|
|||
// winding order of vertices
|
||||
WRL1_ORDER order;
|
||||
|
||||
float creaseAngle;
|
||||
|
||||
WRL1STATUS()
|
||||
{
|
||||
Init();
|
||||
|
@ -95,6 +97,7 @@ struct WRL1STATUS
|
|||
coord = NULL;
|
||||
txmatrix = glm::scale( glm::mat4( 1.0 ), glm::vec3( 1.0 ) );
|
||||
order = ORD_UNKNOWN;
|
||||
creaseAngle = 0.5;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
#include "vrml1_base.h"
|
||||
#include "vrml1_shapehints.h"
|
||||
|
@ -33,6 +34,7 @@ WRL1SHAPEHINTS::WRL1SHAPEHINTS( NAMEREGISTER* aDictionary ) : WRL1NODE( aDiction
|
|||
{
|
||||
m_order = ORD_UNKNOWN;
|
||||
m_Type = WRL1_SHAPEHINTS;
|
||||
m_crease = 0.5;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -229,6 +231,13 @@ bool WRL1SHAPEHINTS::Read( WRLPROC& proc, WRL1BASE* aTopNode )
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( tmp < 0.0 )
|
||||
tmp = 0.0;
|
||||
else if( tmp > M_PI )
|
||||
tmp = M_PI;
|
||||
|
||||
m_crease = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -262,6 +271,7 @@ SGNODE* WRL1SHAPEHINTS::TranslateToSG( SGNODE* aParent, WRL1STATUS* sp )
|
|||
}
|
||||
|
||||
sp->order = m_order;
|
||||
sp->creaseAngle = m_crease;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,8 @@ class SGNODE;
|
|||
class WRL1SHAPEHINTS : public WRL1NODE
|
||||
{
|
||||
private:
|
||||
WRL1_ORDER m_order;
|
||||
WRL1_ORDER m_order; // vertex order
|
||||
float m_crease; // VRML creaseAngle
|
||||
|
||||
public:
|
||||
WRL1SHAPEHINTS( NAMEREGISTER* aDictionary );
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
|
||||
#define PLUGIN_VRML_MAJOR 1
|
||||
#define PLUGIN_VRML_MINOR 0
|
||||
#define PLUGIN_VRML_MINOR 1
|
||||
#define PLUGIN_VRML_PATCH 0
|
||||
#define PLUGIN_VRML_REVNO 0
|
||||
|
||||
|
|
|
@ -0,0 +1,748 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "wrlfacet.h"
|
||||
|
||||
|
||||
static bool VDegenerate( glm::vec3* pts )
|
||||
{
|
||||
double dx, dy, dz;
|
||||
|
||||
dx = pts[1].x - pts[0].x;
|
||||
dy = pts[1].y - pts[0].y;
|
||||
dz = pts[1].z - pts[0].z;
|
||||
|
||||
if( ( dx*dx + dy*dy + dz*dz ) < 1e-6 )
|
||||
return true;
|
||||
|
||||
dx = pts[2].x - pts[0].x;
|
||||
dy = pts[2].y - pts[0].y;
|
||||
dz = pts[2].z - pts[0].z;
|
||||
|
||||
if( ( dx*dx + dy*dy + dz*dz ) < 1e-6 )
|
||||
return true;
|
||||
|
||||
dx = pts[2].x - pts[1].x;
|
||||
dy = pts[2].y - pts[1].y;
|
||||
dz = pts[2].z - pts[1].z;
|
||||
|
||||
if( ( dx*dx + dy*dy + dz*dz ) < 1e-6 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
static WRLVEC3F VCalcTriNorm( const WRLVEC3F& p1, const WRLVEC3F& p2, const WRLVEC3F& p3 )
|
||||
{
|
||||
// note: p1 = reference vertex
|
||||
|
||||
WRLVEC3F result;
|
||||
result.x = 0.0;
|
||||
result.y = 0.0;
|
||||
result.z = 1.0;
|
||||
|
||||
glm::vec3 tri = glm::dvec3( 0.0, 0.0, 0.0 );
|
||||
glm::vec3 pts[3];
|
||||
|
||||
pts[0] = glm::vec3( p1.x, p1.y, p1.z );
|
||||
pts[1] = glm::vec3( p2.x, p2.y, p2.z );
|
||||
pts[2] = glm::vec3( p3.x, p3.y, p3.z );
|
||||
|
||||
// degenerate points are given a default 0, 0, 1 normal
|
||||
if( VDegenerate( pts ) )
|
||||
return result;
|
||||
|
||||
// normal
|
||||
tri = cross( pts[1] - pts[0], pts[2] - pts[0] );
|
||||
normalize( tri );
|
||||
|
||||
result.x = tri.x;
|
||||
result.y = tri.y;
|
||||
result.z = tri.z;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void printX( const WRLVEC3F& p1 )
|
||||
{
|
||||
std::cerr << p1.x << ", " << p1.y << ", " << p1.z << "\n";
|
||||
}
|
||||
|
||||
// p1 = reference vertex
|
||||
static float VCalcAngle( const WRLVEC3F& p1, const WRLVEC3F& p2, const WRLVEC3F& p3 )
|
||||
{
|
||||
// note: p1 = reference vertex
|
||||
float l12, l13;
|
||||
float dx, dy, dz;
|
||||
|
||||
dx = p2.x - p1.x;
|
||||
dy = p2.y - p1.y;
|
||||
dz = p2.z - p1.z;
|
||||
float p12 = dx*dx + dy*dy + dz*dz;
|
||||
l12 = sqrtf( p12 );
|
||||
|
||||
dx = p3.x - p2.x;
|
||||
dy = p3.y - p2.y;
|
||||
dz = p3.z - p2.z;
|
||||
float p23 = dx*dx + dy*dy + dz*dz;
|
||||
|
||||
dx = p3.x - p1.x;
|
||||
dy = p3.y - p1.y;
|
||||
dz = p3.z - p1.z;
|
||||
float p13 = dx*dx + dy*dy + dz*dz;
|
||||
l13 = sqrtf( p13 );
|
||||
|
||||
float dn = 2.0 * l12 * l13;
|
||||
|
||||
// place a limit to prevent calculations from blowing up
|
||||
if( dn < 1e-15 )
|
||||
return 0.0;
|
||||
|
||||
float cosAngle = (p12 + p13 - p23) / dn;
|
||||
|
||||
// check the domain; errors in the cosAngle calculation
|
||||
// can result in domain errors
|
||||
if( cosAngle > 1.0 || cosAngle < -1.0 )
|
||||
cosAngle = 1.0;
|
||||
|
||||
// note: we are guaranteed that acosf() is never negative
|
||||
return acosf( cosAngle );
|
||||
}
|
||||
|
||||
|
||||
FACET::FACET()
|
||||
{
|
||||
face_normal.x = 0.0;
|
||||
face_normal.y = 0.0;
|
||||
face_normal.z = 0.0;
|
||||
maxIdx = 0;
|
||||
}
|
||||
|
||||
|
||||
void FACET::Init()
|
||||
{
|
||||
vertices.clear();
|
||||
colors.clear();
|
||||
indices.clear();
|
||||
norms.clear();
|
||||
vnweight.clear();
|
||||
|
||||
face_normal.x = 0.0;
|
||||
face_normal.y = 0.0;
|
||||
face_normal.z = 0.0;
|
||||
maxIdx = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool FACET::HasMinPoints()
|
||||
{
|
||||
if( vertices.size() < 3 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FACET::HasColors()
|
||||
{
|
||||
if( colors.empty() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void FACET::AddVertex( WRLVEC3F& aVertex, int aIndex )
|
||||
{
|
||||
if( aIndex < 0 )
|
||||
return;
|
||||
|
||||
vertices.push_back( aVertex );
|
||||
indices.push_back( aIndex );
|
||||
|
||||
if( aIndex > maxIdx )
|
||||
maxIdx = aIndex;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void FACET::AddColor( const SGCOLOR& aColor )
|
||||
{
|
||||
colors.push_back( aColor );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void FACET::CalcFaceNormal()
|
||||
{
|
||||
// note: this calculation assumes that the face is a convex polygon;
|
||||
// concave polygons may be supported in the future via functions which
|
||||
// split the polygon into triangles
|
||||
|
||||
if( vertices.size() < 3 )
|
||||
return;
|
||||
|
||||
// check if the values were already calculated
|
||||
if( vertices.size() == vnweight.size() )
|
||||
return;
|
||||
|
||||
WRLVEC3F lCPts[3];
|
||||
|
||||
std::vector< WRLVEC3F >::iterator sV = vertices.begin();
|
||||
std::vector< WRLVEC3F >::iterator eV = vertices.end();
|
||||
|
||||
lCPts[0] = vertices.back();
|
||||
lCPts[1] = *sV;
|
||||
++sV;
|
||||
lCPts[2] = *sV;
|
||||
++sV;
|
||||
|
||||
face_normal = VCalcTriNorm( lCPts[1], lCPts[0], lCPts[2] );
|
||||
|
||||
vnweight.clear();
|
||||
WRLVEC3F wnorm = face_normal;
|
||||
float ang = VCalcAngle( lCPts[1], lCPts[0], lCPts[2] );
|
||||
wnorm.x *= ang;
|
||||
wnorm.y *= ang;
|
||||
wnorm.z *= ang;
|
||||
vnweight.push_back( wnorm );
|
||||
|
||||
while( sV != eV )
|
||||
{
|
||||
lCPts[0] = lCPts[1];
|
||||
lCPts[1] = lCPts[2];
|
||||
lCPts[2] = *sV;
|
||||
++sV;
|
||||
|
||||
WRLVEC3F wnorm = face_normal;
|
||||
ang = VCalcAngle( lCPts[1], lCPts[0], lCPts[2] );
|
||||
wnorm.x *= ang;
|
||||
wnorm.y *= ang;
|
||||
wnorm.z *= ang;
|
||||
vnweight.push_back( wnorm );
|
||||
}
|
||||
|
||||
lCPts[0] = lCPts[1];
|
||||
lCPts[1] = lCPts[2];
|
||||
lCPts[2] = vertices.front();
|
||||
|
||||
wnorm = face_normal;
|
||||
ang = VCalcAngle( lCPts[1], lCPts[0], lCPts[2] );
|
||||
wnorm.x *= ang;
|
||||
wnorm.y *= ang;
|
||||
wnorm.z *= ang;
|
||||
vnweight.push_back( wnorm );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void FACET::CalcVertexNormal( int aIndex, std::list< FACET* > &aFacetList, float aCreaseAngle )
|
||||
{
|
||||
if( vertices.size() < 3 )
|
||||
return;
|
||||
|
||||
if( norms.size() != vertices.size() )
|
||||
norms.resize( vertices.size() );
|
||||
|
||||
std::vector< int >::iterator sI = indices.begin();
|
||||
std::vector< int >::iterator eI = indices.end();
|
||||
int idx = 0;
|
||||
|
||||
WRLVEC3F fp[2]; // vectors to calculate facet angle
|
||||
fp[0].x = 0.0;
|
||||
fp[0].y = 0.0;
|
||||
fp[0].z = 0.0;
|
||||
|
||||
while( sI != eI )
|
||||
{
|
||||
if( *sI == aIndex )
|
||||
{
|
||||
if( vnweight.size() != vertices.size() )
|
||||
CalcFaceNormal();
|
||||
|
||||
// first set the default (weighted) normal value
|
||||
norms[idx] = vnweight[idx];
|
||||
|
||||
// iterate over adjacent facets
|
||||
std::list< FACET* >::iterator sF = aFacetList.begin();
|
||||
std::list< FACET* >::iterator eF = aFacetList.end();
|
||||
|
||||
while( sF != eF )
|
||||
{
|
||||
if( this == *sF )
|
||||
{
|
||||
++sF;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check the create angle limit
|
||||
(*sF)->GetFaceNormal( fp[1] );
|
||||
|
||||
if( aCreaseAngle >= VCalcAngle( fp[0], face_normal, fp[1] ) )
|
||||
{
|
||||
if( GetWeightedNormal( aIndex, fp[1] ) )
|
||||
{
|
||||
norms[idx].x += fp[1].x;
|
||||
norms[idx].y += fp[1].y;
|
||||
norms[idx].z += fp[1].z;
|
||||
}
|
||||
}
|
||||
|
||||
++sF;
|
||||
}
|
||||
|
||||
// normalize the vector
|
||||
glm::vec3 tri = glm::dvec3( norms[idx].x, norms[idx].y, norms[idx].z );
|
||||
normalize( tri );
|
||||
norms[idx].x = tri.x;
|
||||
norms[idx].y = tri.y;
|
||||
norms[idx].z = tri.z;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
++idx;
|
||||
++sI;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool FACET::GetWeightedNormal( int aIndex, WRLVEC3F& aNorm )
|
||||
{
|
||||
// the default weighted normal shall have no effect even if accidentally included
|
||||
aNorm.x = 0.0;
|
||||
aNorm.y = 0.0;
|
||||
aNorm.z = 0.0;
|
||||
|
||||
if( vertices.size() < 3 )
|
||||
return false;
|
||||
|
||||
std::vector< int >::iterator sI = indices.begin();
|
||||
std::vector< int >::iterator eI = indices.end();
|
||||
int idx = 0;
|
||||
|
||||
while( sI != eI )
|
||||
{
|
||||
if( *sI == aIndex )
|
||||
{
|
||||
if( vnweight.size() != vertices.size() )
|
||||
CalcFaceNormal();
|
||||
|
||||
aNorm = vnweight[idx];
|
||||
return true;
|
||||
}
|
||||
|
||||
++idx;
|
||||
++sI;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool FACET::GetFaceNormal( WRLVEC3F& aNorm )
|
||||
{
|
||||
aNorm.x = 0.0;
|
||||
aNorm.y = 0.0;
|
||||
aNorm.z = 0.0;
|
||||
|
||||
if( vertices.size() < 3 )
|
||||
return false;
|
||||
|
||||
if( vnweight.size() != vertices.size() )
|
||||
CalcFaceNormal();
|
||||
|
||||
aNorm = face_normal;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FACET::GetData( std::vector< WRLVEC3F >& aVertexList, std::vector< WRLVEC3F >& aNormalsList,
|
||||
std::vector< SGCOLOR >& aColorsList, WRL1_ORDER aVertexOrder )
|
||||
{
|
||||
// if no normals are calculated we simply return
|
||||
if( norms.empty() )
|
||||
return false;
|
||||
|
||||
// the output must always be triangle sets in order to conform to the
|
||||
// requirements of the SG* classes
|
||||
int idx[3];
|
||||
|
||||
idx[0] = 0;
|
||||
idx[1] = 1;
|
||||
idx[2] = 2;
|
||||
WRLVEC3F tnorm;
|
||||
|
||||
if( aVertexOrder != ORD_CLOCKWISE )
|
||||
{
|
||||
aVertexList.push_back( vertices[idx[0]] );
|
||||
aVertexList.push_back( vertices[idx[1]] );
|
||||
aVertexList.push_back( vertices[idx[2]] );
|
||||
|
||||
aNormalsList.push_back( norms[idx[0]] );
|
||||
aNormalsList.push_back( norms[idx[1]] );
|
||||
aNormalsList.push_back( norms[idx[2]] );
|
||||
}
|
||||
|
||||
if( aVertexOrder != ORD_CCW )
|
||||
{
|
||||
aVertexList.push_back( vertices[idx[0]] );
|
||||
aVertexList.push_back( vertices[idx[2]] );
|
||||
aVertexList.push_back( vertices[idx[1]] );
|
||||
|
||||
tnorm = norms[idx[0]];
|
||||
tnorm.x = -tnorm.x;
|
||||
tnorm.y = -tnorm.y;
|
||||
tnorm.z = -tnorm.z;
|
||||
aNormalsList.push_back( tnorm );
|
||||
|
||||
tnorm = norms[idx[2]];
|
||||
tnorm.x = -tnorm.x;
|
||||
tnorm.y = -tnorm.y;
|
||||
tnorm.z = -tnorm.z;
|
||||
aNormalsList.push_back( tnorm );
|
||||
|
||||
tnorm = norms[idx[1]];
|
||||
tnorm.x = -tnorm.x;
|
||||
tnorm.y = -tnorm.y;
|
||||
tnorm.z = -tnorm.z;
|
||||
aNormalsList.push_back( tnorm );
|
||||
}
|
||||
|
||||
bool hasColor;
|
||||
bool perVC; // per-vertex colors?
|
||||
|
||||
if( !colors.empty() )
|
||||
{
|
||||
hasColor = true;
|
||||
|
||||
if( colors.size() >= vertices.size() )
|
||||
perVC = true;
|
||||
|
||||
if( perVC )
|
||||
{
|
||||
if( aVertexOrder != ORD_CLOCKWISE )
|
||||
{
|
||||
aColorsList.push_back( colors[idx[0]] );
|
||||
aColorsList.push_back( colors[idx[1]] );
|
||||
aColorsList.push_back( colors[idx[2]] );
|
||||
}
|
||||
|
||||
if( aVertexOrder != ORD_CCW )
|
||||
{
|
||||
aColorsList.push_back( colors[idx[0]] );
|
||||
aColorsList.push_back( colors[idx[2]] );
|
||||
aColorsList.push_back( colors[idx[1]] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aVertexOrder != ORD_CLOCKWISE )
|
||||
{
|
||||
aColorsList.push_back( colors[0] );
|
||||
aColorsList.push_back( colors[0] );
|
||||
aColorsList.push_back( colors[0] );
|
||||
}
|
||||
|
||||
if( aVertexOrder != ORD_CCW )
|
||||
{
|
||||
aColorsList.push_back( colors[0] );
|
||||
aColorsList.push_back( colors[0] );
|
||||
aColorsList.push_back( colors[0] );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hasColor = false;
|
||||
}
|
||||
|
||||
int lim = (int) vertices.size() - 1;
|
||||
|
||||
while( idx[2] < lim )
|
||||
{
|
||||
idx[1] = idx[2];
|
||||
++idx[2];
|
||||
|
||||
if( aVertexOrder != ORD_CLOCKWISE )
|
||||
{
|
||||
aVertexList.push_back( vertices[idx[0]] );
|
||||
aVertexList.push_back( vertices[idx[1]] );
|
||||
aVertexList.push_back( vertices[idx[2]] );
|
||||
|
||||
aNormalsList.push_back( norms[idx[0]] );
|
||||
aNormalsList.push_back( norms[idx[1]] );
|
||||
aNormalsList.push_back( norms[idx[2]] );
|
||||
}
|
||||
|
||||
if( aVertexOrder != ORD_CCW )
|
||||
{
|
||||
aVertexList.push_back( vertices[idx[0]] );
|
||||
aVertexList.push_back( vertices[idx[2]] );
|
||||
aVertexList.push_back( vertices[idx[1]] );
|
||||
|
||||
tnorm = norms[idx[0]];
|
||||
tnorm.x = -tnorm.x;
|
||||
tnorm.y = -tnorm.y;
|
||||
tnorm.z = -tnorm.z;
|
||||
aNormalsList.push_back( tnorm );
|
||||
|
||||
tnorm = norms[idx[2]];
|
||||
tnorm.x = -tnorm.x;
|
||||
tnorm.y = -tnorm.y;
|
||||
tnorm.z = -tnorm.z;
|
||||
aNormalsList.push_back( tnorm );
|
||||
|
||||
tnorm = norms[idx[1]];
|
||||
tnorm.x = -tnorm.x;
|
||||
tnorm.y = -tnorm.y;
|
||||
tnorm.z = -tnorm.z;
|
||||
aNormalsList.push_back( tnorm );
|
||||
}
|
||||
|
||||
if( hasColor )
|
||||
{
|
||||
if( perVC )
|
||||
{
|
||||
if( aVertexOrder != ORD_CLOCKWISE )
|
||||
{
|
||||
aColorsList.push_back( colors[idx[0]] );
|
||||
aColorsList.push_back( colors[idx[1]] );
|
||||
aColorsList.push_back( colors[idx[2]] );
|
||||
}
|
||||
|
||||
if( aVertexOrder != ORD_CCW )
|
||||
{
|
||||
aColorsList.push_back( colors[idx[0]] );
|
||||
aColorsList.push_back( colors[idx[2]] );
|
||||
aColorsList.push_back( colors[idx[1]] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aVertexOrder != ORD_CLOCKWISE )
|
||||
{
|
||||
aColorsList.push_back( colors[0] );
|
||||
aColorsList.push_back( colors[0] );
|
||||
aColorsList.push_back( colors[0] );
|
||||
}
|
||||
|
||||
if( aVertexOrder != ORD_CCW )
|
||||
{
|
||||
aColorsList.push_back( colors[0] );
|
||||
aColorsList.push_back( colors[0] );
|
||||
aColorsList.push_back( colors[0] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void FACET::CollectVertices( std::vector< std::list< FACET* > >& aFacetList )
|
||||
{
|
||||
// check if this facet may contribute anything at all
|
||||
if( vertices.size() < 3 )
|
||||
return;
|
||||
|
||||
// note: in principle this should never be invoked
|
||||
if( (maxIdx + 1) >= (int)aFacetList.size() )
|
||||
aFacetList.resize( maxIdx + 1 );
|
||||
|
||||
std::vector< int >::iterator sI = indices.begin();
|
||||
std::vector< int >::iterator eI = indices.end();
|
||||
|
||||
while( sI != eI )
|
||||
{
|
||||
aFacetList[*sI].push_back( this );
|
||||
++sI;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SHAPE::~SHAPE()
|
||||
{
|
||||
std::list< FACET* >::iterator sF = facets.begin();
|
||||
std::list< FACET* >::iterator eF = facets.end();
|
||||
|
||||
while( sF != eF )
|
||||
{
|
||||
delete *sF;
|
||||
++sF;
|
||||
}
|
||||
|
||||
facets.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
FACET* SHAPE::NewFacet()
|
||||
{
|
||||
FACET* fp = new FACET;
|
||||
facets.push_back( fp );
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SHAPE::CalcShape( SGNODE* aParent, SGNODE* aColor, WRL1_ORDER aVertexOrder,
|
||||
float aCreaseAngle )
|
||||
{
|
||||
if( facets.empty() || !facets.front()->HasMinPoints() )
|
||||
return NULL;
|
||||
|
||||
std::vector< std::list< FACET* > > flist;
|
||||
|
||||
// determine the max. index and size flist as appropriate
|
||||
std::list< FACET* >::iterator sF = facets.begin();
|
||||
std::list< FACET* >::iterator eF = facets.end();
|
||||
|
||||
int maxIdx = 0;
|
||||
int tmi;
|
||||
|
||||
while( sF != eF )
|
||||
{
|
||||
tmi = (*sF)->GetMaxIndex();
|
||||
|
||||
if( tmi > maxIdx )
|
||||
maxIdx = tmi;
|
||||
|
||||
++sF;
|
||||
}
|
||||
|
||||
++maxIdx;
|
||||
|
||||
if( maxIdx < 3 )
|
||||
return NULL;
|
||||
|
||||
flist.resize( maxIdx );
|
||||
|
||||
// create the lists of facets common to indices
|
||||
sF = facets.begin();
|
||||
|
||||
while( sF != eF )
|
||||
{
|
||||
(*sF)->CollectVertices( flist );
|
||||
++sF;
|
||||
}
|
||||
|
||||
// calculate the normals
|
||||
size_t vs = flist.size();
|
||||
|
||||
for( size_t i = 0; i < vs; ++i )
|
||||
{
|
||||
sF = flist[i].begin();
|
||||
eF = flist[i].end();
|
||||
|
||||
while( sF != eF )
|
||||
{
|
||||
(*sF)->CalcVertexNormal( i, flist[i], aCreaseAngle );
|
||||
++sF;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector< WRLVEC3F > vertices;
|
||||
std::vector< WRLVEC3F > normals;
|
||||
std::vector< SGCOLOR > colors;
|
||||
|
||||
// push the facet data to the final output list
|
||||
sF = facets.begin();
|
||||
eF = facets.end();
|
||||
|
||||
while( sF != eF )
|
||||
{
|
||||
(*sF)->GetData( vertices, normals, colors, aVertexOrder );
|
||||
++sF;
|
||||
}
|
||||
|
||||
flist.clear();
|
||||
|
||||
if( vertices.size() < 3 )
|
||||
return NULL;
|
||||
|
||||
IFSG_SHAPE shapeNode( aParent );
|
||||
|
||||
if( aColor )
|
||||
{
|
||||
if( NULL == S3D::GetSGNodeParent( aColor ) )
|
||||
shapeNode.AddChildNode( aColor );
|
||||
else
|
||||
shapeNode.AddRefNode( aColor );
|
||||
}
|
||||
|
||||
std::vector< SGPOINT > lCPts; // vertex points in SGPOINT (double) format
|
||||
std::vector< SGVECTOR > lCNorm; // per-vertex normals
|
||||
vs = vertices.size();
|
||||
|
||||
for( size_t i = 0; i < vs; ++i )
|
||||
{
|
||||
SGPOINT pt;
|
||||
pt.x = vertices[i].x;
|
||||
pt.y = vertices[i].y;
|
||||
pt.z = vertices[i].z;
|
||||
lCPts.push_back( pt );
|
||||
lCNorm.push_back( SGVECTOR( normals[i].x, normals[i].y, normals[i].z ) );
|
||||
}
|
||||
|
||||
vertices.clear();
|
||||
normals.clear();
|
||||
|
||||
IFSG_FACESET fsNode( shapeNode );
|
||||
IFSG_COORDS cpNode( fsNode );
|
||||
cpNode.SetCoordsList( lCPts.size(), &lCPts[0] );
|
||||
IFSG_COORDINDEX ciNode( fsNode );
|
||||
|
||||
for( int i = 0; i < (int)lCPts.size(); ++i )
|
||||
ciNode.AddIndex( i );
|
||||
|
||||
IFSG_NORMALS nmNode( fsNode );
|
||||
nmNode.SetNormalList( lCNorm.size(), &lCNorm[0] );
|
||||
|
||||
if( !colors.empty() )
|
||||
{
|
||||
IFSG_COLORS nmColor( fsNode );
|
||||
nmColor.SetColorList( colors.size(), &colors[0] );
|
||||
colors.clear();
|
||||
}
|
||||
|
||||
return fsNode.GetRawPtr();
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file wrlfacet.h
|
||||
* declares classes to help manage normals calculations from VRML files
|
||||
*/
|
||||
|
||||
|
||||
#ifndef WRLFACET_H
|
||||
#define WRLFACET_H
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include "wrltypes.h"
|
||||
#include "plugins/3dapi/ifsg_all.h"
|
||||
|
||||
|
||||
class SGNODE;
|
||||
|
||||
class FACET
|
||||
{
|
||||
private:
|
||||
std::vector< WRLVEC3F > vertices; // vertices of the facet
|
||||
std::vector< SGCOLOR > colors; // per-vertex/per-face color (if any)
|
||||
std::vector< int > indices; // index of each vertex
|
||||
|
||||
WRLVEC3F face_normal; // normal of this facet
|
||||
std::vector< WRLVEC3F > norms; // per-vertex normals
|
||||
std::vector< WRLVEC3F > vnweight; // angle weighted per vertex normal
|
||||
|
||||
int maxIdx; // maximum index used
|
||||
|
||||
public:
|
||||
FACET();
|
||||
|
||||
void Init();
|
||||
bool HasMinPoints();
|
||||
bool HasColors();
|
||||
|
||||
/**
|
||||
* Function AddVertex
|
||||
* adds the vertex and its associated index to the internal list
|
||||
* of polygon vertices
|
||||
*/
|
||||
void AddVertex( WRLVEC3F& aVertex, int aIndex );
|
||||
|
||||
/**
|
||||
* Function AddColor
|
||||
* adds the given RGB color to the internal list. For per-face
|
||||
* coloring only a single color needs to be specified; for a
|
||||
* per-vertex coloring the color must be specified for each
|
||||
* vertex
|
||||
*/
|
||||
void AddColor( const SGCOLOR& aColor );
|
||||
|
||||
/**
|
||||
* Function CalcFaceNormal
|
||||
* calculates the normal to the facet assuming a CCW orientation
|
||||
* and performs the calculation of the angle weighted vertex normals
|
||||
*/
|
||||
void CalcFaceNormal();
|
||||
|
||||
/**
|
||||
* Function CalcVertexNormal
|
||||
* calculates the weighted normal for the given vertex
|
||||
*
|
||||
* @param aIndex is the VRML file's Vertex Index for the vertex to be processed
|
||||
* @param aFacetList is the list of all faces which share this vertex
|
||||
*/
|
||||
void CalcVertexNormal( int aIndex, std::list< FACET* >& aFacetList, float aCreaseAngle );
|
||||
|
||||
/**
|
||||
* Function GetWeightedNormal
|
||||
* retrieves the angle weighted normal for the given vertex index
|
||||
*
|
||||
* @param aIndex is the VRML file's Vertex Index for the vertex to be processed
|
||||
* @param aNorm will hold the result
|
||||
*/
|
||||
bool GetWeightedNormal( int aIndex, WRLVEC3F& aNorm );
|
||||
|
||||
/**
|
||||
* Function GetFaceNormal
|
||||
* retrieves the normal for this facet
|
||||
*
|
||||
* @param aNorm will hold the result
|
||||
*/
|
||||
bool GetFaceNormal( WRLVEC3F& aNorm );
|
||||
|
||||
/**
|
||||
* Function GetData
|
||||
* packages the internal data as triangles with corresponding per-vertex normals
|
||||
*
|
||||
* @param aVertexList is the list of vertices to add to
|
||||
* @param aNormalsList is the list of per-vertex normals to add to
|
||||
* @param aColorsList is the list of per-vertex colors (if any) to add to
|
||||
* @param aVertexOrder informs the function of the vertex winding order
|
||||
*/
|
||||
bool GetData( std::vector< WRLVEC3F >& aVertexList, std::vector< WRLVEC3F >& aNormalsList,
|
||||
std::vector< SGCOLOR >& aColorsList, WRL1_ORDER aVertexOrder );
|
||||
|
||||
int GetMaxIndex()
|
||||
{
|
||||
return maxIdx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function CollectVertices
|
||||
* adds a pointer to this object at each position within aFacetList
|
||||
* referenced by the internal vertex indices
|
||||
*/
|
||||
void CollectVertices( std::vector< std::list< FACET* > >& aFacetList );
|
||||
};
|
||||
|
||||
|
||||
class SHAPE
|
||||
{
|
||||
std::list< FACET* > facets;
|
||||
|
||||
public:
|
||||
~SHAPE();
|
||||
|
||||
FACET* NewFacet();
|
||||
SGNODE* CalcShape( SGNODE* aParent, SGNODE* aColor, WRL1_ORDER aVertexOrder,
|
||||
float aCreaseAngle = 0.5235983 );
|
||||
};
|
||||
|
||||
#endif // WRLFACET_H
|
Loading…
Reference in New Issue