Bjorn,
There are two ways of parsing geometry data in a dwf file. This depends on whether the stream is a 2d or 3d stream. Basically you do as follows :
NOTES :
Pasted code is from my application, and may have irrelevant information, just ignore and read the documentation.
I am not performing memory management, so you must ensure you do this.
I am not performing error checking, but obviuosly you must in your application.
step 1.
Find out if you are dealing with a package or a stream.
DWFFile file( pwszFile );
DWFPackageReader PkgRdr( file );
DWFPackageReader::tPackageInfo packInfo;
PkgRdr.getPackageInfo( packInfo );
switch (tInfo.eType) {
case DWFToolkit::DWFPackageReader::eDWFPackage:
// deal with a package
break;
case DWFToolkit::DWFPackageReader::eW2DStream:
//deal with a2d stream
break;
case DWFToolkit::DWFPackageReader::eDWFStream:
// deal with a eDWF Stream
break;
case DWFToolkit::DWFPackageReader::eDWFPackageEncrypted:
// password protected package.
break;
default:
return false;
}
step 2.
So if it is a package, we can find the layouts (sections) as follows :
DWFManifest &Manf = PkgRdr.getManifest();
DWFSection* pSection = NULL;
DWFManifest::SectionIterator* pSections = NULL;
for ( pSections = Manf.getSections();
pSections && pSections->valid(); pSections->next() ) {
pSection = pSections->get();
if ( (pSection->type() == _DWF_FORMAT_EPLOT_TYPE_WIDE_STRING ) ||
(pSection->type() == _DWF_FORMAT_EMODEL_TYPE_WIDE_STRING ) ) {
std::wstring wsCurView = (const wchar_t*)pSection->name();
}
// ok we have a section so next we get the stream for the geometry data.
}
step 3.
So now we have a layout, we can get the stream.
2d streams are as follows :
DWFToolkit::DWFResourceContainer::ResourceIterator* piRes = pSect->findResourcesByRole( DWFXML::kzRole_Graphics2d );
DWFCore::DWFInputStream* pW2DStream = piRes->get()->getInputStream();
3d streams are as follows :
DWFToolkit::DWFResourceContainer::ResourceIterator* piRes = pSect->findResourcesByRole( DWFXML::kzRole_Graphics3d );
DWFToolkit::DWFGraphicResource* pW3D = dynamic_cast(piRes->get()); DWFCore::DWFInputStream* pW3DStream = pW3D->getInputStream();
step 4.
Laslty you must parse the stream with the correct part of the tool kit.
2d streams use the whip toolkit.
3d streams use the hoops scenegraph.
Look in the examples section and this should help you, as this is where I started from.
But basically for the 2d streams I do as follows :
m_pDwf2DStrm = pW2DStream ;
m_pW2DStrm = new WT_File();
m_pW2DStrm->set_stream_open_action(&CWhipHndlr::Open);
m_pW2DStrm->set_stream_close_action (&CWhipHndlr::Close);
m_pW2DStrm->set_stream_read_action (&CWhipHndlr::Read);
m_pW2DStrm->set_stream_seek_action (&CWhipHndlr::Seek);
m_pW2DStrm->set_stream_end_seek_action (&CWhipHndlr::EndSeek);
and the CWhipHndlr functions are callbacks as follows :
WT_Result CWhipHndlr::Open(WT_File & file) {
file.set_stream_user_data (m_pDwf2DStrm);
return m_pDwf2DStrm ?
WT_Result::Success :
WT_Result::File_Open_Error;
}
//---------------------------------------------------------------------------------
WT_Result CWhipHndlr::Close (WT_File & file)
{
return WT_Result::Success;
}
//---------------------------------------------------------------------------------
WT_Result CWhipHndlr::Read( WT_File & file,
int desired_bytes,
int & bytes_read,
void * buffer)
{
WT_Result res = WT_Result::Unknown_File_Read_Error;
if (m_pDwf2DStrm)
{
bytes_read = (int)m_pDwf2DStrm->read (buffer, desired_bytes);
res = WT_Result::Success;
}
return res;
}
//---------------------------------------------------------------------------------
WT_Result CWhipHndlr::Seek( WT_File & file,
int desired_bytes,
int &bytes_seeked)
{
WT_Result res = WT_Result::Unknown_File_Read_Error;
if (m_pDwf2DStrm)
{
m_pDwf2DStrm->seek (SEEK_SET, desired_bytes);
bytes_seeked = desired_bytes;
res = WT_Result::Success;
}
return res;
}
//---------------------------------------------------------------------------------
WT_Result CWhipHndlr::EndSeek (WT_File & file)
{
WT_Result res = WT_Result::Unknown_File_Read_Error;
return res;
}
//---------------------------------------------------------------------------------
WT_Result CWhipHndlr::Tell ( WT_File & file,
unsigned long *current_file_pointer_position )
{
WT_Result res = WT_Result::Unknown_File_Read_Error;
if (m_pDwf2DStrm)
{
*current_file_pointer_position =
m_pDwf2DStrm->seek (SEEK_CUR, 0);
res = WT_Result::Success;
}
return res;
}
and I use the callbacks for all the geometry type like :
m_pW2DStrm->set_polyline_action(CWhipHndlr::prcsPolyLine);
m_pW2DStrm->set_units_action(CWhipHndlr::prcsUnits);
m_pW2DStrm->set_text_action(CWhipHndlr::prcsText);
m_pW2DStrm->set_polygon_action(CWhipHndlr::prcsPolygon);
m_pW2DStrm->set_polytriangle_action(CWhipHndlr::prcsPolyTri);
m_pW2DStrm->set_layer_action(CWhipHndlr::prcsLyr);
m_pW2DStrm->set_color_action(CWhipHndlr::prcsClr);
m_pW2DStrm->set_fill_action(CWhipHndlr::prcsFill);
m_pW2DStrm->set_contour_set_action(CWhipHndlr::prcsContSet);
m_pW2DStrm->set_background_action(CWhipHndlr::prcsBckGrnd);
m_pW2DStrm->set_image_action(CWhipHndlr::prcsImage);
m_pW2DStrm->set_png_group4_image_action(CWhipHndlr::prcsPngImge4);
m_pW2DStrm->set_object_node_action(CWhipHndlr::prcsObjNode);
m_pW2DStrm->set_outline_ellipse_action(CWhipHndlr::prcsOutLineElps);
m_pW2DStrm->set_filled_ellipse_action(CWhipHndlr::prcsFilledElps);
m_pW2DStrm->set_viewport_action(CWhipHndlr::prcsViewPort);
m_pW2DStrm->set_line_weight_action(CWhipHndlr::prcsLineWght);
m_pW2DStrm->set_origin_action(CWhipHndlr::prcsOrgn);
and finally you process each object in the file with the following loop:
while ( res == WT_Result::Success ) {
res = m_pW2DStrm->process_next_object(); // this will call the correct callback for the correct object
// optional section if you wish to do other things as well.
if ( res == WT_Result::Success ) {
WT_Object* pObj = (WT_Object *) m_pW2DStrm->current_object();
if ( pObj ) {
prntDbgObjType(pObj);
WT_Object::WT_ID type = pObj->object_id();
switch ( pObj->object_id() )
{
case WT_Object::DWF_Header_ID :
case WT_Object::End_Of_DWF_ID :
// do any extra work if need be
break;
case WT_Object::Color_Map_ID :
break;
default:
break;
}
}
}
// end of optional section.
}
for 3d its like this
BStreamFileToolkit oW3DStreamParser;
oW3DStreamParser.SetOpcodeHandler( TKE_Open_Segment, new COpenSgmtHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Close_Segment, new CCloseSgmtHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Polygon, new CPolyLineHndlr(pCtxt.get(), TKE_Polygon) );
oW3DStreamParser.SetOpcodeHandler( TKE_Polyline, new CPolyLineHndlr(pCtxt.get(), TKE_Polyline) );
oW3DStreamParser.SetOpcodeHandler( TKE_PolyPolyline, new CPolyPolyPntHndlr(pCtxt.get(), TKE_PolyPolyline) );
oW3DStreamParser.SetOpcodeHandler( TKE_Shell, new CShellHndlr(pCtxt.get()) );
oW3DStreamParser.SetOpcodeHandler( TKE_Include_Segment, new CRefSgmtHndlr(pCtxt.get(), TKE_Include_Segment ));
oW3DStreamParser.SetOpcodeHandler( TKE_Style_Segment, new CStylSgmtHndlr(pCtxt.get(), TKE_Style_Segment));
oW3DStreamParser.SetOpcodeHandler( TKE_Modelling_Matrix, new CMtrxHndlr(pCtxt.get(), TKE_Modelling_Matrix ));
oW3DStreamParser.SetOpcodeHandler( TKE_User_Options, new CUserOptnHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_User_Value, new CUserValHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Rendering_Options, new CRndrOptnHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Color_RGB, new CClrRGBHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Color, new CClrHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Color_By_Value, new CClrByValHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Color_Map, new CClrMapHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_PolyCylinder, new CPolyCylHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Mesh, new CMeshHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_LOD, new CLODHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Image, new CImgeHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( W3DE_Image, new CW3DImgeHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Texture, new CTxtrHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Circular_Arc, new CCircHndlr(pCtxt.get(), TKE_Circular_Arc));
oW3DStreamParser.SetOpcodeHandler( TKE_Line, new CLineHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_NURBS_Curve, new CNurbsCurveHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_NURBS_Surface, new CNurbsSrfcHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Visibility, new CVsblHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Rendering_Options, new CRndrOptsHndlr(pCtxt.get()));
oW3DStreamParser.SetOpcodeHandler( TKE_Heuristics, new CHeurHndlr());
oW3DStreamParser.SetOpcodeHandler( TKE_Termination, new CTermHndlr(TKE_Termination));
oW3DStreamParser.SetOpcodeHandler( TKE_Pause, new CTermHndlr(TKE_Pause));
oW3DStreamParser.SetOpcodeHandler( TKE_Clip_Region, new CClipRgnHndlr());
oW3DStreamParser.SetOpcodeHandler( TKE_Tag, new CTestHndlr());
oW3DStreamParser.OpenStream( *pW3DStream );
size_t nBytesRead = 0;
char aBuffer[16384] = {0};
while (pW3DStream->available() > 0) {
nBytesRead = pW3DStream->read( aBuffer, 16384 );
if (oW3DStreamParser.ParseBuffer(aBuffer, (int) nBytesRead, TK_Normal) == TK_Error) {
oW3DStreamParser.CloseStream();
DWFCORE_FREE_OBJECT( pW3DStream );
m_wsLastErr = pwszErrCorruptData;
return false;
}
oW3DStreamParser.CloseStream();
and each of the classes above ie COpenSgmtHndlr looks similar too:
class COpenSgmtHndlr : public TK_Open_Segment {
public:
COpenSgmtHndlr(PstCtxt pCtxt) : CSgmtHndlr(pCtxt), TK_Open_Segment() { ;}
TK_Status Execute( BStreamFileToolkit& parser );
virtual ~COpenSgmtHndlr() {;}
private:
};
and the Execute command gets called for each object that the hoops parses.
Also, if you wish to do texture mapping, you will need to extract them as well, and map them texture/enviornments onto your model as well.
Also Embedded fonts are another thing to extract and get working, but search the forums for this infomration as it is all here.
Anyhow, I hope this helps you.
Cheers
Jason Anderssen