diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2026-08-24 11:16:07 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2026-08-24 11:16:07 +0200 |
| commit | c068f22329d5cc722622a2183bbb22eef2093df7 (patch) | |
| tree | 12d56c1aede67988a55e241364606bfbb4dba933 /tool_src/BspLib/BRep.cpp | |
| download | openparsec-main.tar.xz openparsec-main.zip | |
Diffstat (limited to 'tool_src/BspLib/BRep.cpp')
| -rw-r--r-- | tool_src/BspLib/BRep.cpp | 1514 |
1 files changed, 1514 insertions, 0 deletions
diff --git a/tool_src/BspLib/BRep.cpp b/tool_src/BspLib/BRep.cpp new file mode 100644 index 0000000..1b4a49a --- /dev/null +++ b/tool_src/BspLib/BRep.cpp @@ -0,0 +1,1514 @@ +//----------------------------------------------------------------------------- +// BSPLIB MODULE: BRep.cpp +// +// Copyright (c) 1997-1998 by Markus Hadwiger +// All Rights Reserved. +//----------------------------------------------------------------------------- + +// bsplib headers +#include "BRep.h" + +// qvlib headers +#include <QvCoordinate3.h> +#include <QvMaterial.h> +#include <QvMaterialBinding.h> +#include <QvMatrixTransform.h> +#include <QvNormal.h> +#include <QvNormalBinding.h> +#include <QvRotation.h> +#include <QvScale.h> +#include <QvShapeHints.h> +#include <QvTexture2.h> +#include <QvTextureCoordinate2.h> +#include <QvTexture2Transform.h> +#include <QvTranslation.h> +#include <QvTransform.h> + +#ifdef USE_JPEG_LIBRARY +#include <jpeglib.h> +#endif + +BSPLIB_NAMESPACE_BEGIN + + +struct tga_header_s { + + byte IDLength; + byte CMapType; + byte ImgType; + byte CMapStartLo; + byte CMapStartHi; + byte CMapLengthLo; + byte CMapLengthHi; + byte CMapDepth; + byte XOffSetLo; + byte XOffSetHi; + byte YOffSetLo; + byte YOffSetHi; + byte WidthLo; + byte WidthHi; + byte HeightLo; + byte HeightHi; + byte PixelDepth; + byte ImageDescriptor; +}; + + +// constructor for b-rep object ----------------------------------------------- +// +BRep::BRep( QvState *state ) +{ + // save pointer to state + m_state = state; + + // create new object and insert into list + m_baseobject = m_state->vrmlfile_base->getObjectList().CreateNewObject(); +} + + +// fetch pointer to Coordinate3 array and length ------------------------------ +// +float *BRep::FetchCoordinate3State( int &num ) +{ + num = 0; + float *coarray = NULL; + QvElement *elt = m_state->getTopElement( QvState::Coordinate3Index ); + + if ( elt != NULL ) { + QvCoordinate3 *c3 = (QvCoordinate3 *) elt->data; + num = c3->point.num; + coarray = c3->point.values; + } + + return coarray; +} + + +// fetch pointer to texture coordinates array and length ---------------------- +// +float *BRep::FetchTextureCoordinate2State( int &num ) +{ + num = 0; + float *coarray = NULL; + QvElement *elt = m_state->getTopElement( QvState::TextureCoordinate2Index ); + + if ( elt != NULL ) { + QvTextureCoordinate2 *tc = (QvTextureCoordinate2 *) elt->data; + num = tc->point.num; + coarray = tc->point.values; + } + + return coarray; +} + + +// fetch pointer to normals array and length ---------------------------------- +// +float *BRep::FetchNormalState( int &num ) +{ + num = 0; + float *coarray = NULL; + QvElement *elt = m_state->getTopElement( QvState::NormalIndex ); + + if ( elt != NULL ) { + QvNormal *nml = (QvNormal *) elt->data; + num = nml->vector.num; + coarray = nml->vector.values; + } + + return coarray; +} + + +// accumulate current transformation stack and init Transform3 object --------- +// +void BRep::FetchTransformationState( Transform3& trafo ) +{ + trafo.LoadIdentity(); + + QvElement *trafoelt = NULL; + trafoelt = m_state->getTopElement( QvState::TransformationIndex ); + for ( ; trafoelt; trafoelt = trafoelt->next ) { + + if ( trafoelt->type == QvElement::Translation ) { + QvTranslation *tnode = (QvTranslation *) trafoelt->data; + trafo.Translate( tnode->translation.value[ 0 ], + tnode->translation.value[ 1 ], + tnode->translation.value[ 2 ] ); + } else if ( trafoelt->type == QvElement::Rotation ) { + QvRotation *tnode = (QvRotation *) trafoelt->data; + trafo.Rotate( tnode->rotation.angle, + tnode->rotation.axis[ 0 ], + tnode->rotation.axis[ 1 ], + tnode->rotation.axis[ 2 ] ); + } else if ( trafoelt->type == QvElement::Scale ) { + QvScale *tnode = (QvScale *) trafoelt->data; + trafo.Scale( tnode->scaleFactor.value[ 0 ], + tnode->scaleFactor.value[ 1 ], + tnode->scaleFactor.value[ 2 ] ); + } else if ( trafoelt->type == QvElement::Transform ) { + QvTransform *tnode = (QvTransform *) trafoelt->data; + trafo.Translate( -tnode->center.value[ 0 ], + -tnode->center.value[ 1 ], + -tnode->center.value[ 2 ] ); + trafo.Rotate( -tnode->scaleOrientation.angle, + tnode->scaleOrientation.axis[ 0 ], + tnode->scaleOrientation.axis[ 1 ], + tnode->scaleOrientation.axis[ 2 ] ); + trafo.Scale( tnode->scaleFactor.value[ 0 ], + tnode->scaleFactor.value[ 1 ], + tnode->scaleFactor.value[ 2 ] ); + trafo.Rotate( tnode->scaleOrientation.angle, + tnode->scaleOrientation.axis[ 0 ], + tnode->scaleOrientation.axis[ 1 ], + tnode->scaleOrientation.axis[ 2 ] ); + trafo.Rotate( tnode->rotation.angle, + tnode->rotation.axis[ 0 ], + tnode->rotation.axis[ 1 ], + tnode->rotation.axis[ 2 ] ); + trafo.Translate( tnode->center.value[ 0 ], + tnode->center.value[ 1 ], + tnode->center.value[ 2 ] ); + trafo.Translate( tnode->translation.value[ 0 ], + tnode->translation.value[ 1 ], + tnode->translation.value[ 2 ] ); + } else if ( trafoelt->type == QvElement::MatrixTransform ) { + QvMatrixTransform *tnode = (QvMatrixTransform *) trafoelt->data; + Transform3 tmat( (const float(*)[4]) tnode->matrix.value ); + trafo.Concat( tmat ); + } + } +} + + +// accumulate current texture transformation stack into Transform2 object ----- +// +void BRep::FetchTextureTransformationState( Transform2& trafo ) +{ + trafo.LoadIdentity(); + + QvElement *trafoelt = m_state->getTopElement( QvState::Texture2TransformationIndex ); + for ( ; trafoelt; trafoelt = trafoelt->next ) { + + if ( trafoelt->type == QvElement::Unknown /*Transform*/ ) { + + //NOTE: + // well, yes. QvLib really uses QvElement::Unknown as type + // for texture transformations!! + + QvTexture2Transform *tnode = (QvTexture2Transform *) trafoelt->data; + trafo.Translate( -tnode->center.value[ 0 ], + -tnode->center.value[ 1 ] ); + trafo.Scale( tnode->scaleFactor.value[ 0 ], + tnode->scaleFactor.value[ 1 ] ); + trafo.Rotate( tnode->rotation.value ); + trafo.Translate( tnode->center.value[ 0 ], + tnode->center.value[ 1 ] ); + trafo.Translate( tnode->translation.value[ 0 ], + tnode->translation.value[ 1 ] ); + } + } +} + + +// check current texture state; create new texture if necessary --------------- +// +Texture *BRep::CheckTexture2State() +{ + QvElement *elt = m_state->getTopElement( QvState::Texture2Index ); + + if ( elt == NULL ) + return NULL; + + // fetch texture node + QvTexture2 *tex = (QvTexture2 *) elt->data; + const char *texfilename = tex->filename.value.getString(); + + if ( ( texfilename == NULL ) || ( *texfilename == 0 ) ) + return NULL; + + // check if texture already exists + TextureChunk& texlist = m_baseobject->getTextureList(); + for ( int i = 0; i < texlist.getNumElements(); i++ ) { + if ( strcmp( texlist[ i ].getFile(), texfilename ) == 0 ) + return &texlist[ i ]; + } + + // default texture width and height are 1, yielding texture + // coordinates between 0.0 and 1.0 when multiplied by vrml + // texture coordinates later on. + int width = 1; + int height = 1; + + // try to open texture file if it is in 3df format to read actual width and height + int namelen = strlen( texfilename ); + if ( ( namelen > 4 ) && ( strcmp( texfilename + namelen - 4, ".3df" ) == 0 ) ) { + + // open 3df file + FILE *fp = fopen( texfilename, "rb" ); + if ( fp != NULL ) { + + // header fields + char version[ 7 ]; + char formatspec[ 11 ]; + int lodsmall; + int lodlarge; + int aspectw; + int aspecth; + + // scan out header + if ( fscanf( fp, "3df v%6s %10s lod range: %i %i aspect ratio: %i %i", + version, formatspec, &lodsmall, &lodlarge, &aspectw, &aspecth ) == 6 ) { + + fclose( fp ); + + version[ 6 ] = 0; + formatspec[ 10 ] = 0; + + // determine geometry + int aindx = ( aspectw << 4 ) | aspecth; + switch ( aindx ) { + + case 0x81 : + width = lodlarge; + height = lodlarge / 8; + break; + + case 0x41 : + width = lodlarge; + height = lodlarge / 4; + break; + + case 0x21 : + width = lodlarge; + height = lodlarge / 2; + break; + + case 0x11 : + width = lodlarge; + height = lodlarge; + break; + + case 0x12 : + width = lodlarge / 2; + height = lodlarge; + break; + + case 0x14 : + width = lodlarge / 4; + height = lodlarge; + break; + + case 0x18 : + width = lodlarge / 8; + height = lodlarge; + break; + + default : + break; + } + } + } + + } else if ( ( namelen > 4 ) && ( strcmp( texfilename + namelen - 4, ".tga" ) == 0 ) ) { + + // try to get width/height from .tga header + + FILE *fp = fopen( texfilename, "rb" ); + if ( fp != NULL ) { + + tga_header_s header; + + // read header + if ( fread( &header, 1, sizeof( tga_header_s ), fp ) == sizeof( tga_header_s ) ) { + + width = ( header.WidthHi << 8 ) | header.WidthLo; + height = ( header.HeightHi << 8 ) | header.HeightLo; + } + + fclose( fp ); + } + + } else if ( ( namelen > 4 ) && ( strcmp( texfilename + namelen - 4, ".jpg" ) == 0 ) ) { + +#ifdef USE_JPEG_LIBRARY + + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + + FILE *fp = fopen( texfilename, "rb" ); + if ( fp != NULL ) { + + // specify error handler + cinfo.err = jpeg_std_error( &jerr ); + + // init decompressor + jpeg_create_decompress( &cinfo ); + + // specify the source for the compressed data + jpeg_stdio_src( &cinfo, fp ); + + // read jpeg header + jpeg_read_header( &cinfo, TRUE ); + + // de-init decompressor + jpeg_destroy_decompress( &cinfo ); + + fclose( fp ); + + width = cinfo.image_width; + height = cinfo.image_height; + } +#else + + fflush( stdout ); + fprintf( stderr, "\nJPEG files are not supported by this version of makeodt.\n" ); + fprintf( stderr, "If you need JPEG support, you can enable -DUSE_JPEG_LIBRARY\n" ); + fprintf( stderr, "in the BspLib Makefile and recompile BspLib and makeodt.\n" ); + fprintf( stderr, "This will require a working version of libjpeg 6.x\n" ); + fprintf( stderr, "to be installed on your system.\n\n" ); + + exit( EXIT_FAILURE ); +#endif + + } + + Texture temptex( width, height ); + temptex.setName( texfilename ); + temptex.setFile( texfilename ); + texlist.AddElement( temptex ); + + return &texlist[ texlist.getNumElements() - 1 ]; +} + + +// retrieve material corresponding to specified index ------------------------- +// +int BRep::FetchMaterialState( Material& mat, int indx ) +{ + QvElement *elt = m_state->getTopElement( QvState::MaterialIndex ); + + if ( elt == NULL ) + return 0; + + // fetch material node + QvMaterial *m = (QvMaterial *) elt->data; + + // determine period for binding + int ambnum = m->ambientColor.num; + int difnum = m->diffuseColor.num; + int spcnum = m->specularColor.num; + int eminum = m->emissiveColor.num; + int shinum = m->shininess.num; + int tranum = m->transparency.num; + int period = ambnum; + if ( difnum > period ) period = difnum; + if ( spcnum > period ) period = spcnum; + if ( eminum > period ) period = eminum; + if ( shinum > period ) period = shinum; + if ( tranum > period ) period = tranum; + + ColorRGBA col; + col.A = 255; + + int modindx = indx % period; + int readindx = ( modindx < ambnum ) ? modindx : ambnum - 1; + col.R = (byte)( m->ambientColor.values[ readindx * 3 + 0 ] * 255 ); + col.G = (byte)( m->ambientColor.values[ readindx * 3 + 1 ] * 255 ); + col.B = (byte)( m->ambientColor.values[ readindx * 3 + 2 ] * 255 ); + mat.setAmbientColor( col ); + + readindx = ( modindx < difnum ) ? modindx : difnum - 1; + col.R = (byte)( m->diffuseColor.values[ readindx * 3 + 0 ] * 255 ); + col.G = (byte)( m->diffuseColor.values[ readindx * 3 + 1 ] * 255 ); + col.B = (byte)( m->diffuseColor.values[ readindx * 3 + 2 ] * 255 ); + mat.setDiffuseColor( col ); + + readindx = ( modindx < spcnum ) ? modindx : spcnum - 1; + col.R = (byte)( m->specularColor.values[ readindx * 3 + 0 ] * 255 ); + col.G = (byte)( m->specularColor.values[ readindx * 3 + 1 ] * 255 ); + col.B = (byte)( m->specularColor.values[ readindx * 3 + 2 ] * 255 ); + mat.setSpecularColor( col ); + + readindx = ( modindx < eminum ) ? modindx : eminum - 1; + col.R = (byte)( m->emissiveColor.values[ readindx * 3 + 0 ] * 255 ); + col.G = (byte)( m->emissiveColor.values[ readindx * 3 + 1 ] * 255 ); + col.B = (byte)( m->emissiveColor.values[ readindx * 3 + 2 ] * 255 ); + mat.setEmissiveColor( col ); + + readindx = ( modindx < shinum ) ? modindx : shinum - 1; + mat.setShininess( m->shininess.values[ readindx ] ); + + readindx = ( modindx < tranum ) ? modindx : tranum - 1; + mat.setTransparency( m->transparency.values[ readindx ] ); + + return 1; +} + + +// fetch material binding ----------------------------------------------------- +// +void BRep::FetchMaterialBindingState( int& binding ) +{ + binding = QvMaterialBinding::DEFAULT; + QvElement *elt = m_state->getTopElement( QvState::MaterialBindingIndex ); + if ( elt != NULL ) { + QvMaterialBinding *mb = (QvMaterialBinding *) elt->data; + binding = mb->value.value; + } +} + + +// fetch normal binding ------------------------------------------------------- +// +void BRep::FetchNormalBindingState( int& binding ) +{ + binding = QvMaterialBinding::DEFAULT; + QvElement *elt = m_state->getTopElement( QvState::NormalBindingIndex ); + if ( elt != NULL ) { + QvNormalBinding *mb = (QvNormalBinding *) elt->data; + binding = mb->value.value; + } +} + + +// fetch shape hints information into static members -------------------------- +// +void BRep::FetchShapeHintsState() +{ + QvElement *elt = m_state->getTopElement( QvState::ShapeHintsIndex ); + if ( elt != NULL ) { + QvShapeHints *sh = (QvShapeHints *) elt->data; + shapehint_vertexOrdering = sh->vertexOrdering.value; + shapehint_shapeType = sh->shapeType.value; + shapehint_faceType = sh->faceType.value; + shapehint_creaseAngle = sh->creaseAngle.value; + } +} + + +// do b-rep construction post-processing -------------------------------------- +// +void BRep::PostProcessObject() +{ + VertexChunk& vtxlist = m_baseobject->getVertexList(); + + int numvtxs = vtxlist.getNumElements(); + if ( numvtxs > 0 ) { + + // apply transformation matrix + // otherwise bounding box will not be correct! + m_baseobject->ApplyTransformation(); + + // determine object bounding box + Vertex3 minvertex; + Vertex3 maxvertex; + m_baseobject->CalcBoundingBox( minvertex, maxvertex ); + + // prepend bounding box to list of scene object bounding boxes + m_state->vrmlfile_base->m_bboxlist = new BoundingBox( minvertex, maxvertex, m_state->vrmlfile_base->m_bboxlist ); + + // set actual vertex correspondences (needs to be done after transformation!) + FaceChunk& facelist = m_baseobject->getFaceList(); + for ( int i = 0; i < facelist.getNumElements(); i++ ) { + if ( facelist[ i ].FaceTexMapped() ) { + // retrieve fake vertex containing corresponding vertex indexes + Vertex2 fake; + fake = facelist[ i ].MapXY( 0 ); + // use vertex indexes to store actual correspondence coordinates + facelist[ i ].MapXY( 0 ).InitFromVertex3( vtxlist[ (int) fake.getX() ] ); + facelist[ i ].MapXY( 1 ).InitFromVertex3( vtxlist[ (int) fake.getY() ] ); + facelist[ i ].MapXY( 2 ).InitFromVertex3( vtxlist[ (int) fake.getW() ] ); + } + } + } + + m_baseobject->CheckParsedData(); +} + + +// construct b-rep from vrml sphere primitive --------------------------------- +// +void BRep::BuildFromSpherePrimitive( const QvSphere& node ) +{ + // base object + VertexChunk& vtxlist = m_baseobject->getVertexList(); + FaceChunk& facelist = m_baseobject->getFaceList(); + PolygonList& polylist = m_baseobject->getPolygonList(); + + // set possible transformation as object's local transformation + Transform3 trafo; + FetchTransformationState( trafo ); + m_baseobject->setObjectTransformation( trafo ); + + int slices4 = tessellation_slices; + + double radius = node.radius.value; + + double phi = 0.0; + double phiinc = 1.570796327 / (double) slices4; // PI/2 + + // create circumference vertices + Vector3 basevec( radius, 0.0, 0.0 ); + Vector3 scancircle( basevec ); + int i = 0; + for ( i = 0; i < slices4; i++ ) { + vtxlist.AddVertex( scancircle ); + phi += phiinc; + double cosphi = cos( phi ); + double sinphi = sin( phi ); + double nextx = cosphi * basevec.getX() + sinphi * basevec.getZ(); + double nextz = sinphi * basevec.getX() + cosphi * basevec.getZ(); + scancircle.setX( nextx ); + scancircle.setZ( -nextz ); + } + for ( i = 0; i < slices4; i++ ) { + Vertex3 nv; + nv.setX( vtxlist[ i ].getZ() ); + nv.setY( vtxlist[ i ].getY() ); + nv.setZ( -vtxlist[ i ].getX() ); + vtxlist.AddVertex( nv ); + } + for ( i = 0; i < slices4; i++ ) { + Vertex3 nv; + nv.setX( -vtxlist[ i ].getX() ); + nv.setY( vtxlist[ i ].getY() ); + nv.setZ( -vtxlist[ i ].getZ() ); + vtxlist.AddVertex( nv ); + } + for ( i = 0; i < slices4; i++ ) { + Vertex3 nv; + nv.setX( -vtxlist[ i ].getZ() ); + nv.setY( vtxlist[ i ].getY() ); + nv.setZ( vtxlist[ i ].getX() ); + vtxlist.AddVertex( nv ); + } + + // create northern hemisphere + basevec = Vector3( radius, 0.0, 0.0 ); + phi = 0.0; + for ( i = 1; i < slices4; i++ ) { + phi += phiinc; + double cosphi = cos( phi ); + double sinphi = sin( phi ); + double nextx = cosphi * basevec.getX() - sinphi * basevec.getY(); + double nexty = sinphi * basevec.getX() + cosphi * basevec.getY(); + double rfac = nextx / radius; + for ( int j = 0; j < slices4 * 4; j++ ) { + Vertex3 nv; + nv.setX( vtxlist[ j ].getX() * rfac ); + nv.setY( nexty ); + nv.setZ( vtxlist[ j ].getZ() * rfac ); + vtxlist.AddVertex( nv ); + } + } + + // create southern hemisphere + basevec = Vector3( radius, 0.0, 0.0 ); + phi = 0.0; + for ( i = 1; i < slices4; i++ ) { + phi += phiinc; + double cosphi = cos( phi ); + double sinphi = sin( phi ); + double nextx = cosphi * basevec.getX() - sinphi * basevec.getY(); + double nexty = sinphi * basevec.getX() + cosphi * basevec.getY(); + double rfac = nextx / radius; + for ( int j = 0; j < slices4 * 4; j++ ) { + Vertex3 nv; + nv.setX( vtxlist[ j ].getX() * rfac ); + nv.setY( -nexty ); + nv.setZ( vtxlist[ j ].getZ() * rfac ); + vtxlist.AddVertex( nv ); + } + } + + // create pole vertices + int p1indx = vtxlist.AddVertex( Vertex3( 0.0, radius, 0.0 ) ); + int p2indx = vtxlist.AddVertex( Vertex3( 0.0, -radius, 0.0 ) ); + + // create polygons for side + int faceid = 0; + int j = 0; + for ( j = 0; j < slices4 - 1; j++ ) { + for ( i = 0; i < slices4 * 4 - 1; i++ ) { + // create side polygon + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( i + j * slices4 * 4 ); + sidepoly->AppendNewVIndx( i + ( j + 1 ) * slices4 * 4 ); + sidepoly->AppendNewVIndx( i + ( j + 1 ) * slices4 * 4 + 1 ); + sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( i + ( j + 1 ) * slices4 * 4 + 1 ); + sidepoly->AppendNewVIndx( i + j * slices4 * 4 + 1 ); + sidepoly->AppendNewVIndx( i + j * slices4 * 4 ); + } + + // create last side polygon + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( slices4 * 4 - 1 + j * slices4 * 4 ); + sidepoly->AppendNewVIndx( slices4 * 4 - 1 + ( j + 1 ) * slices4 * 4 ); + sidepoly->AppendNewVIndx( ( j + 1 ) * slices4 * 4 ); + sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( ( j + 1 ) * slices4 * 4 ); + sidepoly->AppendNewVIndx( j * slices4 * 4 ); + sidepoly->AppendNewVIndx( slices4 * 4 - 1 + j * slices4 * 4 ); + } + + for ( i = 0; i < slices4 * 4 - 1; i++ ) { + // create side polygon + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( i ); + sidepoly->AppendNewVIndx( i + 1 ); + sidepoly->AppendNewVIndx( i + slices4 * slices4 * 4 + 1 ); + sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( i + slices4 * slices4 * 4 + 1 ); + sidepoly->AppendNewVIndx( i + slices4 * slices4 * 4 ); + sidepoly->AppendNewVIndx( i ); + } + + // create last side polygon + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( slices4 * 4 - 1 ); + sidepoly->AppendNewVIndx( 0 ); + sidepoly->AppendNewVIndx( slices4 * slices4 * 4 ); + sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( slices4 * slices4 * 4 ); + sidepoly->AppendNewVIndx( slices4 * 4 - 1 + slices4 * slices4 * 4 ); + sidepoly->AppendNewVIndx( slices4 * 4 - 1 ); + + + for ( j = slices4; j < 2 * slices4 - 2; j++ ) { + for ( i = 0; i < slices4 * 4 - 1; i++ ) { + // create side polygon + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( i + j * slices4 * 4 ); + sidepoly->AppendNewVIndx( i + j * slices4 * 4 + 1 ); + sidepoly->AppendNewVIndx( i + ( j + 1 ) * slices4 * 4 + 1 ); + sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( i + ( j + 1 ) * slices4 * 4 + 1 ); + sidepoly->AppendNewVIndx( i + ( j + 1 ) * slices4 * 4 ); + sidepoly->AppendNewVIndx( i + j * slices4 * 4 ); + } + + // create last side polygon + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( slices4 * 4 - 1 + j * slices4 * 4 ); + sidepoly->AppendNewVIndx( j * slices4 * 4 ); + sidepoly->AppendNewVIndx( ( j + 1 ) * slices4 * 4 ); + sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( ( j + 1 ) * slices4 * 4 ); + sidepoly->AppendNewVIndx( slices4 * 4 - 1 + ( j + 1 ) * slices4 * 4 ); + sidepoly->AppendNewVIndx( slices4 * 4 - 1 + j * slices4 * 4 ); + } + + // create polygons for poles + for ( i = 0; i < slices4 * 4 - 1; i++ ) { + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( i + ( slices4 - 1 ) * slices4 * 4 + 1 ); + sidepoly->AppendNewVIndx( i + ( slices4 - 1 ) * slices4 * 4 ); + sidepoly->AppendNewVIndx( p1indx ); + } + { + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( ( slices4 - 1 ) * slices4 * 4 ); + sidepoly->AppendNewVIndx( slices4 * 4 - 1 + ( slices4 - 1 ) * slices4 * 4 ); + sidepoly->AppendNewVIndx( p1indx ); + } + for ( i = 0; i < slices4 * 4 - 1; i++ ) { + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( i + ( 2 * slices4 - 2 ) * slices4 * 4 ); + sidepoly->AppendNewVIndx( i + ( 2 * slices4 - 2 ) * slices4 * 4 + 1 ); + sidepoly->AppendNewVIndx( p2indx ); + } + { + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( faceid++ ); + sidepoly->AppendNewVIndx( slices4 * 4 - 1 + ( 2 * slices4 - 2 ) * slices4 * 4 ); + sidepoly->AppendNewVIndx( ( 2 * slices4 - 2 ) * slices4 * 4 ); + sidepoly->AppendNewVIndx( p2indx ); + } + + // the sphere primitive ignores the current material binding! + // therefore fetch only the first material + Material mat; + int matvalid = FetchMaterialState( mat, 0 ); + + // create faces + for ( i = 0; i < polylist.getNumElements(); i++ ) { + Face tempface; + if ( matvalid ) { + if ( use_material_spec ) { + // attach material specification + tempface.setShadingType( Face::material_shad ); + tempface.AttachMaterial( new Material( mat ) ); + } else { + // use gouraud_shad with diffuse color + tempface.setShadingType( Face::gouraud_shad ); + tempface.setFaceColor( mat.getDiffuseColor() ); + } + } else { + // use no_shad with index 255 if no material in state + tempface.setShadingType( Face::no_shad ); + tempface.setFaceColor( 255 ); + } + + tempface.setId( facelist.getNumElements() ); + facelist.AddElement( tempface ); + } + + // do post-processing after object has been built + PostProcessObject(); +} + + +// construct b-rep from vrml cone primitive ----------------------------------- +// +void BRep::BuildFromConePrimitive( const QvCone& node ) +{ + // base object + VertexChunk& vtxlist = m_baseobject->getVertexList(); + FaceChunk& facelist = m_baseobject->getFaceList(); + PolygonList& polylist = m_baseobject->getPolygonList(); + + // set possible transformation as object's local transformation + Transform3 trafo; + FetchTransformationState( trafo ); + m_baseobject->setObjectTransformation( trafo ); + + int slices4 = tessellation_slices; + + double radius = node.bottomRadius.value; + double top_y = node.height.value / 2; + double bottom_y = - node.height.value / 2; + + double phi = 0.0; + double phiinc = 1.570796327 / (double) slices4; // PI/2 + + // create bottom plate vertices + Vector3 basevec( radius, bottom_y, 0.0 ); + Vector3 scancircle( basevec ); + vtxlist.AddVertex( Vertex3( 0.0, bottom_y, 0.0 ) ); + int i = 0; + for ( i = 0; i < slices4; i++ ) { + vtxlist.AddVertex( scancircle ); + phi += phiinc; + double cosphi = cos( phi ); + double sinphi = sin( phi ); + double nextx = cosphi * basevec.getX() + sinphi * basevec.getZ(); + double nextz = sinphi * basevec.getX() + cosphi * basevec.getZ(); + scancircle.setX( nextx ); + scancircle.setZ( -nextz ); + } + for ( i = 0; i < slices4; i++ ) { + Vertex3 nv; + nv.setX( vtxlist[ i + 1 ].getZ() ); + nv.setY( vtxlist[ i + 1 ].getY() ); + nv.setZ( -vtxlist[ i + 1 ].getX() ); + vtxlist.AddVertex( nv ); + } + for ( i = 0; i < slices4; i++ ) { + Vertex3 nv; + nv.setX( -vtxlist[ i + 1 ].getX() ); + nv.setY( vtxlist[ i + 1 ].getY() ); + nv.setZ( -vtxlist[ i + 1 ].getZ() ); + vtxlist.AddVertex( nv ); + } + for ( i = 0; i < slices4; i++ ) { + Vertex3 nv; + nv.setX( -vtxlist[ i + 1 ].getZ() ); + nv.setY( vtxlist[ i + 1 ].getY() ); + nv.setZ( vtxlist[ i + 1 ].getX() ); + vtxlist.AddVertex( nv ); + } + + // create top vertex + vtxlist.AddVertex( Vertex3( 0.0, top_y, 0.0 ) ); + + // create polygons + for ( i = 0; i < slices4 * 4 - 1; i++ ) { + // create bottom plate polygon + Polygon *bottompoly = polylist.NewPolygon(); + bottompoly->setFaceId( 0 ); + bottompoly->AppendNewVIndx( i + 1 ); + bottompoly->AppendNewVIndx( i + 2 ); + bottompoly->AppendNewVIndx( 0 ); + // create side polygon + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( i + 1 ); + sidepoly->AppendNewVIndx( i + 1 ); + sidepoly->AppendNewVIndx( slices4 * 4 + 1 ); + sidepoly->AppendNewVIndx( i + 2 ); + } + + { + // create last bottom plate polygon + Polygon *bottompoly = polylist.NewPolygon(); + bottompoly->setFaceId( 0 ); + bottompoly->AppendNewVIndx( slices4 * 4 ); + bottompoly->AppendNewVIndx( 1 ); + bottompoly->AppendNewVIndx( 0 ); + // create last side polygon + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( slices4 * 4 ); + sidepoly->AppendNewVIndx( slices4 * 4 ); + sidepoly->AppendNewVIndx( slices4 * 4 + 1 ); + sidepoly->AppendNewVIndx( 1 ); + } + + // fetch the first two materials + Material mat1, mat2; + int mat1valid = FetchMaterialState( mat1, 0 ); + int mat2valid = FetchMaterialState( mat2, 1 ); + + // fetch the current material binding + int currentbinding; + FetchMaterialBindingState( currentbinding ); + + // apply material binding + if ( currentbinding != QvMaterialBinding::PER_PART && + currentbinding != QvMaterialBinding::PER_PART_INDEXED ) { + mat2 = mat1; + mat2valid = mat1valid; + } + + // create faces + for ( i = 0; i < slices4 * 4 + 1; i++ ) { + + //NOTE: + // there are ( slices4 * 4 + 1 ) faces. + // the bottom plate is a single face although it consists + // of ( slices4 * 4 ) polygons. + + Face tempface; + if ( mat1valid && mat2valid ) { + if ( use_material_spec ) { + // attach material specification + tempface.setShadingType( Face::material_shad ); + if ( i == 0 ) + tempface.AttachMaterial( new Material( mat2 ) ); + else + tempface.AttachMaterial( new Material( mat1 ) ); + } else { + // use gouraud_shad with diffuse color + tempface.setShadingType( Face::gouraud_shad ); + if ( i == 0 ) + tempface.setFaceColor( mat2.getDiffuseColor() ); + else + tempface.setFaceColor( mat1.getDiffuseColor() ); + } + } else { + // use no_shad with index 255 if no material in state + tempface.setShadingType( Face::no_shad ); + tempface.setFaceColor( 255 ); + } + + tempface.setId( facelist.getNumElements() ); + facelist.AddElement( tempface ); + } + + // do post-processing after object has been built + PostProcessObject(); +} + + +// construct b-rep from vrml cylinder primitive ------------------------------- +// +void BRep::BuildFromCylinderPrimitive( const QvCylinder& node ) +{ + // base object + VertexChunk& vtxlist = m_baseobject->getVertexList(); + FaceChunk& facelist = m_baseobject->getFaceList(); + PolygonList& polylist = m_baseobject->getPolygonList(); + + // set possible transformation as object's local transformation + Transform3 trafo; + FetchTransformationState( trafo ); + m_baseobject->setObjectTransformation( trafo ); + + int slices4 = tessellation_slices; + + double radius = node.radius.value; + double top_y = node.height.value / 2; + double bottom_y = - node.height.value / 2; + + double phi = 0.0; + double phiinc = 1.570796327 / (double) slices4; // PI/2 + + // create bottom plate vertices + Vector3 basevec( radius, bottom_y, 0.0 ); + Vector3 scancircle( basevec ); + vtxlist.AddVertex( Vertex3( 0.0, bottom_y, 0.0 ) ); + int i = 0; + for ( i = 0; i < slices4; i++ ) { + vtxlist.AddVertex( scancircle ); + phi += phiinc; + double cosphi = cos( phi ); + double sinphi = sin( phi ); + double nextx = cosphi * basevec.getX() + sinphi * basevec.getZ(); + double nextz = sinphi * basevec.getX() + cosphi * basevec.getZ(); + scancircle.setX( nextx ); + scancircle.setZ( -nextz ); + } + for ( i = 0; i < slices4; i++ ) { + Vertex3 nv; + nv.setX( vtxlist[ i + 1 ].getZ() ); + nv.setY( vtxlist[ i + 1 ].getY() ); + nv.setZ( -vtxlist[ i + 1 ].getX() ); + vtxlist.AddVertex( nv ); + } + for ( i = 0; i < slices4; i++ ) { + Vertex3 nv; + nv.setX( -vtxlist[ i + 1 ].getX() ); + nv.setY( vtxlist[ i + 1 ].getY() ); + nv.setZ( -vtxlist[ i + 1 ].getZ() ); + vtxlist.AddVertex( nv ); + } + for ( i = 0; i < slices4; i++ ) { + Vertex3 nv; + nv.setX( -vtxlist[ i + 1 ].getZ() ); + nv.setY( vtxlist[ i + 1 ].getY() ); + nv.setZ( vtxlist[ i + 1 ].getX() ); + vtxlist.AddVertex( nv ); + } + + // create top plate vertices + vtxlist.AddVertex( Vertex3( 0.0, top_y, 0.0 ) ); + for ( i = 0; i < slices4 * 4; i++ ) { + Vertex3 nv( vtxlist[ i + 1 ] ); + nv.setY( top_y ); + vtxlist.AddVertex( nv ); + } + + // create polygons + for ( i = 0; i < slices4 * 4 - 1; i++ ) { + // create bottom plate polygon + Polygon *bottompoly = polylist.NewPolygon(); + bottompoly->setFaceId( 0 ); + bottompoly->AppendNewVIndx( i + 1 ); + bottompoly->AppendNewVIndx( i + 2 ); + bottompoly->AppendNewVIndx( 0 ); + // create top plate polygon + Polygon *toppoly = polylist.NewPolygon(); + toppoly->setFaceId( 1 ); + toppoly->AppendNewVIndx( i + slices4 * 4 + 3 ); + toppoly->AppendNewVIndx( i + slices4 * 4 + 2 ); + toppoly->AppendNewVIndx( slices4 * 4 + 1 ); + // create side polygon + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( i + 2 ); + sidepoly->AppendNewVIndx( i + 1 ); + sidepoly->AppendNewVIndx( i + slices4 * 4 + 2 ); + sidepoly->AppendNewVIndx( i + slices4 * 4 + 3 ); + sidepoly->AppendNewVIndx( i + 2 ); + } + + { + // create last bottom plate polygon + Polygon *bottompoly = polylist.NewPolygon(); + bottompoly->setFaceId( 0 ); + bottompoly->AppendNewVIndx( slices4 * 4 ); + bottompoly->AppendNewVIndx( 1 ); + bottompoly->AppendNewVIndx( 0 ); + // create last top plate polygon + Polygon *toppoly = polylist.NewPolygon(); + toppoly->setFaceId( 1 ); + toppoly->AppendNewVIndx( slices4 * 4 + 2 ); + toppoly->AppendNewVIndx( 2 * slices4 * 4 + 1 ); + toppoly->AppendNewVIndx( slices4 * 4 + 1 ); + // create last side polygon + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->setFaceId( slices4 * 4 + 1 ); + sidepoly->AppendNewVIndx( slices4 * 4 ); + sidepoly->AppendNewVIndx( 2 * slices4 * 4 + 1 ); + sidepoly->AppendNewVIndx( slices4 * 4 + 2 ); + sidepoly->AppendNewVIndx( 1 ); + } + + // fetch the first three materials + Material mat1, mat2, mat3; + int mat1valid = FetchMaterialState( mat1, 0 ); + int mat2valid = FetchMaterialState( mat2, 1 ); + int mat3valid = FetchMaterialState( mat3, 2 ); + + // fetch the current material binding + int currentbinding; + FetchMaterialBindingState( currentbinding ); + + // apply material binding + if ( currentbinding != QvMaterialBinding::PER_PART && + currentbinding != QvMaterialBinding::PER_PART_INDEXED ) { + mat2 = mat1; + mat3 = mat1; + mat2valid = mat1valid; + mat3valid = mat1valid; + } + + // create faces + for ( i = 0; i < slices4 * 4 + 2; i++ ) { + Face tempface; + + //NOTE: + // there are ( slices4 * 4 + 2 ) faces. + // the bottom and top plates are each a single face although + // they each consist of ( slices4 * 4 ) polygons. + + if ( mat1valid && mat2valid && mat3valid ) { + if ( use_material_spec ) { + // attach material specification + tempface.setShadingType( Face::material_shad ); + if ( i == 0 ) + tempface.AttachMaterial( new Material( mat3 ) ); + else if ( i == 1 ) + tempface.AttachMaterial( new Material( mat2 ) ); + else + tempface.AttachMaterial( new Material( mat1 ) ); + } else { + // use gouraud_shad with diffuse color + tempface.setShadingType( Face::gouraud_shad ); + if ( i == 0 ) + tempface.setFaceColor( mat3.getDiffuseColor() ); + else if ( i == 1 ) + tempface.setFaceColor( mat2.getDiffuseColor() ); + else + tempface.setFaceColor( mat1.getDiffuseColor() ); + } + } else { + // use no_shad with index 255 if no material in state + tempface.setShadingType( Face::no_shad ); + tempface.setFaceColor( 255 ); + } + + tempface.setId( facelist.getNumElements() ); + facelist.AddElement( tempface ); + } + + // do post-processing after object has been built + PostProcessObject(); +} + + +// construct b-rep from vrml cube primitive ----------------------------------- +// +void BRep::BuildFromCubePrimitive( const QvCube& node ) +{ + // base object + VertexChunk& vtxlist = m_baseobject->getVertexList(); + FaceChunk& facelist = m_baseobject->getFaceList(); + PolygonList& polylist = m_baseobject->getPolygonList(); + + // set possible transformation as object's local transformation + Transform3 trafo; + FetchTransformationState( trafo ); + m_baseobject->setObjectTransformation( trafo ); + + double max_x = node.width.value / 2; + double max_y = node.height.value / 2; + double max_z = node.depth.value / 2; + + vtxlist.AddVertex( Vertex3( -max_x, max_y, max_z ) ); + vtxlist.AddVertex( Vertex3( max_x, max_y, max_z ) ); + vtxlist.AddVertex( Vertex3( max_x, -max_y, max_z ) ); + vtxlist.AddVertex( Vertex3( -max_x, -max_y, max_z ) ); + + vtxlist.AddVertex( Vertex3( -max_x, max_y, -max_z ) ); + vtxlist.AddVertex( Vertex3( -max_x, -max_y, -max_z ) ); + vtxlist.AddVertex( Vertex3( max_x, -max_y, -max_z ) ); + vtxlist.AddVertex( Vertex3( max_x, max_y, -max_z ) ); + + Polygon *sidepoly = polylist.NewPolygon(); + sidepoly->AppendNewVIndx( 0 ); sidepoly->AppendNewVIndx( 1 ); sidepoly->AppendNewVIndx( 2 ); sidepoly->AppendNewVIndx( 3 ); + sidepoly = polylist.NewPolygon(); + sidepoly->AppendNewVIndx( 1 ); sidepoly->AppendNewVIndx( 7 ); sidepoly->AppendNewVIndx( 6 ); sidepoly->AppendNewVIndx( 2 ); + sidepoly = polylist.NewPolygon(); + sidepoly->AppendNewVIndx( 7 ); sidepoly->AppendNewVIndx( 4 ); sidepoly->AppendNewVIndx( 5 ); sidepoly->AppendNewVIndx( 6 ); + sidepoly = polylist.NewPolygon(); + sidepoly->AppendNewVIndx( 4 ); sidepoly->AppendNewVIndx( 0 ); sidepoly->AppendNewVIndx( 3 ); sidepoly->AppendNewVIndx( 5 ); + sidepoly = polylist.NewPolygon(); + sidepoly->AppendNewVIndx( 3 ); sidepoly->AppendNewVIndx( 2 ); sidepoly->AppendNewVIndx( 6 ); sidepoly->AppendNewVIndx( 5 ); + sidepoly = polylist.NewPolygon(); + sidepoly->AppendNewVIndx( 1 ); sidepoly->AppendNewVIndx( 0 ); sidepoly->AppendNewVIndx( 4 ); sidepoly->AppendNewVIndx( 7 ); + + //TODO: + // polygons have to be created in the order prescribed by + // material application! + + // fetch the first six materials + Material mats[ 6 ]; + int matsvalid[ 6 ]; + int i = 0; + for ( i = 0; i < 6; i++ ) + matsvalid[ i ] = FetchMaterialState( mats[ i ], 0 ); + + // fetch the current material binding + int currentbinding; + FetchMaterialBindingState( currentbinding ); + + // apply material binding + if ( currentbinding != QvMaterialBinding::PER_PART && + currentbinding != QvMaterialBinding::PER_PART_INDEXED && + currentbinding != QvMaterialBinding::PER_FACE && + currentbinding != QvMaterialBinding::PER_FACE_INDEXED ) + for ( i = 1; i < 6; i++ ) { + mats[ i ] = mats[ 0 ]; + matsvalid[ i ] = matsvalid[ 0 ]; + } + + // check validity of all materials + int allmatsvalid = 1; + for ( i = 0; i < 6; i++ ) + if ( !matsvalid[ i ] ) + allmatsvalid = 0; + + // create faces + for ( i = 0; i < 6; i++ ) { + Face tempface; + + if ( allmatsvalid ) { + if ( use_material_spec ) { + // attach material specification + tempface.setShadingType( Face::material_shad ); + tempface.AttachMaterial( new Material( mats[ i ] ) ); + } else { + // use gouraud_shad with diffuse color + tempface.setShadingType( Face::gouraud_shad ); + tempface.setFaceColor( mats[ i ].getDiffuseColor() ); + } + } else { + // use no_shad with index 255 if no material in state + tempface.setShadingType( Face::no_shad ); + tempface.setFaceColor( 255 ); + } + + tempface.setId( facelist.getNumElements() ); + facelist.AddElement( tempface ); + } + + // do post-processing after object has been built + PostProcessObject(); +} + + +// create single face for specification in indexed face set ------------------- +// +void BRep::CreateIndexedFace( Texture *texture, int curindex, int numtexindexs, long *texindexs, int v1, int v2, int v3 ) +{ + // base object + VertexChunk& vtxlist = m_baseobject->getVertexList(); + FaceChunk& facelist = m_baseobject->getFaceList(); + + // face to be created + Face tempface; + + // fetch material + Material mat; + int matvalid = FetchMaterialState( mat, 0 ); + + if ( matvalid ) { + if ( use_material_spec ) { + // attach material specification + tempface.setShadingType( Face::material_shad ); + tempface.AttachMaterial( new Material( mat ) ); + } else { + // use gouraud_shad with diffuse color + tempface.setShadingType( Face::gouraud_shad ); + tempface.setFaceColor( mat.getDiffuseColor() ); + } + } else { + // use no_shad with index 255 if no material in state + tempface.setShadingType( Face::no_shad ); + tempface.setFaceColor( 255 ); + } + + // check if face is textured + if ( texture != NULL ) { + int coordsnum; + float *texcoords = FetchTextureCoordinate2State( coordsnum ); + + // fetch (u,v) transformation + Transform2 trafo; + FetchTextureTransformationState( trafo ); + + // store fake vertex containing corresponding vertex indexes + Vertex2 fake( v1, v2, v3 ); + tempface.MapXY( 0 ) = fake; + + int mappingvalid = 0; + + int coordindx = ( curindex - 3 < numtexindexs ) ? texindexs[ curindex - 3 ] : -1; + if ( ( coordindx >= 0 ) && ( coordindx < coordsnum ) ) { + tempface.MapUV( 0 ).setX( texcoords[ coordindx * 2 + 0 ] ); + tempface.MapUV( 0 ).setY( texcoords[ coordindx * 2 + 1 ] ); + tempface.MapUV( 0 ).setW( 1.0 ); + Vertex2 tv = trafo.TransformVector2( tempface.MapUV( 0 ) ); + tv.setX( tv.getX() * texture->getWidth() ); + double ucoord = mirror_v_axis ? ( 1.0 - tv.getY() ) : tv.getY(); + tv.setY( ucoord * texture->getHeight() ); + tempface.MapUV( 0 ) = tv; + mappingvalid++; + } + + coordindx = ( curindex - 2 < numtexindexs ) ? texindexs[ curindex - 2 ] : -1; + if ( ( coordindx >= 0 ) && ( coordindx < coordsnum ) ) { + tempface.MapUV( 1 ).setX( texcoords[ coordindx * 2 + 0 ] ); + tempface.MapUV( 1 ).setY( texcoords[ coordindx * 2 + 1 ] ); + tempface.MapUV( 1 ).setW( 1.0 ); + Vertex2 tv = trafo.TransformVector2( tempface.MapUV( 1 ) ); + tv.setX( tv.getX() * texture->getWidth() ); + double ucoord = mirror_v_axis ? ( 1.0 - tv.getY() ) : tv.getY(); + tv.setY( ucoord * texture->getHeight() ); + tempface.MapUV( 1 ) = tv; + mappingvalid++; + } + + coordindx = ( curindex - 1 < numtexindexs ) ? texindexs[ curindex - 1 ] : -1; + if ( ( coordindx >= 0 ) && ( coordindx < coordsnum ) ) { + tempface.MapUV( 2 ).setX( texcoords[ coordindx * 2 + 0 ] ); + tempface.MapUV( 2 ).setY( texcoords[ coordindx * 2 + 1 ] ); + tempface.MapUV( 2 ).setW( 1.0 ); + Vertex2 tv = trafo.TransformVector2( tempface.MapUV( 2 ) ); + tv.setX( tv.getX() * texture->getWidth() ); + double ucoord = mirror_v_axis ? ( 1.0 - tv.getY() ) : tv.getY(); + tv.setY( ucoord * texture->getHeight() ); + tempface.MapUV( 2 ) = tv; + mappingvalid++; + } + + // only set shading type to textured if all three + // mapping coordinates valid + if ( mappingvalid == 3 ) { + tempface.setShadingType( Face::ipol1tex_shad ); + tempface.setTextureName( texture->getName() ); + } + } + + tempface.setId( facelist.getNumElements() ); + facelist.AddElement( tempface ); +} + + +// construct b-rep from vrml indexed face set --------------------------------- +// +void BRep::BuildFromIndexedFaceSet( const QvIndexedFaceSet& faceset ) +{ + // check current shape hints + FetchShapeHintsState(); + + // check for texture mapping + Texture *texture = CheckTexture2State(); + + // determine number and address of vertices in current state + int numvertices; + float *vertices = FetchCoordinate3State( numvertices ); + + // base object + VertexChunk& vtxlist = m_baseobject->getVertexList(); + FaceChunk& facelist = m_baseobject->getFaceList(); + PolygonList& polylist = m_baseobject->getPolygonList(); + + // set possible transformation as object's local transformation + Transform3 trafo; + FetchTransformationState( trafo ); + m_baseobject->setObjectTransformation( trafo ); + + // create vertices (regardless of usage) + for ( int i = 0; i < numvertices; i++ ) { + double x = vertices[ i * 3 + 0 ]; + double y = vertices[ i * 3 + 1 ]; + double z = vertices[ i * 3 + 2 ]; + vtxlist.AddVertex( Vertex3( x, y, z ) ); + } + + //TODO: + // all vertices are included in every object, regardless of usage! + + // fetch the current material binding + int currentbinding; + FetchMaterialBindingState( currentbinding ); + + // determine number and address of vertex indexes + int numvtxindexs = faceset.coordIndex.num; + long *vtxindexs = faceset.coordIndex.values; + + // determine number and address of material indexes + int nummatindexs = faceset.materialIndex.num; + long *matindexs = faceset.materialIndex.values; + + // determine number and address of normal indexes + int numnmlindexs = faceset.normalIndex.num; + long *nmlindexs = faceset.normalIndex.values; + + // determine number and address of texture coordinate indexes + int numtexindexs = faceset.textureCoordIndex.num; + long *texindexs = faceset.textureCoordIndex.values; + + // create polygons and faces + int vtxsread = 0; + int polysread = 0; // this also counts polygons removed due to degeneracy! + int v1, v2, v3; + Plane curplane; + while ( numvtxindexs > 0 ) { + + // prepend new polygon to list + Polygon *poly = polylist.NewPolygon(); + + // create vertexlist for this polygon + int vtxcount = 0; + while ( numvtxindexs-- > 0 ) { + // read next vertex index + int vindx = *vtxindexs++; + vtxsread++; + vtxcount++; + // -1 is end marker for face + if ( vindx == -1 ) + break; + if ( vindx >= numvertices ) { + { + StrScratch message; + sprintf( message, "**ERROR** [Specified vertex-index invalid]: %d\n", vindx ); + ErrorMessage( message ); + } + HandleCriticalError(); + } + + if ( vtxcount == 1 ) { + // store first vertex index + v1 = vindx; + } else if ( vtxcount == 2 ) { + // store second vertex index + v2 = vindx; + } else if ( vtxcount == 3 ) { + // store third vertex index + v3 = vindx; + // create plane for polygon (sidedness irrelevant!) + curplane.InitPlane( vtxlist[ v1 ], vtxlist[ v2 ], vtxlist[ v3 ] ); + // count original polygons (including degenerate ones!) + polysread++; + // check if plane valid + if ( !curplane.PlaneValid() ) { + // remove polygon if invalid + polylist.DeleteHead(); + // skip possibly remaining vertexindexes + while ( ( numvtxindexs-- > 0 ) && ( *vtxindexs++ != -1 ) ) + vtxsread++; + vtxindexs--; + numvtxindexs++; + continue; + } + // create face + CreateIndexedFace( texture, vtxsread, numtexindexs, texindexs, v1, v2, v3 ); +// } else if ( vtxcount == 4 ) { + } else { + // create new polygon and face if next point not contained in + // previous triangle's plane or triangulation explicitly desired + if ( !curplane.PointContained( vtxlist[ vindx ] ) || do_triangulation ) { + // add new polygon to list + poly = polylist.NewPolygon(); + if ( shapehint_vertexOrdering == QvShapeHints::CLOCKWISE ) { + polylist.AppendNewVIndx( v1 ); + polylist.AppendNewVIndx( v3 ); + } else { + polylist.PrependNewVIndx( v1 ); + polylist.PrependNewVIndx( v3 ); + } + // create plane for polygon + curplane.InitPlane( vtxlist[ v1 ], vtxlist[ v3 ], vtxlist[ vindx ] ); + // check if plane valid + if ( !curplane.PlaneValid() ) { + // remove polygon if invalid + polylist.DeleteHead(); + // skip possibly remaining vertexindexes + while ( ( numvtxindexs-- > 0 ) && ( *vtxindexs++ != -1 ) ) + vtxsread++; + vtxindexs--; + numvtxindexs++; + continue; + } + // create face + CreateIndexedFace( texture, vtxsread, numtexindexs, texindexs, v1, v2, v3 ); + } + // advance triangle fan + v3 = vindx; + } + + // insert current vertex index into polygon + if ( shapehint_vertexOrdering == QvShapeHints::CLOCKWISE ) + polylist.AppendNewVIndx( vindx ); + else + polylist.PrependNewVIndx( vindx ); + } + + if ( polylist.FetchHead() != NULL ) { + + //NOTE: + // if all polygons up to now have been removed due to degeneracy, + // polylist might contain not a single element! therefore, + // getNumVertices() cannot be used! + + // check if polygon is at least triangle + if ( polylist.getNumVertices() < 3 ) { + { + StrScratch message; + sprintf( message, "**ERROR** [Face must have at least 3 vertices]: %d\n", + polylist.getNumElements() ); + ErrorMessage( message ); + } + HandleCriticalError(); + } + + } else { + StrScratch message; + sprintf( message, "**ERROR** [Polygon is degenerate]: %d\n", polysread ); + ErrorMessage( message ); + } + } + + // do post-processing after object has been built + PostProcessObject(); +} + + +// shape hints ---------------------------------------------------------------- +// +int BRep::shapehint_vertexOrdering = QvShapeHints::UNKNOWN_ORDERING; +int BRep::shapehint_shapeType = QvShapeHints::UNKNOWN_SHAPE_TYPE; +int BRep::shapehint_faceType = QvShapeHints::CONVEX; +float BRep::shapehint_creaseAngle = 0.5f; + + +// full material specification usage control ---------------------------------- +// +int BRep::use_material_spec = FALSE; + + +// flag if v axis should be mirrored for texture coordinates ------------------ +// +int BRep::mirror_v_axis = TRUE; + + +// triangulation control ------------------------------------------------------ +// +int BRep::do_triangulation = FALSE; + + +// tessellation resolution in slices per PI/2 --------------------------------- +// +int BRep::tessellation_slices = 4; + + +BSPLIB_NAMESPACE_END + +//----------------------------------------------------------------------------- |
