Added RAW Loader. Tested with various configurations, seems to work.

Added OFF Loader. Tested with various configurations, seems to work.
Added POLYLINE support to the DXF Loader.
Added WIP version of the MDR loader - disabled and not yet working.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@145 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2008-09-16 16:17:32 +00:00
parent b776f04251
commit 7f9c3652b3
23 changed files with 132372 additions and 232 deletions

View File

@ -58,6 +58,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
// AutoCAD Binary DXF<CR><LF><SUB><NULL>
#define AI_DXF_BINARY_IDENT ("AutoCAD Binary DXF\r\n\x1a\0")
#define AI_DXF_BINARY_IDENT_LEN (24)
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
DXFImporter::DXFImporter()
@ -100,6 +105,12 @@ bool DXFImporter::GetNextLine()
// ------------------------------------------------------------------------------------------------
bool DXFImporter::GetNextToken()
{
if (bRepeat)
{
bRepeat = false;
return true;
}
SkipSpaces(&buffer);
groupCode = strtol10s(buffer,&buffer);
if(!GetNextLine())return false;
@ -132,19 +143,23 @@ void DXFImporter::InternReadFile( const std::string& pFile,
file->Read( &buffer2[0], m,1);
buffer2[m] = '\0';
bRepeat = false;
mDefaultLayer = NULL;
// check whether this is a binaray DXF file - we can't read binary DXF files :-(
if (!strncmp(AI_DXF_BINARY_IDENT,buffer,AI_DXF_BINARY_IDENT_LEN))
throw new ImportErrorException("DXF: Binary files are not supported at the moment");
// now get all lines of the file
while (GetNextToken())
{
if (2 == groupCode)
{
// ENTITIES section
if (!::strcmp(cursor,"ENTITIES"))
// ENTITIES and BLOCKS sections - skip the whole rest, no need to waste our time with them
if (!::strcmp(cursor,"ENTITIES") || !::strcmp(cursor,"BLOCKS"))
if (!ParseEntities())break;
// other sections such as BLOCK - skip them to make
// sure there will be no name conflicts
// other sections - skip them to make sure there will be no name conflicts
else
{
bool b = false;
@ -165,14 +180,23 @@ void DXFImporter::InternReadFile( const std::string& pFile,
break;
}
if (mLayers.empty())
// find out how many valud layers we have
for (std::vector<LayerInfo>::const_iterator it = mLayers.begin(),end = mLayers.end();
it != end;++it)
{
if (!(*it).vPositions.empty())++pScene->mNumMeshes;
}
if (!pScene->mNumMeshes)
throw new ImportErrorException("DXF: this file contains no 3d data");
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes = (unsigned int)mLayers.size()];
pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ];
m = 0;
for (std::vector<LayerInfo>::const_iterator it = mLayers.begin(),end = mLayers.end();
it != end;++it)
{
if ((*it).vPositions.empty())continue;
// generate the output mesh
aiMesh* pMesh = pScene->mMeshes[m++] = new aiMesh();
const std::vector<aiVector3D>& vPositions = (*it).vPositions;
@ -257,11 +281,12 @@ bool DXFImporter::ParseEntities()
{
if (!groupCode)
{
while (true) {
if (!::strcmp(cursor,"3DFACE"))
if (!Parse3DFace()) return false; else continue;
break;
};
if (!Parse3DFace()) return false; else bRepeat = true;
if (!::strcmp(cursor,"POLYLINE"))
if (!ParsePolyLine()) return false; else bRepeat = true;
if (!::strcmp(cursor,"ENDSEC"))
return true;
}
@ -269,6 +294,173 @@ bool DXFImporter::ParseEntities()
return false;
}
// ------------------------------------------------------------------------------------------------
void DXFImporter::SetLayer(LayerInfo*& out)
{
for (std::vector<LayerInfo>::iterator it = mLayers.begin(),end = mLayers.end();
it != end;++it)
{
if (!::strcmp( (*it).name, cursor ))
{
out = &(*it);
break;
}
}
if (!out)
{
// we don't have this layer yet
mLayers.push_back(LayerInfo());
out = &mLayers.back();
::strcpy(out->name,cursor);
}
}
// ------------------------------------------------------------------------------------------------
void DXFImporter::SetDefaultLayer(LayerInfo*& out)
{
if (!mDefaultLayer)
{
mLayers.push_back(LayerInfo());
mDefaultLayer = &mLayers.back();
}
out = mDefaultLayer;
}
// ------------------------------------------------------------------------------------------------
bool DXFImporter::ParsePolyLine()
{
bool ret = false;
LayerInfo* out = NULL;
std::vector<aiVector3D> positions;
std::vector<unsigned int> indices;
unsigned int flags = 0;
while (GetNextToken())
{
switch (groupCode)
{
case 0:
{
if (!::strcmp(cursor,"VERTEX"))
{
aiVector3D v;
unsigned int idx[4] = {0xffffffff,0xffffffff,0xffffffff,0xffffffff};
ParsePolyLineVertex(v, idx);
if (0xffffffff == idx[0])positions.push_back(v);
else
{
// check whether we have a fourth coordinate
if (0xffffffff == idx[3])
{
idx[3] = idx[2];
}
indices.reserve(indices.size()+4);
for (unsigned int m = 0; m < 4;++m)
indices.push_back(idx[m]);
}
bRepeat = true;
}
else if (!::strcmp(cursor,"ENDSEQ"))
{
ret = true;
}
break;
}
// flags --- important that we know whether it is a polyface mesh
case 70:
{
flags = strtol10(cursor);
break;
};
// optional number of vertices
case 71:
{
positions.reserve(std::min(std::max(100u, strtol10(cursor)),100000000u));
break;
}
// optional number of faces
case 72:
{
indices.reserve(std::min(std::max(100u, strtol10(cursor)),100000000u) * 4u);
break;
}
// 8 specifies the layer
case 8:
{
SetLayer(out);
break;
}
}
}
if (!(flags & 64))
{
DefaultLogger::get()->warn("DXF: Only polyface meshes are currently supported");
return ret;
}
if (positions.size() < 3 || indices.size() < 3)
{
DefaultLogger::get()->warn("DXF: Unable to parse POLYLINE element - not enough vertices");
return ret;
}
// use a default layer if necessary
if (!out)SetDefaultLayer(out);
// generate unique vertices
for (std::vector<unsigned int>::const_iterator it = indices.begin(), end = indices.end();
it != end; ++it)
{
unsigned int idx = *it;
if (idx > positions.size())
{
DefaultLogger::get()->error("DXF: Polyface mesh index os out of range");
idx = (unsigned int) positions.size();
}
out->vPositions.push_back(positions[idx-1]); // indices are one-based.
}
return ret;
}
// ------------------------------------------------------------------------------------------------
bool DXFImporter::ParsePolyLineVertex(aiVector3D& out,unsigned int* outIdx)
{
bool ret = false;
while (GetNextToken())
{
switch (groupCode)
{
case 0: ret = true;break;
// todo - handle the correct layer for the vertex
// x position of the first corner
case 10: out.x = fast_atof(cursor);break;
// y position of the first corner
case 20: out.y = -fast_atof(cursor);break;
// z position of the first corner
case 30: out.z = fast_atof(cursor);break;
// POLYFACE vertex indices
case 71: outIdx[0] = strtol10(cursor);break;
case 72: outIdx[1] = strtol10(cursor);break;
case 73: outIdx[2] = strtol10(cursor);break;
case 74: outIdx[3] = strtol10(cursor);break;
};
if (ret)break;
}
return ret;
}
// ------------------------------------------------------------------------------------------------
bool DXFImporter::Parse3DFace()
{
@ -285,22 +477,7 @@ bool DXFImporter::Parse3DFace()
// 8 specifies the layer
case 8:
{
for (std::vector<LayerInfo>::iterator it = mLayers.begin(),end = mLayers.end();
it != end;++it)
{
if (!::strcmp( (*it).name, cursor ))
{
out = &(*it);
break;
}
}
if (!out)
{
// we don't have this layer yet
mLayers.push_back(LayerInfo());
out = &mLayers.back();
::strcpy(out->name,cursor);
}
SetLayer(out);
break;
}
@ -344,20 +521,12 @@ bool DXFImporter::Parse3DFace()
}
// use a default layer if necessary
if (!out)
{
if (!mDefaultLayer)
{
mLayers.push_back(LayerInfo());
mDefaultLayer = &mLayers.back();
}
out = mDefaultLayer;
}
if (!out)SetDefaultLayer(out);
// add the faces to the face list for this layer
out->vPositions.push_back(vip[0]);
out->vPositions.push_back(vip[1]);
out->vPositions.push_back(vip[2]);
out->vPositions.push_back(vip[3]);
out->vPositions.push_back(vip[3]); // might be equal to the third
return ret;
}

View File

@ -63,6 +63,22 @@ protected:
/** Destructor, private as well */
~DXFImporter();
// describes a single layer in the DXF file
struct LayerInfo
{
LayerInfo()
{
name[0] = '\0';
}
char name[4096];
// face buffer - order is x,y,z,w v1,v2,v3 (w is equal to z if unused)
std::vector<aiVector3D> vPositions;
};
public:
// -------------------------------------------------------------------
@ -112,6 +128,33 @@ protected:
*/
bool Parse3DFace();
// -------------------------------------------------------------------
/** Parses a POLYLINE section in the file
* @return false if the end of the file was reached
*/
bool ParsePolyLine();
// -------------------------------------------------------------------
/** Sets the current layer - cursor must point to the name of it.
* @param out Receives a handle to the layer
*/
void SetLayer(LayerInfo*& out);
// -------------------------------------------------------------------
/** Creates a default layer.
* @param out Receives a handle to the default layer
*/
void SetDefaultLayer(LayerInfo*& out);
// -------------------------------------------------------------------
/** Parses a VERTEX element in a POLYLINE/POLYFACE
* @param out Receives the output vertex.
* @param outIdx Receives the output vertex indices, if present.
* Wont't be modified otherwise. Size must be at least 4.
* @return false if the end of the file was reached
*/
bool ParsePolyLineVertex(aiVector3D& out,unsigned int* outIdx);
private:
// points to the next section
@ -123,19 +166,9 @@ private:
// contains the current data line
char cursor[4096];
// describes a single layer in the DXF file
struct LayerInfo
{
LayerInfo()
{
name[0] = '\0';
}
char name[4096];
// face buffer - order is x,y,z,w v1,v2,v3 (w is equal to z if unused)
std::vector<aiVector3D> vPositions;
};
// specifies whether the next call to GetNextToken()
// should return the current token a second time
bool bRepeat;
// list of all loaded layers
std::vector<LayerInfo> mLayers;

View File

@ -90,11 +90,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#if (!defined AI_BUILD_NO_SMD_IMPORTER)
# include "SMDLoader.h"
#endif
#if 0
#if (!defined AI_BUILD_NO_MDR_IMPORTER)
# include "MDRLoader.h"
#endif
#endif
#if (!defined AI_BUILD_NO_MDC_IMPORTER)
# include "MDCLoader.h"
#endif
@ -113,6 +111,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#if (!defined AI_BUILD_NO_NFF_IMPORTER)
# include "NFFLoader.h"
#endif
#if (!defined AI_BUILD_NO_RAW_IMPORTER)
# include "RAWLoader.h"
#endif
#if (!defined AI_BUILD_NO_OFF_IMPORTER)
# include "OffLoader.h"
#endif
// PostProcess-Steps
@ -211,11 +215,11 @@ Importer::Importer() :
#if (!defined AI_BUILD_NO_SMD_IMPORTER)
mImporter.push_back( new SMDImporter());
#endif
#if 0
/*
#if (!defined AI_BUILD_NO_MDR_IMPORTER)
mImporter.push_back( new MDRImporter());
#endif
#endif
*/
#if (!defined AI_BUILD_NO_MDC_IMPORTER)
mImporter.push_back( new MDCImporter());
#endif
@ -234,6 +238,12 @@ Importer::Importer() :
#if (!defined AI_BUILD_NO_NFF_IMPORTER)
mImporter.push_back( new NFFImporter());
#endif
#if (!defined AI_BUILD_NO_RAW_IMPORTER)
mImporter.push_back( new RAWImporter());
#endif
#if (!defined AI_BUILD_NO_OFF_IMPORTER)
mImporter.push_back( new OFFImporter());
#endif
// add an instance of each post processing step here in the order
// of sequence it is executed. steps that are added here are not validated -

View File

@ -52,7 +52,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// public ASSIMP headers
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
#include "../include/DefaultLogger.h"

View File

@ -87,7 +87,7 @@ struct Vertex
aiVector3D normal;
aiVector2D texCoords;
uint32_t numWeights;
Weight weights[1]; // variable sized
Weight weights; // variable sized
} PACK_STRUCT;
// ---------------------------------------------------------------------------
@ -143,7 +143,7 @@ struct Bone
/** \brief Data structure for a frame in a MDR file
*/
struct Frame {
aiVector3D bounds[2]; // bounds of all surfaces of all LOD's for this frame
aiVector3D bounds0,bounds1; // bounds of all surfaces of all LOD's for this frame
aiVector3D localOrigin; // midpoint of bounds, used for sphere cull
float radius; // dist from localOrigin to corner
char name[16];
@ -165,7 +165,7 @@ struct CompBone
*/
struct CompFrame
{
aiVector3D bounds[2]; // bounds of all surfaces of all LOD's for this frame
aiVector3D bounds0,bounds1; // bounds of all surfaces of all LOD's for this frame
aiVector3D localOrigin; // midpoint of bounds, used for sphere cull
float radius; // dist from localOrigin to corner
CompBone bones[1]; // [numBones]
@ -204,7 +204,7 @@ struct Header
char name[AI_MDR_MAXQPATH];
// frames and bones are shared by all levels of detail
int32_t numFrames;
uint32_t numFrames;
uint32_t numBones;
uint32_t ofsFrames;
@ -221,7 +221,6 @@ struct Header
#include "./../include/Compiler/poppack1.h"
};
};
}}
#endif // !! AI_MDRFILEHELPER_H_INC

232
code/MDRLoader.cpp 100644
View File

@ -0,0 +1,232 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (ASSIMP)
---------------------------------------------------------------------------
Copyright (c) 2006-2008, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the MDR importer class */
// internal headers
#include "MDRLoader.h"
#include "MaterialSystem.h"
#include "StringComparison.h"
#include "ByteSwap.h"
// public ASSIMP headers
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
#include "../include/DefaultLogger.h"
#include "../include/assimp.hpp"
// boost headers
#include <boost/scoped_ptr.hpp>
using namespace Assimp;
using namespace Assimp::MDR;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MDRImporter::MDRImporter()
{
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
MDRImporter::~MDRImporter()
{
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool MDRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
{
// simple check of file extension is enough for the moment
std::string::size_type pos = pFile.find_last_of('.');
// no file extension - can't read
if( pos == std::string::npos)
return false;
std::string extension = pFile.substr( pos);
return !(extension.length() != 4 || extension[0] != '.' ||
extension[1] != 'm' && extension[1] != 'M' ||
extension[2] != 'd' && extension[2] != 'D' ||
extension[3] != 'r' && extension[3] != 'R');
}
// ------------------------------------------------------------------------------------------------
// Validate the header of the given MDR file
void MDRImporter::ValidateHeader()
{
AI_SWAP4(pcLOD->version);
AI_SWAP4(pcLOD->numBones);
AI_SWAP4(pcLOD->numTags);
AI_SWAP4(pcLOD->numFrames);
AI_SWAP4(pcLOD->ofsFrames);
AI_SWAP4(pcLOD->ofsTags);
AI_SWAP4(pcLOD->numLODs);
AI_SWAP4(pcLOD->ofsLODs);
if (pcHeader->ident != AI_MDR_MAGIC_NUMBER_BE &&
pcHeader->ident != AI_MDR_MAGIC_NUMBER_LE)
{
char szBuffer[5];
szBuffer[0] = ((char*)&pcHeader->ident)[0];
szBuffer[1] = ((char*)&pcHeader->ident)[1];
szBuffer[2] = ((char*)&pcHeader->ident)[2];
szBuffer[3] = ((char*)&pcHeader->ident)[3];
szBuffer[4] = '\0';
throw new ImportErrorException("Invalid MDR magic word: should be 5MDR, the "
"magic word found is " + std::string( szBuffer ));
}
if (pcHeader->version != AI_MDR_VERSION)
DefaultLogger::get()->warn("Unsupported MDR file version (2 (AI_MDR_VERSION) was expected)");
if (!pcHeader->numBones)
DefaultLogger::get()->warn("MDR: At least one bone must be there");
// validate all LODs
uint32_t cur = pcHeader->ofsLODs;
for (uint32_t i = 0; i < pcHeader->numLODs;++i)
{
if (cur + sizeof(MDR::LOD) > fileSize)
throw new ImportErrorException("MDR: header is invalid - LOD out of range");
BE_NCONST MDR::LOD* pcSurf = (BE_NCONST MDR::LOD*)((int8_t*)pcHeader + cur);
ValidateLODHeader(pcSurf);
cur = pcSurf->ofsEnd;
}
// validate all frames
if (pcHeader->ofsFrames + sizeof(MDR::Frame) * (pcHeader->numBones-1) *
sizeof(MDR::Bone) * pcHeader->numFrames > fileSize)
{
throw new ImportErrorException("MDR: header is invalid - frame out of range");
}
// check whether the requested frame is existing
if (this->configFrameID >= pcHeader->numFrames)
throw new ImportErrorException("The requested frame is not available");
}
// ------------------------------------------------------------------------------------------------
// Validate the header of a given MDR file LOD
void MDRImporter::ValidateLODHeader(BE_NCONST MDR::LOD* pcLOD)
{
AI_SWAP4(pcLOD->ofsSurfaces);
AI_SWAP4(pcLOD->numSurfaces);
AI_SWAP4(pcLOD->ofsEnd);
const unsigned int iMax = this->fileSize - (unsigned int)((int8_t*)pcLOD-(int8_t*)pcHeader);
uint32_t cur = pcLOD->ofsSurfaces;
for (unsigned int i = 0; i < pcLOD->numSurfaces;++i)
{
if (cur + sizeof(MDR::Surface) > iMax)
throw new ImportErrorException("MDR: LOD header is invalid");
BE_NCONST MDR::Surface* pcSurf = (BE_NCONST MDR::Surface*)((int8_t*)pcLOD + cur);
ValidateSurfaceHeader(pcSurf);
cur = pcSurf->ofsEnd;
}
}
// ------------------------------------------------------------------------------------------------
// Validate the header of a given MDR file surface
void MDRImporter::ValidateSurfaceHeader(BE_NCONST MDR::Surface* pcSurf)
{
AI_SWAP4(pcSurf->ident);
AI_SWAP4(pcSurf->numBoneReferences);
AI_SWAP4(pcSurf->numTriangles);
AI_SWAP4(pcSurf->numVerts);
AI_SWAP4(pcSurf->ofsBoneReferences);
AI_SWAP4(pcSurf->ofsEnd);
AI_SWAP4(pcSurf->ofsTriangles);
AI_SWAP4(pcSurf->ofsVerts);
AI_SWAP4(pcSurf->shaderIndex);
const unsigned int iMax = this->fileSize - (unsigned int)((int8_t*)pcSurf-(int8_t*)pcHeader);
// not exact - there could be extra data in the vertices.
if (pcSurf->ofsTriangles + pcSurf->numTriangles*sizeof(MDR::Triangle) > iMax ||
pcSurf->ofsVerts + pcSurf->numVerts*sizeof(MDR::Vertex) > iMax)
{
throw new ImportErrorException("MDR: Surface header is invalid");
}
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties
void MDRImporter::SetupProperties(const Importer* pImp)
{
// The AI_CONFIG_IMPORT_MDR_KEYFRAME option overrides the
// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
if(0xffffffff == (this->configFrameID = pImp->GetPropertyInteger(
AI_CONFIG_IMPORT_MDR_KEYFRAME,0xffffffff)))
{
this->configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
}
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void MDRImporter::InternReadFile(
const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
// Check whether we can read from the file
if( file.get() == NULL)
throw new ImportErrorException( "Failed to open MDR file " + pFile + ".");
// check whether the mdr file is large enough to contain the file header
fileSize = (unsigned int)file->FileSize();
if( fileSize < sizeof(MDR::Header))
throw new ImportErrorException( "MDR File is too small.");
std::vector<unsigned char> mBuffer2(fileSize);
file->Read( &mBuffer2[0], 1, fileSize);
mBuffer = &mBuffer2[0];
// validate the file header
this->pcHeader = (BE_NCONST MDR::Header*)this->mBuffer;
this->ValidateHeader();
}

139
code/MDRLoader.h 100644
View File

@ -0,0 +1,139 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2008, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file Definition of the MDR importer class. */
#ifndef AI_MDRLOADER_H_INCLUDED
#define AI_MDRLOADER_H_INCLUDED
#include "../include/aiTypes.h"
#include "BaseImporter.h"
#include "MDRFileData.h"
#include "ByteSwap.h"
namespace Assimp {
using namespace MDR;
// ---------------------------------------------------------------------------
/** Importer class for the MDR file format (Ravensoft)
*/
class MDRImporter : public BaseImporter
{
friend class Importer;
protected:
/** Constructor to be privately used by Importer */
MDRImporter();
/** Destructor, private as well */
~MDRImporter();
public:
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
// -------------------------------------------------------------------
/** Called prior to ReadFile().
* The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list.
*/
void SetupProperties(const Importer* pImp);
protected:
// -------------------------------------------------------------------
/** Called by Importer::GetExtensionList() for each loaded importer.
* See BaseImporter::GetExtensionList() for details
*/
void GetExtensionList(std::string& append)
{
append.append("*.mdr");
}
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
protected:
// -------------------------------------------------------------------
/** Validate the header of the file
*/
void ValidateHeader();
// -------------------------------------------------------------------
/** Validate the header of a MDR surface
* @param pcSurf Surface to be validated
*/
void ValidateSurfaceHeader(BE_NCONST MDR::Surface* pcSurf);
// -------------------------------------------------------------------
/** Validate the header of a MDR LOD
* @param pcLOD LOD to be validated
*/
void ValidateLODHeader(BE_NCONST MDR::LOD* pcLOD);
protected:
/** Configuration option: frame to be loaded */
unsigned int configFrameID;
/** Header of the MDR file */
BE_NCONST MDR::Header* pcHeader;
/** Buffer to hold the loaded file */
unsigned char* mBuffer;
/** size of the file, in bytes */
unsigned int fileSize;
};
} // end of namespace Assimp
#endif // AI_MDRIMPORTER_H_INC

View File

@ -88,20 +88,6 @@ bool NFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
extension[2] != 'f' && extension[2] != 'F' ||
extension[3] != 'f' && extension[3] != 'F');
}
// ------------------------------------------------------------------------------------------------
bool GetNextLine(const char*& buffer, char out[4096])
{
if ('\0' == *buffer)return false;
char* _out = out;
char* const end = _out+4096;
while (!IsLineEnd( *buffer ) && _out < end)
*_out++ = *buffer++;
*_out = '\0';
if ('\0' != *buffer)while (IsLineEnd( *buffer ))++buffer;
return true;
}
// ------------------------------------------------------------------------------------------------
#define AI_NFF_PARSE_FLOAT(f) \

189
code/OFFLoader.cpp 100644
View File

@ -0,0 +1,189 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (ASSIMP)
---------------------------------------------------------------------------
Copyright (c) 2006-2008, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the OFF importer class */
// internal headers
#include "OFFLoader.h"
#include "MaterialSystem.h"
#include "ParsingUtils.h"
#include "fast_atof.h"
// public assimp headers
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
#include "../include/DefaultLogger.h"
// boost headers
#include <boost/scoped_ptr.hpp>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
OFFImporter::OFFImporter()
{
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
OFFImporter::~OFFImporter()
{
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
{
// simple check of file extension is enough for the moment
std::string::size_type pos = pFile.find_last_of('.');
// no file extension - can't read
if( pos == std::string::npos)return false;
std::string extension = pFile.substr( pos);
if (extension.length() < 4)return false;
if (extension[0] != '.')return false;
return !(extension.length() != 4 || extension[0] != '.' ||
extension[1] != 'o' && extension[1] != 'R' ||
extension[2] != 'f' && extension[2] != 'F' ||
extension[3] != 'f' && extension[3] != 'F');
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void OFFImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler)
{
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
// Check whether we can read from the file
if( file.get() == NULL)
throw new ImportErrorException( "Failed to open OFF file " + pFile + ".");
unsigned int fileSize = (unsigned int)file->FileSize();
// allocate storage and copy the contents of the file to a memory buffer
std::vector<char> mBuffer2(fileSize+1);
file->Read(&mBuffer2[0], 1, fileSize);
mBuffer2[fileSize] = '\0';
const char* buffer = &mBuffer2[0];
char line[4096];
GetNextLine(buffer,line);
if ('O' == line[0])GetNextLine(buffer,line); // skip the 'OFF' line
const char* sz = line; SkipSpaces(&sz);
const unsigned int numVertices = strtol10(sz,&sz);SkipSpaces(&sz);
const unsigned int numFaces = strtol10(sz,&sz);
pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = 1 ];
aiMesh* mesh = pScene->mMeshes[0] = new aiMesh();
mesh->mNumVertices = numFaces*3;
aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
aiFace* faces = mesh->mFaces = new aiFace [mesh->mNumFaces = numFaces];
std::vector<aiVector3D> tempPositions(numVertices);
// now read all vertex lines
for (unsigned int i = 0; i< numVertices;++i)
{
if(!GetNextLine(buffer,line))
{
DefaultLogger::get()->error("OFF: The number of verts in the header is incorrect");
break;
}
aiVector3D& v = tempPositions[i];
sz = line; SkipSpaces(&sz);
sz = fast_atof_move(sz,(float&)v.x); SkipSpaces(&sz);
sz = fast_atof_move(sz,(float&)v.y); SkipSpaces(&sz);
fast_atof_move(sz,(float&)v.z);
}
// now read all faces lines
for (unsigned int i = 0, p = 0; i< mesh->mNumFaces;++i)
{
if(!GetNextLine(buffer,line))
{
DefaultLogger::get()->error("OFF: The number of faces in the header is incorrect");
break;
}
unsigned int idx;sz = line;SkipSpaces(&sz);
if(!(faces->mNumIndices = strtol10(sz,&sz)) || faces->mNumIndices > 100)
{
DefaultLogger::get()->error("OFF: Faces with zero indices aren't allowed");
--mesh->mNumFaces;
continue;
}
faces->mIndices = new unsigned int [faces->mNumIndices];
for (unsigned int m = 0; m < faces->mNumIndices;++m)
{
SkipSpaces(&sz);
if ((idx = strtol10(sz,&sz)) >= numVertices)
{
DefaultLogger::get()->error("OFF: Vertex index is out of range");
idx = numVertices-1;
}
faces->mIndices[m] = p++;
*verts++ = tempPositions[idx];
}
++faces;
}
// generate the output node graph
pScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("<OFFRoot>");
pScene->mRootNode->mMeshes = new unsigned int [pScene->mRootNode->mNumMeshes = 1];
pScene->mRootNode->mMeshes[0] = 0;
// generate a default material
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = 1];
MaterialHelper* pcMat = new MaterialHelper();
aiColor4D clr(0.6f,0.6f,0.6f,1.0f);
pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
pScene->mMaterials[0] = pcMat;
}

96
code/OFFLoader.h 100644
View File

@ -0,0 +1,96 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2008, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file Declaration of the OFF importer class. */
#ifndef AI_OFFLOADER_H_INCLUDED
#define AI_OFFLOADER_H_INCLUDED
#include "BaseImporter.h"
#include "../include/aiTypes.h"
#include <vector>
namespace Assimp {
// ---------------------------------------------------------------------------
/** Importer class for the Object File Format (.off)
*/
class OFFImporter : public BaseImporter
{
friend class Importer;
protected:
/** Constructor to be privately used by Importer */
OFFImporter();
/** Destructor, private as well */
~OFFImporter();
public:
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
protected:
// -------------------------------------------------------------------
/** Called by Importer::GetExtensionList() for each loaded importer.
* See BaseImporter::GetExtensionList() for details
*/
void GetExtensionList(std::string& append)
{
append.append("*.off");
}
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
private:
};
} // end of namespace Assimp
#endif // AI_3DSIMPORTER_H_IN

View File

@ -107,6 +107,21 @@ inline bool SkipSpacesAndLineEnd( const char_t** inout)
{
return SkipSpacesAndLineEnd<char_t>(*inout,inout);
}
// ---------------------------------------------------------------------------------
template <class char_t>
bool GetNextLine(const char_t*& buffer, char_t out[4096])
{
if ((char_t)'\0' == *buffer)return false;
char* _out = out;
char* const end = _out+4096;
while (!IsLineEnd( *buffer ) && _out < end)
*_out++ = *buffer++;
*_out = (char_t)'\0';
while (IsLineEnd( *buffer ) && '\0' != *buffer)++buffer;
return true;
}
#endif // ! AI_PARSING_UTILS_H_INC

330
code/RawLoader.cpp 100644
View File

@ -0,0 +1,330 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (ASSIMP)
---------------------------------------------------------------------------
Copyright (c) 2006-2008, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the RAW importer class */
// internal headers
#include "RAWLoader.h"
#include "MaterialSystem.h"
#include "ParsingUtils.h"
#include "fast_atof.h"
// public assimp headers
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
#include "../include/DefaultLogger.h"
// boost headers
#include <boost/scoped_ptr.hpp>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
RAWImporter::RAWImporter()
{
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
RAWImporter::~RAWImporter()
{
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool RAWImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
{
// simple check of file extension is enough for the moment
std::string::size_type pos = pFile.find_last_of('.');
// no file extension - can't read
if( pos == std::string::npos)return false;
std::string extension = pFile.substr( pos);
if (extension.length() < 4)return false;
if (extension[0] != '.')return false;
return !(extension.length() != 4 || extension[0] != '.' ||
extension[1] != 'r' && extension[1] != 'R' ||
extension[2] != 'a' && extension[2] != 'A' ||
extension[3] != 'w' && extension[3] != 'W');
}
// ------------------------------------------------------------------------------------------------
#define AI_RAW_IS_NON_INTEGRAL(sz) \
((*sz < '0' || *sz > '9') && *sz != '+' && *sz != '-')
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void RAWImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler)
{
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
// Check whether we can read from the file
if( file.get() == NULL)
throw new ImportErrorException( "Failed to open RAW file " + pFile + ".");
unsigned int fileSize = (unsigned int)file->FileSize();
// allocate storage and copy the contents of the file to a memory buffer
// (terminate it with zero)
std::vector<char> mBuffer2(fileSize+1);
file->Read(&mBuffer2[0], 1, fileSize);
mBuffer2[fileSize] = '\0';
const char* buffer = &mBuffer2[0];
// list of groups loaded from the file
std::vector< GroupInformation > outGroups(1,GroupInformation("<default>"));
std::vector< GroupInformation >::iterator curGroup = outGroups.begin();
// now read all lines
char line[4096];
while (GetNextLine(buffer,line))
{
// if the line starts with a non-numeric identifier, it marks
// the beginning of a new group
const char* sz = line;SkipSpaces(&sz);
if (IsLineEnd(*sz))continue;
if (AI_RAW_IS_NON_INTEGRAL(sz))
{
const char* sz2 = sz;
while (!IsSpaceOrNewLine(*sz2))++sz2;
const unsigned int length = (unsigned int)(sz2-sz);
// find an existing group with this name
for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end();
it != end;++it)
{
if (length == (*it).name.length() && !::strcmp(sz,(*it).name.c_str()))
{
curGroup = it;sz2 = NULL;
break;
}
}
if (sz2)
{
outGroups.push_back(GroupInformation(std::string(sz,length)));
curGroup = outGroups.end()-1;
}
}
else
{
// there can be maximally 12 floats plus an extra texture file name
float data[12];
unsigned int num;
for (num = 0; num < 12;++num)
{
if(!SkipSpaces(&sz) || AI_RAW_IS_NON_INTEGRAL(sz))break;
sz = fast_atof_move(sz,data[num]);
}
if (num != 12 && num != 9)
{
DefaultLogger::get()->error("A line may have either 9 or 12 floats and an optional texture");
continue;
}
MeshInformation* output = NULL;
const char* sz2 = sz;
unsigned int length;
if (!IsLineEnd(*sz))
{
while (!IsSpaceOrNewLine(*sz2))++sz2;
length = (unsigned int)(sz2-sz);
}
else if (9 == num)
{
sz = "%default%";
length = 9;
}
else
{
sz = "";
length = 0;
}
// search in the list of meshes whether we have one with this texture
for (std::vector< MeshInformation >::iterator it = (*curGroup).meshes.begin(),
end = (*curGroup).meshes.end(); it != end; ++it)
{
if (length == (*it).name.length() && (length ? !::strcmp(sz,(*it).name.c_str()) : true))
{
output = &(*it);
break;
}
}
// if we don't have the mesh, create it
if (!output)
{
(*curGroup).meshes.push_back(MeshInformation(std::string(sz,length)));
output = &((*curGroup).meshes.back());
}
if (12 == num)
{
aiColor4D v(data[0],data[1],data[2],1.0f);
output->colors.push_back(v);
output->colors.push_back(v);
output->colors.push_back(v);
output->vertices.push_back(aiVector3D(data[3],data[4],data[5]));
output->vertices.push_back(aiVector3D(data[6],data[7],data[8]));
output->vertices.push_back(aiVector3D(data[9],data[10],data[11]));
}
else
{
output->vertices.push_back(aiVector3D(data[0],data[1],data[2]));
output->vertices.push_back(aiVector3D(data[3],data[4],data[5]));
output->vertices.push_back(aiVector3D(data[6],data[7],data[8]));
}
}
}
pScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("<RawRoot>");
// count the number of valid groups
// (meshes can't be empty)
for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end();
it != end;++it)
{
if (!(*it).meshes.empty())
{
++pScene->mRootNode->mNumChildren;
pScene->mNumMeshes += (unsigned int)(*it).meshes.size();
}
}
if (!pScene->mNumMeshes)
{
throw new ImportErrorException("RAW: No meshes loaded. The file seems to be corrupt or empty.");
}
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
aiNode** cc;
if (1 == pScene->mRootNode->mNumChildren)
{
cc = &pScene->mRootNode;
pScene->mRootNode->mNumChildren = 0;
}
else cc = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
pScene->mNumMaterials = pScene->mNumMeshes;
aiMaterial** mats = pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
unsigned int meshIdx = 0;
for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end();
it != end;++it)
{
if ((*it).meshes.empty())continue;
aiNode* node;
if (pScene->mRootNode->mNumChildren)
{
node = *cc = new aiNode();
node->mParent = pScene->mRootNode;
}
else node = *cc;++cc;
node->mName.Set((*it).name);
// add all meshes
node->mNumMeshes = (unsigned int)(*it).meshes.size();
unsigned int* pi = node->mMeshes = new unsigned int[ node->mNumMeshes ];
for (std::vector< MeshInformation >::iterator it2 = (*it).meshes.begin(),
end2 = (*it).meshes.end(); it2 != end2; ++it2)
{
ai_assert(!(*it2).vertices.empty());
// allocate the mesh
*pi++ = meshIdx;
aiMesh* mesh = pScene->mMeshes[meshIdx] = new aiMesh();
mesh->mMaterialIndex = meshIdx++;
// allocate storage for the vertex components and copy them
mesh->mNumVertices = (unsigned int)(*it2).vertices.size();
mesh->mVertices = new aiVector3D[ mesh->mNumVertices ];
::memcpy(mesh->mVertices,&(*it2).vertices[0],sizeof(aiVector3D)*mesh->mNumVertices);
if ((*it2).colors.size())
{
ai_assert((*it2).colors.size() == mesh->mNumVertices);
mesh->mColors[0] = new aiColor4D[ mesh->mNumVertices ];
::memcpy(mesh->mColors[0],&(*it2).colors[0],sizeof(aiColor4D)*mesh->mNumVertices);
}
// generate triangles
ai_assert(0 == mesh->mNumVertices % 3);
aiFace* fc = mesh->mFaces = new aiFace[ mesh->mNumFaces = mesh->mNumVertices/3 ];
aiFace* const fcEnd = fc + mesh->mNumFaces;
unsigned int n = 0;
while (fc != fcEnd)
{
aiFace& f = *fc++;
f.mIndices = new unsigned int[f.mNumIndices = 3];
for (unsigned int m = 0; m < 3;++m)
f.mIndices[m] = n++;
}
// generate a material for the mesh
MaterialHelper* mat = new MaterialHelper();
aiColor4D clr(1.0f,1.0f,1.0f,1.0f);
if ("%default%" == (*it2).name) // a gray default material
{
clr.r = clr.g = clr.b = 0.6f;
}
else if ((*it2).name.length() > 0) // a texture
{
aiString s;
s.Set((*it2).name);
mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
}
mat->AddProperty<aiColor4D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
*mats++ = mat;
}
}
}

122
code/RawLoader.h 100644
View File

@ -0,0 +1,122 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2008, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file Declaration of the RAW importer class. */
#ifndef AI_RAWLOADER_H_INCLUDED
#define AI_RAWLOADER_H_INCLUDED
#include "BaseImporter.h"
#include "../include/aiTypes.h"
#include <vector>
namespace Assimp {
// ---------------------------------------------------------------------------
/** Importer class for the PovRay RAW triangle format
*/
class RAWImporter : public BaseImporter
{
friend class Importer;
protected:
/** Constructor to be privately used by Importer */
RAWImporter();
/** Destructor, private as well */
~RAWImporter();
public:
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
protected:
// -------------------------------------------------------------------
/** Called by Importer::GetExtensionList() for each loaded importer.
* See BaseImporter::GetExtensionList() for details
*/
void GetExtensionList(std::string& append)
{
append.append("*.raw");
}
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
private:
struct MeshInformation
{
MeshInformation(const std::string& _name)
: name(_name)
{
vertices.reserve(100);
colors.reserve(100);
}
std::string name;
std::vector<aiVector3D> vertices;
std::vector<aiColor4D> colors;
};
struct GroupInformation
{
GroupInformation(const std::string& _name)
: name(_name)
{
meshes.reserve(10);
}
std::string name;
std::vector<MeshInformation> meshes;
};
};
} // end of namespace Assimp
#endif // AI_3DSIMPORTER_H_IN

View File

@ -109,13 +109,12 @@ void Subdivide(std::vector<aiVector3D>& positions)
// ------------------------------------------------------------------------------------------------
void StandardShapes::MakeIcosahedron(aiVector3D& center,const aiVector3D& length,
std::vector<aiVector3D>& positions)
void StandardShapes::MakeIcosahedron(std::vector<aiVector3D>& positions)
{
positions.reserve(positions.size()+60);
const float t = (1.f + 2.236067977f)/2.f;
const aiVector3D s = aiVector3D( sqrt(1.f + t*t) ) / length;
const float s = sqrt(1.f + t*t);
aiVector3D v0 = aiVector3D(t,1.f, 0.f)/s;
aiVector3D v1 = aiVector3D(-t,1.f, 0.f)/s;
@ -157,8 +156,7 @@ void StandardShapes::MakeIcosahedron(aiVector3D& center,const aiVector3D& length
}
// ------------------------------------------------------------------------------------------------
void StandardShapes::MakeDodecahedron(aiVector3D& center,const aiVector3D& length,
std::vector<aiVector3D>& positions)
void StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions)
{
positions.reserve(positions.size()+108);
@ -166,26 +164,26 @@ void StandardShapes::MakeDodecahedron(aiVector3D& center,const aiVector3D& lengt
const float b = sqrt((3.f-2.23606797f)/6.f);
const float c = sqrt((3.f+2.23606797f)/6.f);
aiVector3D v0 = aiVector3D(a,a,a).SymMul(length);
aiVector3D v1 = aiVector3D(a,a,-a).SymMul(length);
aiVector3D v2 = aiVector3D(a,-a,a).SymMul(length);
aiVector3D v3 = aiVector3D(a,-a,-a).SymMul(length);
aiVector3D v4 = aiVector3D(-a,a,a).SymMul(length);
aiVector3D v5 = aiVector3D(-a,a,-a).SymMul(length);
aiVector3D v6 = aiVector3D(-a,-a,a).SymMul(length);
aiVector3D v7 = aiVector3D(-a,-a,-a).SymMul(length);
aiVector3D v8 = aiVector3D(b,c,0.f).SymMul(length);
aiVector3D v9 = aiVector3D(-b,c,0.f).SymMul(length);
aiVector3D v10 = aiVector3D(b,-c,0.f).SymMul(length);
aiVector3D v11 = aiVector3D(-b,-c,0.f).SymMul(length);
aiVector3D v12 = aiVector3D(c, 0.f, b).SymMul(length);
aiVector3D v13 = aiVector3D(c, 0.f, -b).SymMul(length);
aiVector3D v14 = aiVector3D(-c, 0.f, b).SymMul(length);
aiVector3D v15 = aiVector3D(-c, 0.f, -b).SymMul(length);
aiVector3D v16 = aiVector3D(0.f, b, c).SymMul(length);
aiVector3D v17 = aiVector3D(0.f, -b, c).SymMul(length);
aiVector3D v18 = aiVector3D(0.f, b, -c).SymMul(length);
aiVector3D v19 = aiVector3D(0.f, -b, -c).SymMul(length);
aiVector3D v0 = aiVector3D(a,a,a);
aiVector3D v1 = aiVector3D(a,a,-a);
aiVector3D v2 = aiVector3D(a,-a,a);
aiVector3D v3 = aiVector3D(a,-a,-a);
aiVector3D v4 = aiVector3D(-a,a,a);
aiVector3D v5 = aiVector3D(-a,a,-a);
aiVector3D v6 = aiVector3D(-a,-a,a);
aiVector3D v7 = aiVector3D(-a,-a,-a);
aiVector3D v8 = aiVector3D(b,c,0.f);
aiVector3D v9 = aiVector3D(-b,c,0.f);
aiVector3D v10 = aiVector3D(b,-c,0.f);
aiVector3D v11 = aiVector3D(-b,-c,0.f);
aiVector3D v12 = aiVector3D(c, 0.f, b);
aiVector3D v13 = aiVector3D(c, 0.f, -b);
aiVector3D v14 = aiVector3D(-c, 0.f, b);
aiVector3D v15 = aiVector3D(-c, 0.f, -b);
aiVector3D v16 = aiVector3D(0.f, b, c);
aiVector3D v17 = aiVector3D(0.f, -b, c);
aiVector3D v18 = aiVector3D(0.f, b, -c);
aiVector3D v19 = aiVector3D(0.f, -b, -c);
ADD_PENTAGON(v0, v8, v9, v4, v16);
ADD_PENTAGON(v0, v12, v13, v1, v8);
@ -203,17 +201,16 @@ void StandardShapes::MakeDodecahedron(aiVector3D& center,const aiVector3D& lengt
}
// ------------------------------------------------------------------------------------------------
void StandardShapes::MakeOctahedron(aiVector3D& center,const aiVector3D& length,
std::vector<aiVector3D>& positions)
void StandardShapes::MakeOctahedron(std::vector<aiVector3D>& positions)
{
positions.reserve(positions.size()+24);
aiVector3D v0 = aiVector3D(length.x, 0.f, 0.f) ;
aiVector3D v1 = aiVector3D(-length.x, 0.f, 0.f);
aiVector3D v2 = aiVector3D(0.f, length.y, 0.f);
aiVector3D v3 = aiVector3D(0.f, -length.y, 0.f);
aiVector3D v4 = aiVector3D(0.f, 0.f, length.z);
aiVector3D v5 = aiVector3D(0.f, 0.f, -length.z);
aiVector3D v0 = aiVector3D(1.0f, 0.f, 0.f) ;
aiVector3D v1 = aiVector3D(-1.0f, 0.f, 0.f);
aiVector3D v2 = aiVector3D(0.f, 1.0f, 0.f);
aiVector3D v3 = aiVector3D(0.f, -1.0f, 0.f);
aiVector3D v4 = aiVector3D(0.f, 0.f, 1.0f);
aiVector3D v5 = aiVector3D(0.f, 0.f, -1.0f);
ADD_TRIANGLE(v4,v0,v2);
ADD_TRIANGLE(v4,v2,v1);
@ -227,18 +224,17 @@ void StandardShapes::MakeOctahedron(aiVector3D& center,const aiVector3D& length,
}
// ------------------------------------------------------------------------------------------------
void StandardShapes::MakeTetrahedron(aiVector3D& center,const aiVector3D& length,
std::vector<aiVector3D>& positions)
void StandardShapes::MakeTetrahedron(std::vector<aiVector3D>& positions)
{
positions.reserve(positions.size()+9);
const float a = 1.41421f/3.f;
const float b = 2.4494f/3.f;
aiVector3D v0 = aiVector3D(0.f,0.f,1.f).SymMul(length);
aiVector3D v1 = aiVector3D(2*a,0,-1.f/3.f).SymMul(length);
aiVector3D v2 = aiVector3D(-a,b,-1.f/3.f).SymMul(length);
aiVector3D v3 = aiVector3D(-a,-b,-1.f/3.f).SymMul(length);
aiVector3D v0 = aiVector3D(0.f,0.f,1.f);
aiVector3D v1 = aiVector3D(2*a,0,-1.f/3.f);
aiVector3D v2 = aiVector3D(-a,b,-1.f/3.f);
aiVector3D v3 = aiVector3D(-a,-b,-1.f/3.f);
ADD_TRIANGLE(v0,v1,v2);
ADD_TRIANGLE(v0,v2,v3);
@ -247,20 +243,19 @@ void StandardShapes::MakeTetrahedron(aiVector3D& center,const aiVector3D& length
}
// ------------------------------------------------------------------------------------------------
void StandardShapes::MakeHexahedron(aiVector3D& center,const aiVector3D& length,
std::vector<aiVector3D>& positions)
void StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions)
{
positions.reserve(positions.size()+36);
aiVector3D _length = length * (1.f/1.73205080f);
float length = 1.f/1.73205080f;
aiVector3D v0 = aiVector3D(-1.f,-1.f,-1.f).SymMul(_length) ;
aiVector3D v1 = aiVector3D(1.f,-1.f,-1.f).SymMul(_length) ;
aiVector3D v2 = aiVector3D(1.f,1.f,-1.f) .SymMul(_length) ;
aiVector3D v3 = aiVector3D(-1.f,1.f,-1.f) .SymMul(_length) ;
aiVector3D v4 = aiVector3D(-1.f,-1.f,1.f) .SymMul(_length) ;
aiVector3D v5 = aiVector3D(1.f,-1.f,1.f) .SymMul(_length) ;
aiVector3D v6 = aiVector3D(1.f,1.f,1.f) .SymMul(_length) ;
aiVector3D v7 = aiVector3D(-1.f,1.f,1.f) .SymMul(_length) ;
aiVector3D v0 = aiVector3D(-1.f,-1.f,-1.f)*length;
aiVector3D v1 = aiVector3D(1.f,-1.f,-1.f)*length;
aiVector3D v2 = aiVector3D(1.f,1.f,-1.f)*length;
aiVector3D v3 = aiVector3D(-1.f,1.f,-1.f)*length;
aiVector3D v4 = aiVector3D(-1.f,-1.f,1.f)*length;
aiVector3D v5 = aiVector3D(1.f,-1.f,1.f)*length;
aiVector3D v6 = aiVector3D(1.f,1.f,1.f)*length;
aiVector3D v7 = aiVector3D(-1.f,1.f,1.f)*length;
ADD_QUAD(v0,v3,v2,v1);
ADD_QUAD(v0,v1,v5,v4);
@ -273,13 +268,10 @@ void StandardShapes::MakeHexahedron(aiVector3D& center,const aiVector3D& length,
#undef ADD_TRIANGLE
// ------------------------------------------------------------------------------------------------
void StandardShapes::MakeSphere(
aiVector3D& center,
float radius,
unsigned int tess,
void StandardShapes::MakeSphere(unsigned int tess,
std::vector<aiVector3D>& positions)
{
MakeIcosahedron(center,radius,positions);
MakeIcosahedron(positions);
for (unsigned int i = 0; i<tess;++i)
Subdivide(positions);

View File

@ -63,65 +63,48 @@ public:
/** @brief Generates a hexahedron (cube)
*
* Hexahedrons can be scaled on all axes.
* @param center Center point of the hexahedron
* @param length Radius of the hexahedron
* @param positions Receives output triangles.
*
* @note If you define AI_STANDARD_SHAPES_OUTPUT_POLYGONS quads
* instead of triangles are returned.
*/
static void MakeHexahedron(aiVector3D& center,const aiVector3D& length,
std::vector<aiVector3D>& positions);
static void MakeHexahedron(std::vector<aiVector3D>& positions);
/** @brief Generates an icosahedron
*
* @param center Center point of the icosahedron
* @param length Radius of the icosahedron
* @param positions Receives output triangles.
*/
static void MakeIcosahedron(aiVector3D& center,const aiVector3D& length,
std::vector<aiVector3D>& positions);
static void MakeIcosahedron(std::vector<aiVector3D>& positions);
/** @brief Generates a dodecahedron
*
* @param center Center point of the dodecahedron
* @param length Radius of the dodecahedron
* @param positions Receives output triangles
* @note If you define AI_STANDARD_SHAPES_OUTPUT_POLYGONS pentagons
* instead of triangles are returned.
*/
static void MakeDodecahedron(aiVector3D& center,const aiVector3D& length,
std::vector<aiVector3D>& positions);
static void MakeDodecahedron(std::vector<aiVector3D>& positions);
/** @brief Generates an octahedron
*
* @param center Center point of the octahedron
* @param length Radius of the octahedron
* @param positions Receives output triangles.
*/
static void MakeOctahedron(aiVector3D& center,const aiVector3D& length,
std::vector<aiVector3D>& positions);
static void MakeOctahedron(std::vector<aiVector3D>& positions);
/** @brief Generates a tetrahedron
*
* @param center Center point of the tetrahedron
* @param length Radius of the octahedron
* @param positions Receives output triangles.
*/
static void MakeTetrahedron(aiVector3D& center,const aiVector3D& length,
std::vector<aiVector3D>& positions);
static void MakeTetrahedron(std::vector<aiVector3D>& positions);
/** @brief Generates a sphere
*
* @param center Center point of the sphere
* @param radius Radius of the sphere
* @param tess Number of subdivions - 0 generates a octahedron
* @param positions Receives output triangles.
*/
static void MakeSphere(aiVector3D& center,float length,unsigned int tess,
static void MakeSphere(unsigned int tess,
std::vector<aiVector3D>& positions);
/** @brief Generates a cone or a cylinder, either opened or closed.
@ -167,82 +150,6 @@ public:
float radius, unsigned int tess,
std::vector<aiVector3D>& positions);
// simplified versions - the radius is a single float and applies
// to all axes. These version of the functions must be used if ou
// REALLY want a platonic primitive :-)
// ---------------------------------------------------------------------
static void MakeHexahedron(aiVector3D& center,float length,
std::vector<aiVector3D>& positions)
{
MakeHexahedron(center,aiVector3D(length),positions);
}
static void MakeDodecahedron(aiVector3D& center,float length,
std::vector<aiVector3D>& positions)
{
MakeDodecahedron(center,aiVector3D(length),positions);
}
static void MakeOctahedron(aiVector3D& center,float length,
std::vector<aiVector3D>& positions)
{
MakeOctahedron(center,aiVector3D(length),positions);
}
static void MakeTetrahedron(aiVector3D& center,float length,
std::vector<aiVector3D>& positions)
{
MakeTetrahedron(center,aiVector3D(length),positions);
}
static void MakeIcosahedron(aiVector3D& center,float length,
std::vector<aiVector3D>& positions)
{
MakeIcosahedron(center,aiVector3D(length),positions);
}
// simplified versions - radius is 1, position is 0|0|0
// ---------------------------------------------------------------------
static void MakeHexahedron(std::vector<aiVector3D>& positions)
{
aiVector3D v;
MakeHexahedron(v,1.0f,positions);
}
static void MakeDodecahedron(std::vector<aiVector3D>& positions)
{
aiVector3D v;
MakeDodecahedron(v,1.0f,positions);
}
static void MakeOctahedron(std::vector<aiVector3D>& positions)
{
aiVector3D v;
MakeOctahedron(v,1.0f,positions);
}
static void MakeTetrahedron(std::vector<aiVector3D>& positions)
{
aiVector3D v;
MakeTetrahedron(v,1.0f,positions);
}
static void MakeIcosahedron(std::vector<aiVector3D>& positions)
{
aiVector3D v;
MakeIcosahedron(v,1.0f,positions);
}
static void MakeSphere(unsigned int tess,
std::vector<aiVector3D>& positions)
{
aiVector3D v;
MakeSphere(v,1.0f,tess,positions);
}
};
} // ! Assimp

View File

@ -55,6 +55,9 @@ SOURCES = 3DSConverter.cpp \
ValidateDataStructure.cpp \
VertexTriangleAdjacency.cpp \
XFileImporter.cpp \
MDRLoader.cpp \
RawLoader.cpp \
OFFLoader.cpp \
XFileParser.cpp
OBJECTS = $(SOURCES:.cpp=.o)
@ -66,7 +69,7 @@ all: $(TARGET)
$(TARGET): $(OBJECTS)
gcc -o $@ $(OBJECTS) -shared -lstdc++
%.o:%.cpp
$(CXX) -g -Wall -c $? -o $@ -I../include -fPIC
$(CXX) -g -Wall -c $? -o $@ -I../include -I"C:\Program Files\boost\boost_1_35_0" -fPIC
clean:
rm -f $(OBJECTS) $(TARGET)

113172
test/DXFFiles/wuson.dxf 100644

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
Hans_Peter
0.5 0.5 0.5 0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0
0.1 0.0 0.0 0.0 0.0 3.0 0.0 1.0 3.0 1.0 0.0 3.0
Hans_Peter2
0.0 1.0 0.0 0.0 3.0 0.0 0.0 4.0 0.0 1.0 3.0 0.0
0.0 0.0 1.0 0.0 3.0 3.0 0.0 4.0 3.0 1.0 3.0 3.0

View File

@ -0,0 +1,12 @@
0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0 unnamed.png
0.0 0.0 3.0 0.0 1.0 3.0 1.0 0.0 3.0 unnamed.png
0.0 0.0 3.0 0.0 1.0 3.0 1.0 0.0 3.0 unnamed2.png
Hans_Peter3
0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0 test.png
0.0 0.0 3.0 0.0 1.0 3.0 1.0 0.0 3.0 test2.png
Hans_Peter4
0.0 3.0 0.0 0.0 4.0 0.0 1.0 3.0 0.0 test.png
0.0 3.0 3.0 0.0 4.0 3.0 1.0 3.0 3.0 test3.png

3732
test/RAW/Wuson.raw 100644

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1015,6 +1015,10 @@
RelativePath="..\..\code\MDRFileData.h"
>
</File>
<File
RelativePath="..\..\code\MDRLoader.h"
>
</File>
</Filter>
<Filter
Name="Obj"
@ -1095,6 +1099,10 @@
<Filter
Name="RAW"
>
<File
RelativePath="..\..\code\RawLoader.h"
>
</File>
</Filter>
<Filter
Name="NFF"
@ -1112,6 +1120,18 @@
Name="Collada"
>
</Filter>
<Filter
Name="WRL"
>
</Filter>
<Filter
Name="OFF"
>
<File
RelativePath="..\..\code\OFFLoader.h"
>
</File>
</Filter>
</Filter>
</Filter>
<Filter
@ -1415,6 +1435,10 @@
<Filter
Name="RAW"
>
<File
RelativePath="..\..\code\RawLoader.cpp"
>
</File>
</Filter>
<Filter
Name="NFF"
@ -1424,6 +1448,26 @@
>
</File>
</Filter>
<Filter
Name="MDR"
>
<File
RelativePath="..\..\code\MDRLoader.cpp"
>
</File>
</Filter>
<Filter
Name="WRL"
>
</Filter>
<Filter
Name="OFF"
>
<File
RelativePath="..\..\code\OFFLoader.cpp"
>
</File>
</Filter>
</Filter>
</Filter>
<Filter