commit
a58d0f57b3
|
@ -94,7 +94,11 @@ SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE PATH
|
||||||
SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH
|
SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH
|
||||||
"Path the tool executables are installed to." )
|
"Path the tool executables are installed to." )
|
||||||
|
|
||||||
SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools")
|
IF (CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||||
|
SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Debug Postfix for lib, samples and tools")
|
||||||
|
ELSE()
|
||||||
|
SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfix for lib, samples and tools")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
# Only generate this target if no higher-level project already has
|
# Only generate this target if no higher-level project already has
|
||||||
IF (NOT TARGET uninstall)
|
IF (NOT TARGET uninstall)
|
||||||
|
|
|
@ -89,6 +89,9 @@ static const aiImporterDesc desc = {
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// read a string (may be enclosed in double quotation marks). buffer must point to "
|
// read a string (may be enclosed in double quotation marks). buffer must point to "
|
||||||
#define AI_AC_GET_STRING(out) \
|
#define AI_AC_GET_STRING(out) \
|
||||||
|
if (*buffer == '\0') { \
|
||||||
|
throw DeadlyImportError("AC3D: Unexpected EOF in string"); \
|
||||||
|
} \
|
||||||
++buffer; \
|
++buffer; \
|
||||||
const char* sz = buffer; \
|
const char* sz = buffer; \
|
||||||
while ('\"' != *buffer) \
|
while ('\"' != *buffer) \
|
||||||
|
@ -293,7 +296,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
|
||||||
SkipSpaces(&buffer);
|
SkipSpaces(&buffer);
|
||||||
|
|
||||||
unsigned int t = strtoul10(buffer,&buffer);
|
unsigned int t = strtoul10(buffer,&buffer);
|
||||||
if (t >= std::numeric_limits<int32_t>::max() / sizeof(aiVector3D)) {
|
if (t >= AI_MAX_ALLOC(aiVector3D)) {
|
||||||
throw DeadlyImportError("AC3D: Too many vertices, would run out of memory");
|
throw DeadlyImportError("AC3D: Too many vertices, would run out of memory");
|
||||||
}
|
}
|
||||||
obj.vertices.reserve(t);
|
obj.vertices.reserve(t);
|
||||||
|
@ -349,8 +352,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
|
||||||
{
|
{
|
||||||
if(!GetNextLine())
|
if(!GetNextLine())
|
||||||
{
|
{
|
||||||
DefaultLogger::get()->error("AC3D: Unexpected EOF: surface is incomplete");
|
throw DeadlyImportError("AC3D: Unexpected EOF: surface is incomplete");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (TokenMatch(buffer,"mat",3))
|
if (TokenMatch(buffer,"mat",3))
|
||||||
{
|
{
|
||||||
|
@ -585,9 +587,19 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
|
||||||
|
|
||||||
// allocate storage for vertices and normals
|
// allocate storage for vertices and normals
|
||||||
mesh->mNumFaces = (*cit).first;
|
mesh->mNumFaces = (*cit).first;
|
||||||
|
if (mesh->mNumFaces == 0) {
|
||||||
|
throw DeadlyImportError("AC3D: No faces");
|
||||||
|
} else if (mesh->mNumFaces > AI_MAX_ALLOC(aiFace)) {
|
||||||
|
throw DeadlyImportError("AC3D: Too many faces, would run out of memory");
|
||||||
|
}
|
||||||
aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
|
aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
|
||||||
|
|
||||||
mesh->mNumVertices = (*cit).second;
|
mesh->mNumVertices = (*cit).second;
|
||||||
|
if (mesh->mNumVertices == 0) {
|
||||||
|
throw DeadlyImportError("AC3D: No vertices");
|
||||||
|
} else if (mesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) {
|
||||||
|
throw DeadlyImportError("AC3D: Too many vertices, would run out of memory");
|
||||||
|
}
|
||||||
aiVector3D* vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
aiVector3D* vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||||
unsigned int cur = 0;
|
unsigned int cur = 0;
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ struct Image;
|
||||||
// -------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
struct ID : ElemBase {
|
struct ID : ElemBase {
|
||||||
|
|
||||||
char name[24] WARN;
|
char name[1024] WARN;
|
||||||
short flag;
|
short flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <stdarg.h>
|
||||||
#include "ColladaParser.h"
|
#include "ColladaParser.h"
|
||||||
#include "fast_atof.h"
|
#include "fast_atof.h"
|
||||||
#include "ParsingUtils.h"
|
#include "ParsingUtils.h"
|
||||||
|
@ -1066,6 +1067,12 @@ void ColladaParser::ReadLight( Collada::Light& pLight)
|
||||||
pLight.mFalloffAngle = ReadFloatFromTextContent();
|
pLight.mFalloffAngle = ReadFloatFromTextContent();
|
||||||
TestClosing("hotspot_beam");
|
TestClosing("hotspot_beam");
|
||||||
}
|
}
|
||||||
|
// OpenCOLLADA extensions
|
||||||
|
// -------------------------------------------------------
|
||||||
|
else if (IsElement("decay_falloff")) {
|
||||||
|
pLight.mOuterAngle = ReadFloatFromTextContent();
|
||||||
|
TestClosing("decay_falloff");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
||||||
if( strcmp( mReader->getNodeName(), "light") == 0)
|
if( strcmp( mReader->getNodeName(), "light") == 0)
|
||||||
|
@ -1998,7 +2005,8 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSIMP_BUILD_DEBUG
|
#ifdef ASSIMP_BUILD_DEBUG
|
||||||
if (primType != Prim_TriFans && primType != Prim_TriStrips) {
|
if (primType != Prim_TriFans && primType != Prim_TriStrips &&
|
||||||
|
primType != Prim_Lines) { // this is ONLY to workaround a bug in SketchUp 15.3.331 where it writes the wrong 'count' when it writes out the 'lines'.
|
||||||
ai_assert(actualPrimitives == numPrimitives);
|
ai_assert(actualPrimitives == numPrimitives);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2108,9 +2116,15 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
|
||||||
}
|
}
|
||||||
|
|
||||||
// complain if the index count doesn't fit
|
// complain if the index count doesn't fit
|
||||||
if( expectedPointCount > 0 && indices.size() != expectedPointCount * numOffsets)
|
if( expectedPointCount > 0 && indices.size() != expectedPointCount * numOffsets) {
|
||||||
|
if (pPrimType == Prim_Lines) {
|
||||||
|
// HACK: We just fix this number since SketchUp 15.3.331 writes the wrong 'count' for 'lines'
|
||||||
|
ReportWarning( "Expected different index count in <p> element, %d instead of %d.", indices.size(), expectedPointCount * numOffsets);
|
||||||
|
pNumPrimitives = (indices.size() / numOffsets) / 2;
|
||||||
|
} else
|
||||||
ThrowException( "Expected different index count in <p> element.");
|
ThrowException( "Expected different index count in <p> element.");
|
||||||
else if( expectedPointCount == 0 && (indices.size() % numOffsets) != 0)
|
|
||||||
|
} else if( expectedPointCount == 0 && (indices.size() % numOffsets) != 0)
|
||||||
ThrowException( "Expected different index count in <p> element.");
|
ThrowException( "Expected different index count in <p> element.");
|
||||||
|
|
||||||
// find the data for all sources
|
// find the data for all sources
|
||||||
|
@ -2712,6 +2726,21 @@ AI_WONT_RETURN void ColladaParser::ThrowException( const std::string& pError) co
|
||||||
{
|
{
|
||||||
throw DeadlyImportError( boost::str( boost::format( "Collada: %s - %s") % mFileName % pError));
|
throw DeadlyImportError( boost::str( boost::format( "Collada: %s - %s") % mFileName % pError));
|
||||||
}
|
}
|
||||||
|
void ColladaParser::ReportWarning(const char* msg,...)
|
||||||
|
{
|
||||||
|
ai_assert(NULL != msg);
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args,msg);
|
||||||
|
|
||||||
|
char szBuffer[3000];
|
||||||
|
const int iLen = vsprintf(szBuffer,msg,args);
|
||||||
|
ai_assert(iLen > 0);
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Skips all data until the end node of the current element
|
// Skips all data until the end node of the current element
|
||||||
|
|
|
@ -215,6 +215,7 @@ protected:
|
||||||
protected:
|
protected:
|
||||||
/** Aborts the file reading with an exception */
|
/** Aborts the file reading with an exception */
|
||||||
AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX;
|
AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX;
|
||||||
|
void ReportWarning(const char* msg,...);
|
||||||
|
|
||||||
/** Skips all data until the end node of the current element */
|
/** Skips all data until the end node of the current element */
|
||||||
void SkipElement();
|
void SkipElement();
|
||||||
|
|
|
@ -152,8 +152,8 @@ bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index)
|
||||||
if (fDelta1_z < 0.05f * sqrtf( fDelta1_y * fDelta1_x ))return false;
|
if (fDelta1_z < 0.05f * sqrtf( fDelta1_y * fDelta1_x ))return false;
|
||||||
|
|
||||||
// now compare the volumes of the bounding boxes
|
// now compare the volumes of the bounding boxes
|
||||||
if (std::fabs(fDelta0_x * fDelta1_yz) <
|
if (std::fabs(fDelta0_x * fDelta0_y * fDelta0_z) <
|
||||||
std::fabs(fDelta1_x * fDelta1_y * fDelta1_z))
|
std::fabs(fDelta1_x * fDelta1_yz))
|
||||||
{
|
{
|
||||||
if (!DefaultLogger::isNullLogger())
|
if (!DefaultLogger::isNullLogger())
|
||||||
{
|
{
|
||||||
|
|
|
@ -602,12 +602,12 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
|
||||||
const IfcVector2& m0, const IfcVector2& m1,
|
const IfcVector2& m0, const IfcVector2& m1,
|
||||||
IfcVector2& out0, IfcVector2& out1)
|
IfcVector2& out0, IfcVector2& out1)
|
||||||
{
|
{
|
||||||
const IfcVector2& n0_to_n1 = n1 - n0;
|
const IfcVector2 n0_to_n1 = n1 - n0;
|
||||||
|
|
||||||
const IfcVector2& n0_to_m0 = m0 - n0;
|
const IfcVector2 n0_to_m0 = m0 - n0;
|
||||||
const IfcVector2& n1_to_m1 = m1 - n1;
|
const IfcVector2 n1_to_m1 = m1 - n1;
|
||||||
|
|
||||||
const IfcVector2& n0_to_m1 = m1 - n0;
|
const IfcVector2 n0_to_m1 = m1 - n0;
|
||||||
|
|
||||||
const IfcFloat e = 1e-5f;
|
const IfcFloat e = 1e-5f;
|
||||||
const IfcFloat smalle = 1e-9f;
|
const IfcFloat smalle = 1e-9f;
|
||||||
|
@ -927,7 +927,7 @@ size_t CloseWindows(ContourVector& contours,
|
||||||
IfcFloat best = static_cast<IfcFloat>(1e10);
|
IfcFloat best = static_cast<IfcFloat>(1e10);
|
||||||
IfcVector3 bestv;
|
IfcVector3 bestv;
|
||||||
|
|
||||||
const IfcVector3& world_point = minv * IfcVector3(proj_point.x,proj_point.y,0.0f);
|
const IfcVector3 world_point = minv * IfcVector3(proj_point.x,proj_point.y,0.0f);
|
||||||
|
|
||||||
BOOST_FOREACH(const TempOpening* opening, refs) {
|
BOOST_FOREACH(const TempOpening* opening, refs) {
|
||||||
BOOST_FOREACH(const IfcVector3& other, opening->wallPoints) {
|
BOOST_FOREACH(const IfcVector3& other, opening->wallPoints) {
|
||||||
|
@ -1066,7 +1066,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
|
||||||
|
|
||||||
// Project all points into the new coordinate system, collect min/max verts on the way
|
// Project all points into the new coordinate system, collect min/max verts on the way
|
||||||
BOOST_FOREACH(const IfcVector3& x, in_verts) {
|
BOOST_FOREACH(const IfcVector3& x, in_verts) {
|
||||||
const IfcVector3& vv = m * x;
|
const IfcVector3 vv = m * x;
|
||||||
// keep Z offset in the plane coordinate system. Ignoring precision issues
|
// keep Z offset in the plane coordinate system. Ignoring precision issues
|
||||||
// (which are present, of course), this should be the same value for
|
// (which are present, of course), this should be the same value for
|
||||||
// all polygon vertices (assuming the polygon is planar).
|
// all polygon vertices (assuming the polygon is planar).
|
||||||
|
@ -1144,7 +1144,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
|
||||||
std::vector<IfcVector2> contour_flat;
|
std::vector<IfcVector2> contour_flat;
|
||||||
|
|
||||||
IfcVector3 nor;
|
IfcVector3 nor;
|
||||||
const IfcMatrix4& m = ProjectOntoPlane(contour_flat, curmesh, ok, nor);
|
const IfcMatrix4 m = ProjectOntoPlane(contour_flat, curmesh, ok, nor);
|
||||||
if(!ok) {
|
if(!ok) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1227,7 +1227,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
|
||||||
|
|
||||||
bool side_flag = true;
|
bool side_flag = true;
|
||||||
if (!is_2d_source) {
|
if (!is_2d_source) {
|
||||||
const IfcVector3& face_nor = ((profile_verts[vi_total+2] - profile_verts[vi_total]) ^
|
const IfcVector3 face_nor = ((profile_verts[vi_total+2] - profile_verts[vi_total]) ^
|
||||||
(profile_verts[vi_total+1] - profile_verts[vi_total])).Normalize();
|
(profile_verts[vi_total+1] - profile_verts[vi_total])).Normalize();
|
||||||
|
|
||||||
const IfcFloat abs_dot_face_nor = std::abs(nor * face_nor);
|
const IfcFloat abs_dot_face_nor = std::abs(nor * face_nor);
|
||||||
|
@ -1242,7 +1242,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
|
||||||
for (unsigned int vi = 0, vend = profile_vertcnts[f]; vi < vend; ++vi, ++vi_total) {
|
for (unsigned int vi = 0, vend = profile_vertcnts[f]; vi < vend; ++vi, ++vi_total) {
|
||||||
const IfcVector3& x = profile_verts[vi_total];
|
const IfcVector3& x = profile_verts[vi_total];
|
||||||
|
|
||||||
const IfcVector3& v = m * x;
|
const IfcVector3 v = m * x;
|
||||||
IfcVector2 vv(v.x, v.y);
|
IfcVector2 vv(v.x, v.y);
|
||||||
|
|
||||||
//if(check_intersection) {
|
//if(check_intersection) {
|
||||||
|
@ -1322,7 +1322,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
|
||||||
MakeDisjunctWindowContours(other, temp_contour, poly);
|
MakeDisjunctWindowContours(other, temp_contour, poly);
|
||||||
if(poly.size() == 1) {
|
if(poly.size() == 1) {
|
||||||
|
|
||||||
const BoundingBox& newbb = GetBoundingBox(poly[0].outer);
|
const BoundingBox newbb = GetBoundingBox(poly[0].outer);
|
||||||
if (!BoundingBoxesOverlapping(ibb, newbb )) {
|
if (!BoundingBoxesOverlapping(ibb, newbb )) {
|
||||||
// Good guy bounding box
|
// Good guy bounding box
|
||||||
bb = newbb ;
|
bb = newbb ;
|
||||||
|
@ -1438,7 +1438,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
|
||||||
// working coordinate system.
|
// working coordinate system.
|
||||||
bool ok;
|
bool ok;
|
||||||
IfcVector3 nor;
|
IfcVector3 nor;
|
||||||
const IfcMatrix3& m = DerivePlaneCoordinateSpace(curmesh, ok, nor);
|
const IfcMatrix3 m = DerivePlaneCoordinateSpace(curmesh, ok, nor);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1686,13 +1686,13 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<p2t::Triangle*>& tris = cdt->GetTriangles();
|
const std::vector<p2t::Triangle*> tris = cdt->GetTriangles();
|
||||||
|
|
||||||
// Collect the triangles we just produced
|
// Collect the triangles we just produced
|
||||||
BOOST_FOREACH(p2t::Triangle* tri, tris) {
|
BOOST_FOREACH(p2t::Triangle* tri, tris) {
|
||||||
for(int i = 0; i < 3; ++i) {
|
for(int i = 0; i < 3; ++i) {
|
||||||
|
|
||||||
const IfcVector2& v = IfcVector2(
|
const IfcVector2 v = IfcVector2(
|
||||||
static_cast<IfcFloat>( tri->GetPoint(i)->x ),
|
static_cast<IfcFloat>( tri->GetPoint(i)->x ),
|
||||||
static_cast<IfcFloat>( tri->GetPoint(i)->y )
|
static_cast<IfcFloat>( tri->GetPoint(i)->y )
|
||||||
);
|
);
|
||||||
|
|
|
@ -954,6 +954,9 @@ inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int
|
||||||
LWO::ReferrerList& refList = mCurLayer->mPointReferrers;
|
LWO::ReferrerList& refList = mCurLayer->mPointReferrers;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
if (idx >= base->abAssigned.size()) {
|
||||||
|
throw DeadlyImportError("Bad index");
|
||||||
|
}
|
||||||
base->abAssigned[idx] = true;
|
base->abAssigned[idx] = true;
|
||||||
for (i = 0; i < numRead;++i) {
|
for (i = 0; i < numRead;++i) {
|
||||||
base->rawData[idx*base->dims+i]= data[i];
|
base->rawData[idx*base->dims+i]= data[i];
|
||||||
|
|
|
@ -783,6 +783,13 @@ void MD3Importer::InternReadFile( const std::string& pFile,
|
||||||
|
|
||||||
// Allocate output storage
|
// Allocate output storage
|
||||||
pScene->mNumMeshes = pcHeader->NUM_SURFACES;
|
pScene->mNumMeshes = pcHeader->NUM_SURFACES;
|
||||||
|
if (pcHeader->NUM_SURFACES == 0) {
|
||||||
|
throw DeadlyImportError("MD3: No surfaces");
|
||||||
|
} else if (pcHeader->NUM_SURFACES > AI_MAX_ALLOC(aiMesh)) {
|
||||||
|
// We allocate pointers but check against the size of aiMesh
|
||||||
|
// since those pointers will eventually have to point to real objects
|
||||||
|
throw DeadlyImportError("MD3: Too many surfaces, would run out of memory");
|
||||||
|
}
|
||||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||||
|
|
||||||
pScene->mNumMaterials = pcHeader->NUM_SURFACES;
|
pScene->mNumMaterials = pcHeader->NUM_SURFACES;
|
||||||
|
|
|
@ -355,6 +355,9 @@ void MDLImporter::InternReadFile_Quake1( )
|
||||||
for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i)
|
for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i)
|
||||||
{
|
{
|
||||||
union{BE_NCONST MDL::Skin* pcSkin;BE_NCONST MDL::GroupSkin* pcGroupSkin;};
|
union{BE_NCONST MDL::Skin* pcSkin;BE_NCONST MDL::GroupSkin* pcGroupSkin;};
|
||||||
|
if (szCurrent + sizeof(MDL::Skin) > this->mBuffer + this->iFileSize) {
|
||||||
|
throw DeadlyImportError("[Quake 1 MDL] Unexpected EOF");
|
||||||
|
}
|
||||||
pcSkin = (BE_NCONST MDL::Skin*)szCurrent;
|
pcSkin = (BE_NCONST MDL::Skin*)szCurrent;
|
||||||
|
|
||||||
AI_SWAP4( pcSkin->group );
|
AI_SWAP4( pcSkin->group );
|
||||||
|
|
|
@ -133,15 +133,16 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
||||||
TextFileToBuffer(file.get(),m_Buffer);
|
TextFileToBuffer(file.get(),m_Buffer);
|
||||||
|
|
||||||
// Get the model name
|
// Get the model name
|
||||||
std::string strModelName;
|
std::string modelName, folderName;
|
||||||
std::string::size_type pos = pFile.find_last_of( "\\/" );
|
std::string::size_type pos = pFile.find_last_of( "\\/" );
|
||||||
if ( pos != std::string::npos )
|
if ( pos != std::string::npos ) {
|
||||||
{
|
modelName = pFile.substr(pos+1, pFile.size() - pos - 1);
|
||||||
strModelName = pFile.substr(pos+1, pFile.size() - pos - 1);
|
folderName = pFile.substr( 0, pos );
|
||||||
|
if ( folderName.empty() ) {
|
||||||
|
pIOHandler->PushDirectory( folderName );
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
{
|
modelName = pFile;
|
||||||
strModelName = pFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// process all '\'
|
// process all '\'
|
||||||
|
@ -161,13 +162,18 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the file into a temporary representation
|
// parse the file into a temporary representation
|
||||||
ObjFileParser parser(m_Buffer, strModelName, pIOHandler);
|
ObjFileParser parser(m_Buffer, modelName, pIOHandler);
|
||||||
|
|
||||||
// And create the proper return structures out of it
|
// And create the proper return structures out of it
|
||||||
CreateDataFromImport(parser.GetModel(), pScene);
|
CreateDataFromImport(parser.GetModel(), pScene);
|
||||||
|
|
||||||
// Clean up allocated storage for the next import
|
// Clean up allocated storage for the next import
|
||||||
m_Buffer.clear();
|
m_Buffer.clear();
|
||||||
|
|
||||||
|
// Pop directory stack
|
||||||
|
if ( pIOHandler->StackSize() > 0 ) {
|
||||||
|
pIOHandler->PopDirectory();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -380,6 +386,11 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
|
||||||
|
|
||||||
// Copy vertices of this mesh instance
|
// Copy vertices of this mesh instance
|
||||||
pMesh->mNumVertices = numIndices;
|
pMesh->mNumVertices = numIndices;
|
||||||
|
if (pMesh->mNumVertices == 0) {
|
||||||
|
throw DeadlyImportError( "OBJ: no vertices" );
|
||||||
|
} else if (pMesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) {
|
||||||
|
throw DeadlyImportError( "OBJ: Too many vertices, would run out of memory" );
|
||||||
|
}
|
||||||
pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
|
pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
|
||||||
|
|
||||||
// Allocate buffer for normal vectors
|
// Allocate buffer for normal vectors
|
||||||
|
|
|
@ -61,21 +61,21 @@ const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME;
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Constructor with loaded data and directories.
|
// Constructor with loaded data and directories.
|
||||||
ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem *io ) :
|
ObjFileParser::ObjFileParser(std::vector<char> &data,const std::string &modelName, IOSystem *io ) :
|
||||||
m_DataIt(Data.begin()),
|
m_DataIt(data.begin()),
|
||||||
m_DataItEnd(Data.end()),
|
m_DataItEnd(data.end()),
|
||||||
m_pModel(NULL),
|
m_pModel(NULL),
|
||||||
m_uiLine(0),
|
m_uiLine(0),
|
||||||
m_pIO( io )
|
m_pIO( io )
|
||||||
{
|
{
|
||||||
std::fill_n(m_buffer,BUFFERSIZE,0);
|
std::fill_n(m_buffer,Buffersize,0);
|
||||||
|
|
||||||
// Create the model instance to store all the data
|
// Create the model instance to store all the data
|
||||||
m_pModel = new ObjFile::Model();
|
m_pModel = new ObjFile::Model();
|
||||||
m_pModel->m_ModelName = strModelName;
|
m_pModel->m_ModelName = modelName;
|
||||||
|
|
||||||
// create default material and store it
|
// create default material and store it
|
||||||
m_pModel->m_pDefaultMaterial = new ObjFile::Material();
|
m_pModel->m_pDefaultMaterial = new ObjFile::Material;
|
||||||
m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_MATERIAL );
|
m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_MATERIAL );
|
||||||
m_pModel->m_MaterialLib.push_back( DEFAULT_MATERIAL );
|
m_pModel->m_MaterialLib.push_back( DEFAULT_MATERIAL );
|
||||||
m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
|
m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
|
||||||
|
@ -248,20 +248,20 @@ void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
|
||||||
}
|
}
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
if( 2 == numComponents ) {
|
if( 2 == numComponents ) {
|
||||||
copyNextWord( m_buffer, BUFFERSIZE );
|
copyNextWord( m_buffer, Buffersize );
|
||||||
x = ( float ) fast_atof( m_buffer );
|
x = ( float ) fast_atof( m_buffer );
|
||||||
|
|
||||||
copyNextWord( m_buffer, BUFFERSIZE );
|
copyNextWord( m_buffer, Buffersize );
|
||||||
y = ( float ) fast_atof( m_buffer );
|
y = ( float ) fast_atof( m_buffer );
|
||||||
z = 0.0;
|
z = 0.0;
|
||||||
} else if( 3 == numComponents ) {
|
} else if( 3 == numComponents ) {
|
||||||
copyNextWord( m_buffer, BUFFERSIZE );
|
copyNextWord( m_buffer, Buffersize );
|
||||||
x = ( float ) fast_atof( m_buffer );
|
x = ( float ) fast_atof( m_buffer );
|
||||||
|
|
||||||
copyNextWord( m_buffer, BUFFERSIZE );
|
copyNextWord( m_buffer, Buffersize );
|
||||||
y = ( float ) fast_atof( m_buffer );
|
y = ( float ) fast_atof( m_buffer );
|
||||||
|
|
||||||
copyNextWord( m_buffer, BUFFERSIZE );
|
copyNextWord( m_buffer, Buffersize );
|
||||||
z = ( float ) fast_atof( m_buffer );
|
z = ( float ) fast_atof( m_buffer );
|
||||||
} else {
|
} else {
|
||||||
throw DeadlyImportError( "OBJ: Invalid number of components" );
|
throw DeadlyImportError( "OBJ: Invalid number of components" );
|
||||||
|
@ -274,13 +274,13 @@ void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
|
||||||
// Get values for a new 3D vector instance
|
// Get values for a new 3D vector instance
|
||||||
void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) {
|
void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) {
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
copyNextWord(m_buffer, BUFFERSIZE);
|
copyNextWord(m_buffer, Buffersize);
|
||||||
x = (float) fast_atof(m_buffer);
|
x = (float) fast_atof(m_buffer);
|
||||||
|
|
||||||
copyNextWord(m_buffer, BUFFERSIZE);
|
copyNextWord(m_buffer, Buffersize);
|
||||||
y = (float) fast_atof(m_buffer);
|
y = (float) fast_atof(m_buffer);
|
||||||
|
|
||||||
copyNextWord( m_buffer, BUFFERSIZE );
|
copyNextWord( m_buffer, Buffersize );
|
||||||
z = ( float ) fast_atof( m_buffer );
|
z = ( float ) fast_atof( m_buffer );
|
||||||
|
|
||||||
point3d_array.push_back( aiVector3D( x, y, z ) );
|
point3d_array.push_back( aiVector3D( x, y, z ) );
|
||||||
|
@ -291,10 +291,10 @@ void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) {
|
||||||
// Get values for a new 2D vector instance
|
// Get values for a new 2D vector instance
|
||||||
void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
|
void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
|
||||||
float x, y;
|
float x, y;
|
||||||
copyNextWord(m_buffer, BUFFERSIZE);
|
copyNextWord(m_buffer, Buffersize);
|
||||||
x = (float) fast_atof(m_buffer);
|
x = (float) fast_atof(m_buffer);
|
||||||
|
|
||||||
copyNextWord(m_buffer, BUFFERSIZE);
|
copyNextWord(m_buffer, Buffersize);
|
||||||
y = (float) fast_atof(m_buffer);
|
y = (float) fast_atof(m_buffer);
|
||||||
|
|
||||||
point2d_array.push_back(aiVector2D(x, y));
|
point2d_array.push_back(aiVector2D(x, y));
|
||||||
|
@ -306,12 +306,12 @@ void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
|
||||||
// Get values for a new face instance
|
// Get values for a new face instance
|
||||||
void ObjFileParser::getFace(aiPrimitiveType type)
|
void ObjFileParser::getFace(aiPrimitiveType type)
|
||||||
{
|
{
|
||||||
copyNextLine(m_buffer, BUFFERSIZE);
|
copyNextLine(m_buffer, Buffersize);
|
||||||
if (m_DataIt == m_DataItEnd)
|
if (m_DataIt == m_DataItEnd)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char *pPtr = m_buffer;
|
char *pPtr = m_buffer;
|
||||||
char *pEnd = &pPtr[BUFFERSIZE];
|
char *pEnd = &pPtr[Buffersize];
|
||||||
pPtr = getNextToken<char*>(pPtr, pEnd);
|
pPtr = getNextToken<char*>(pPtr, pEnd);
|
||||||
if (pPtr == pEnd || *pPtr == '\0')
|
if (pPtr == pEnd || *pPtr == '\0')
|
||||||
return;
|
return;
|
||||||
|
@ -468,8 +468,9 @@ void ObjFileParser::getMaterialDesc()
|
||||||
|
|
||||||
// Get next data for material data
|
// Get next data for material data
|
||||||
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
||||||
if (m_DataIt == m_DataItEnd)
|
if (m_DataIt == m_DataItEnd) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char *pStart = &(*m_DataIt);
|
char *pStart = &(*m_DataIt);
|
||||||
while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
|
while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
|
||||||
|
@ -483,14 +484,11 @@ void ObjFileParser::getMaterialDesc()
|
||||||
|
|
||||||
// Search for material
|
// Search for material
|
||||||
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName );
|
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName );
|
||||||
if ( it == m_pModel->m_MaterialMap.end() )
|
if ( it == m_pModel->m_MaterialMap.end() ) {
|
||||||
{
|
|
||||||
// Not found, use default material
|
// Not found, use default material
|
||||||
m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
|
m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
|
||||||
DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
|
DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Found, using detected material
|
// Found, using detected material
|
||||||
m_pModel->m_pCurrentMaterial = (*it).second;
|
m_pModel->m_pCurrentMaterial = (*it).second;
|
||||||
if ( needsNewMesh( strName ))
|
if ( needsNewMesh( strName ))
|
||||||
|
@ -539,10 +537,16 @@ void ObjFileParser::getMaterialLib()
|
||||||
|
|
||||||
// Check for existence
|
// Check for existence
|
||||||
const std::string strMatName(pStart, &(*m_DataIt));
|
const std::string strMatName(pStart, &(*m_DataIt));
|
||||||
IOStream *pFile = m_pIO->Open(strMatName);
|
std::string absName;
|
||||||
|
if ( m_pIO->StackSize() > 0 ) {
|
||||||
|
const std::string &path = m_pIO->CurrentDirectory();
|
||||||
|
absName = path + strMatName;
|
||||||
|
} else {
|
||||||
|
absName = strMatName;
|
||||||
|
}
|
||||||
|
IOStream *pFile = m_pIO->Open( absName );
|
||||||
|
|
||||||
if (!pFile )
|
if (!pFile ) {
|
||||||
{
|
|
||||||
DefaultLogger::get()->error( "OBJ: Unable to locate material file " + strMatName );
|
DefaultLogger::get()->error( "OBJ: Unable to locate material file " + strMatName );
|
||||||
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -62,10 +62,9 @@ class IOSystem;
|
||||||
|
|
||||||
/// \class ObjFileParser
|
/// \class ObjFileParser
|
||||||
/// \brief Parser for a obj waveform file
|
/// \brief Parser for a obj waveform file
|
||||||
class ObjFileParser
|
class ObjFileParser {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
static const size_t BUFFERSIZE = 4096;
|
static const size_t Buffersize = 4096;
|
||||||
typedef std::vector<char> DataArray;
|
typedef std::vector<char> DataArray;
|
||||||
typedef std::vector<char>::iterator DataArrayIt;
|
typedef std::vector<char>::iterator DataArrayIt;
|
||||||
typedef std::vector<char>::const_iterator ConstDataArrayIt;
|
typedef std::vector<char>::const_iterator ConstDataArrayIt;
|
||||||
|
@ -137,9 +136,10 @@ private:
|
||||||
//! Current line (for debugging)
|
//! Current line (for debugging)
|
||||||
unsigned int m_uiLine;
|
unsigned int m_uiLine;
|
||||||
//! Helper buffer
|
//! Helper buffer
|
||||||
char m_buffer[BUFFERSIZE];
|
char m_buffer[Buffersize];
|
||||||
/// Pointer to IO system instance.
|
/// Pointer to IO system instance.
|
||||||
IOSystem *m_pIO;
|
IOSystem *m_pIO;
|
||||||
|
/// Path to the current model
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace Assimp
|
} // Namespace Assimp
|
||||||
|
|
|
@ -63,23 +63,23 @@ static const aiImporterDesc desc = {
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Grammar {
|
namespace Grammar {
|
||||||
static const char *MetricType = "Metric";
|
static const std::string MetricType = "Metric";
|
||||||
static const char *Metric_DistanceType = "distance";
|
static const std::string Metric_DistanceType = "distance";
|
||||||
static const char *Metric_AngleType = "angle";
|
static const std::string Metric_AngleType = "angle";
|
||||||
static const char *Metric_TimeType = "time";
|
static const std::string Metric_TimeType = "time";
|
||||||
static const char *Metric_UpType = "up";
|
static const std::string Metric_UpType = "up";
|
||||||
static const char *NameType = "Name";
|
static const std::string NameType = "Name";
|
||||||
static const char *ObjectRefType = "ObjectRef";
|
static const std::string ObjectRefType = "ObjectRef";
|
||||||
static const char *MaterialRefType = "MaterialRef";
|
static const std::string MaterialRefType = "MaterialRef";
|
||||||
static const char *MetricKeyType = "key";
|
static const std::string MetricKeyType = "key";
|
||||||
static const char *GeometryNodeType = "GeometryNode";
|
static const std::string GeometryNodeType = "GeometryNode";
|
||||||
static const char *GeometryObjectType = "GeometryObject";
|
static const std::string GeometryObjectType = "GeometryObject";
|
||||||
static const char *TransformType = "Transform";
|
static const std::string TransformType = "Transform";
|
||||||
static const char *MeshType = "Mesh";
|
static const std::string MeshType = "Mesh";
|
||||||
static const char *VertexArrayType = "VertexArray";
|
static const std::string VertexArrayType = "VertexArray";
|
||||||
static const char *IndexArrayType = "IndexArray";
|
static const std::string IndexArrayType = "IndexArray";
|
||||||
static const char *MaterialType = "Material";
|
static const std::string MaterialType = "Material";
|
||||||
static const char *ColorType = "Color";
|
static const std::string ColorType = "Color";
|
||||||
static const std::string DiffuseColorToken = "diffuse";
|
static const std::string DiffuseColorToken = "diffuse";
|
||||||
static const std::string SpecularColorToken = "specular";
|
static const std::string SpecularColorToken = "specular";
|
||||||
static const std::string EmissionColorToken = "emission";
|
static const std::string EmissionColorToken = "emission";
|
||||||
|
@ -112,7 +112,7 @@ namespace Grammar {
|
||||||
TextureToken
|
TextureToken
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *ValidMetricToken[ 4 ] = {
|
static const std::string ValidMetricToken[ 4 ] = {
|
||||||
Metric_DistanceType,
|
Metric_DistanceType,
|
||||||
Metric_AngleType,
|
Metric_AngleType,
|
||||||
Metric_TimeType,
|
Metric_TimeType,
|
||||||
|
@ -126,7 +126,7 @@ namespace Grammar {
|
||||||
|
|
||||||
int idx( -1 );
|
int idx( -1 );
|
||||||
for( size_t i = 0; i < 4; i++ ) {
|
for( size_t i = 0; i < 4; i++ ) {
|
||||||
if( 0 == strncmp( ValidMetricToken[ i ], token, strlen( token ) ) ) {
|
if( ValidMetricToken[ i ] == token ) {
|
||||||
idx = (int) i;
|
idx = (int) i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -136,45 +136,33 @@ namespace Grammar {
|
||||||
}
|
}
|
||||||
|
|
||||||
static TokenType matchTokenType( const char *tokenType ) {
|
static TokenType matchTokenType( const char *tokenType ) {
|
||||||
if( 0 == strncmp( MetricType, tokenType, strlen( MetricType ) ) ) {
|
if( MetricType == tokenType ) {
|
||||||
return MetricToken;
|
return MetricToken;
|
||||||
} else if( 0 == strncmp( NameType, tokenType, strlen( NameType ) ) ) {
|
} else if( NameType == tokenType ) {
|
||||||
return NameToken;
|
return NameToken;
|
||||||
}
|
} else if( ObjectRefType == tokenType ) {
|
||||||
else if( 0 == strncmp( ObjectRefType, tokenType, strlen( ObjectRefType ) ) ) {
|
|
||||||
return ObjectRefToken;
|
return ObjectRefToken;
|
||||||
}
|
} else if( MaterialRefType == tokenType ) {
|
||||||
else if( 0 == strncmp( MaterialRefType, tokenType, strlen( MaterialRefType ) ) ) {
|
|
||||||
return MaterialRefToken;
|
return MaterialRefToken;
|
||||||
}
|
} else if( MetricKeyType == tokenType ) {
|
||||||
else if( 0 == strncmp( MetricKeyType, tokenType, strlen( MetricKeyType ) ) ) {
|
|
||||||
return MetricKeyToken;
|
return MetricKeyToken;
|
||||||
}
|
} else if( GeometryNodeType == tokenType ) {
|
||||||
else if( 0 == strncmp( GeometryNodeType, tokenType, strlen( GeometryNodeType ) ) ) {
|
|
||||||
return GeometryNodeToken;
|
return GeometryNodeToken;
|
||||||
}
|
} else if( GeometryObjectType == tokenType ) {
|
||||||
else if( 0 == strncmp( GeometryObjectType, tokenType, strlen( GeometryObjectType ) ) ) {
|
|
||||||
return GeometryObjectToken;
|
return GeometryObjectToken;
|
||||||
}
|
} else if( TransformType == tokenType ) {
|
||||||
else if( 0 == strncmp( TransformType, tokenType, strlen( TransformType ) ) ) {
|
|
||||||
return TransformToken;
|
return TransformToken;
|
||||||
}
|
} else if( MeshType == tokenType ) {
|
||||||
else if( 0 == strncmp( MeshType, tokenType, strlen( MeshType ) ) ) {
|
|
||||||
return MeshToken;
|
return MeshToken;
|
||||||
}
|
} else if( VertexArrayType == tokenType ) {
|
||||||
else if( 0 == strncmp( VertexArrayType, tokenType, strlen( VertexArrayType ) ) ) {
|
|
||||||
return VertexArrayToken;
|
return VertexArrayToken;
|
||||||
}
|
} else if( IndexArrayType == tokenType ) {
|
||||||
else if( 0 == strncmp( IndexArrayType, tokenType, strlen( IndexArrayType ) ) ) {
|
|
||||||
return IndexArrayToken;
|
return IndexArrayToken;
|
||||||
}
|
} else if( MaterialType == tokenType ) {
|
||||||
else if( 0 == strncmp( MaterialType, tokenType, strlen( MaterialType ) ) ) {
|
|
||||||
return MaterialToken;
|
return MaterialToken;
|
||||||
}
|
} else if( ColorType == tokenType ) {
|
||||||
else if( 0 == strncmp( ColorType, tokenType, strlen( ColorType ) ) ) {
|
|
||||||
return ColorToken;
|
return ColorToken;
|
||||||
}
|
} else if( TextureType == tokenType ) {
|
||||||
else if( 0 == strncmp( TextureType, tokenType, strlen( TextureType ) ) ) {
|
|
||||||
return TextureToken;
|
return TextureToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,7 +189,12 @@ PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool bina
|
||||||
}
|
}
|
||||||
|
|
||||||
mOutput << "element face " << faces << endl;
|
mOutput << "element face " << faces << endl;
|
||||||
mOutput << "property list uint uint vertex_index" << endl;
|
|
||||||
|
// uchar seems to be the most common type for the number of indices per polygon and int seems to be most common for the vertex indices.
|
||||||
|
// For instance, MeshLab fails to load meshes in which both types are uint. Houdini seems to have problems as well.
|
||||||
|
// Obviously, using uchar will not work for meshes with polygons with more than 255 indices, but how realistic is this case?
|
||||||
|
mOutput << "property list uchar int vertex_index" << endl;
|
||||||
|
|
||||||
mOutput << "end_header" << endl;
|
mOutput << "end_header" << endl;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||||
|
@ -342,16 +347,24 @@ void PlyExporter::WriteMeshIndices(const aiMesh* m, unsigned int offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlyExporter::WriteMeshIndicesBinary(const aiMesh* m, unsigned int offset)
|
// Generic method in case we want to use different data types for the indices or make this configurable.
|
||||||
|
template<typename NumIndicesType, typename IndexType>
|
||||||
|
void WriteMeshIndicesBinary_Generic(const aiMesh* m, unsigned int offset, std::ostringstream& output)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < m->mNumFaces; ++i) {
|
for (unsigned int i = 0; i < m->mNumFaces; ++i) {
|
||||||
const aiFace& f = m->mFaces[i];
|
const aiFace& f = m->mFaces[i];
|
||||||
mOutput.write(reinterpret_cast<const char*>(&f.mNumIndices), 4);
|
NumIndicesType numIndices = static_cast<NumIndicesType>(f.mNumIndices);
|
||||||
|
output.write(reinterpret_cast<const char*>(&numIndices), sizeof(NumIndicesType));
|
||||||
for (unsigned int c = 0; c < f.mNumIndices; ++c) {
|
for (unsigned int c = 0; c < f.mNumIndices; ++c) {
|
||||||
unsigned int index = f.mIndices[c] + offset;
|
IndexType index = f.mIndices[c] + offset;
|
||||||
mOutput.write(reinterpret_cast<const char*>(&index), 4);
|
output.write(reinterpret_cast<const char*>(&index), sizeof(IndexType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlyExporter::WriteMeshIndicesBinary(const aiMesh* m, unsigned int offset)
|
||||||
|
{
|
||||||
|
WriteMeshIndicesBinary_Generic<unsigned char, int>(m, offset, mOutput);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -310,6 +310,10 @@ void PLYImporter::ConvertMeshes(std::vector<PLY::Face>* avFaces,
|
||||||
iNum += (unsigned int)(*avFaces)[aiSplit[p][i]].mIndices.size();
|
iNum += (unsigned int)(*avFaces)[aiSplit[p][i]].mIndices.size();
|
||||||
}
|
}
|
||||||
p_pcOut->mNumVertices = iNum;
|
p_pcOut->mNumVertices = iNum;
|
||||||
|
if( 0 == iNum ) { // nothing to do
|
||||||
|
delete[] aiSplit; // cleanup
|
||||||
|
return;
|
||||||
|
}
|
||||||
p_pcOut->mVertices = new aiVector3D[iNum];
|
p_pcOut->mVertices = new aiVector3D[iNum];
|
||||||
|
|
||||||
if (!avColors->empty())
|
if (!avColors->empty())
|
||||||
|
@ -335,20 +339,25 @@ void PLYImporter::ConvertMeshes(std::vector<PLY::Face>* avFaces,
|
||||||
for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q)
|
for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q)
|
||||||
{
|
{
|
||||||
p_pcOut->mFaces[iNum].mIndices[q] = iVertex;
|
p_pcOut->mFaces[iNum].mIndices[q] = iVertex;
|
||||||
p_pcOut->mVertices[iVertex] = (*avPositions)[(*avFaces)[*i].mIndices[q]];
|
const size_t idx = ( *avFaces )[ *i ].mIndices[ q ];
|
||||||
|
if( idx >= ( *avPositions ).size() ) {
|
||||||
|
// out of border
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
p_pcOut->mVertices[ iVertex ] = ( *avPositions )[ idx ];
|
||||||
|
|
||||||
if (!avColors->empty())
|
if (!avColors->empty())
|
||||||
p_pcOut->mColors[0][iVertex] = (*avColors)[(*avFaces)[*i].mIndices[q]];
|
p_pcOut->mColors[ 0 ][ iVertex ] = ( *avColors )[ idx ];
|
||||||
|
|
||||||
if (!avTexCoords->empty())
|
if (!avTexCoords->empty())
|
||||||
{
|
{
|
||||||
const aiVector2D& vec = (*avTexCoords)[(*avFaces)[*i].mIndices[q]];
|
const aiVector2D& vec = ( *avTexCoords )[ idx ];
|
||||||
p_pcOut->mTextureCoords[0][iVertex].x = vec.x;
|
p_pcOut->mTextureCoords[0][iVertex].x = vec.x;
|
||||||
p_pcOut->mTextureCoords[0][iVertex].y = vec.y;
|
p_pcOut->mTextureCoords[0][iVertex].y = vec.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!avNormals->empty())
|
if (!avNormals->empty())
|
||||||
p_pcOut->mNormals[iVertex] = (*avNormals)[(*avFaces)[*i].mIndices[q]];
|
p_pcOut->mNormals[ iVertex ] = ( *avNormals )[ idx ];
|
||||||
iVertex++;
|
iVertex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,8 +75,9 @@ static const aiImporterDesc desc = {
|
||||||
// 2) 4 byte face count
|
// 2) 4 byte face count
|
||||||
// 3) 50 bytes per face
|
// 3) 50 bytes per face
|
||||||
bool IsBinarySTL(const char* buffer, unsigned int fileSize) {
|
bool IsBinarySTL(const char* buffer, unsigned int fileSize) {
|
||||||
if (fileSize < 84)
|
if( fileSize < 84 ) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const uint32_t faceCount = *reinterpret_cast<const uint32_t*>(buffer + 80);
|
const uint32_t faceCount = *reinterpret_cast<const uint32_t*>(buffer + 80);
|
||||||
const uint32_t expectedBinaryFileSize = faceCount * 50 + 84;
|
const uint32_t expectedBinaryFileSize = faceCount * 50 + 84;
|
||||||
|
@ -99,7 +100,20 @@ bool IsAsciiSTL(const char* buffer, unsigned int fileSize) {
|
||||||
if (buffer + 5 >= bufferEnd)
|
if (buffer + 5 >= bufferEnd)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return strncmp(buffer, "solid", 5) == 0;
|
bool isASCII( strncmp( buffer, "solid", 5 ) == 0 );
|
||||||
|
if( isASCII ) {
|
||||||
|
// A lot of importers are write solid even if the file is binary. So we have to check for ASCII-characters.
|
||||||
|
if( fileSize >= 500 ) {
|
||||||
|
isASCII = true;
|
||||||
|
for( unsigned int i = 0; i < 500; i++ ) {
|
||||||
|
if( buffer[ i ] > 127 ) {
|
||||||
|
isASCII = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isASCII;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -122,23 +136,37 @@ bool STLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
|
||||||
{
|
{
|
||||||
const std::string extension = GetExtension(pFile);
|
const std::string extension = GetExtension(pFile);
|
||||||
|
|
||||||
if (extension == "stl")
|
if( extension == "stl" ) {
|
||||||
return true;
|
return true;
|
||||||
else if (!extension.length() || checkSig) {
|
} else if (!extension.length() || checkSig) {
|
||||||
if (!pIOHandler)
|
if( !pIOHandler ) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
const char* tokens[] = {"STL","solid"};
|
const char* tokens[] = {"STL","solid"};
|
||||||
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2);
|
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const aiImporterDesc* STLImporter::GetInfo () const
|
const aiImporterDesc* STLImporter::GetInfo () const {
|
||||||
{
|
|
||||||
return &desc;
|
return &desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addFacesToMesh(aiMesh* pMesh)
|
||||||
|
{
|
||||||
|
pMesh->mFaces = new aiFace[pMesh->mNumFaces];
|
||||||
|
for (unsigned int i = 0, p = 0; i < pMesh->mNumFaces;++i) {
|
||||||
|
|
||||||
|
aiFace& face = pMesh->mFaces[i];
|
||||||
|
face.mIndices = new unsigned int[face.mNumIndices = 3];
|
||||||
|
for (unsigned int o = 0; o < 3;++o,++p) {
|
||||||
|
face.mIndices[o] = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Imports the given file into the given scene structure.
|
// Imports the given file into the given scene structure.
|
||||||
void STLImporter::InternReadFile( const std::string& pFile,
|
void STLImporter::InternReadFile( const std::string& pFile,
|
||||||
|
@ -164,17 +192,8 @@ void STLImporter::InternReadFile( const std::string& pFile,
|
||||||
// the default vertex color is light gray.
|
// the default vertex color is light gray.
|
||||||
clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = 0.6f;
|
clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = 0.6f;
|
||||||
|
|
||||||
// allocate one mesh
|
|
||||||
pScene->mNumMeshes = 1;
|
|
||||||
pScene->mMeshes = new aiMesh*[1];
|
|
||||||
aiMesh* pMesh = pScene->mMeshes[0] = new aiMesh();
|
|
||||||
pMesh->mMaterialIndex = 0;
|
|
||||||
|
|
||||||
// allocate a single node
|
// allocate a single node
|
||||||
pScene->mRootNode = new aiNode();
|
pScene->mRootNode = new aiNode();
|
||||||
pScene->mRootNode->mNumMeshes = 1;
|
|
||||||
pScene->mRootNode->mMeshes = new unsigned int[1];
|
|
||||||
pScene->mRootNode->mMeshes[0] = 0;
|
|
||||||
|
|
||||||
bool bMatClr = false;
|
bool bMatClr = false;
|
||||||
|
|
||||||
|
@ -186,16 +205,11 @@ void STLImporter::InternReadFile( const std::string& pFile,
|
||||||
throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + ".");
|
throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
// now copy faces
|
// add all created meshes to the single node
|
||||||
pMesh->mFaces = new aiFace[pMesh->mNumFaces];
|
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
|
||||||
for (unsigned int i = 0, p = 0; i < pMesh->mNumFaces;++i) {
|
pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
|
||||||
|
for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
|
||||||
aiFace& face = pMesh->mFaces[i];
|
pScene->mRootNode->mMeshes[i] = i;
|
||||||
face.mIndices = new unsigned int[face.mNumIndices = 3];
|
|
||||||
for (unsigned int o = 0; o < 3;++o,++p) {
|
|
||||||
face.mIndices[o] = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a single default material, using a light gray diffuse color for consistency with
|
// create a single default material, using a light gray diffuse color for consistency with
|
||||||
// other geometric types (e.g., PLY).
|
// other geometric types (e.g., PLY).
|
||||||
|
@ -221,9 +235,24 @@ void STLImporter::InternReadFile( const std::string& pFile,
|
||||||
// Read an ASCII STL file
|
// Read an ASCII STL file
|
||||||
void STLImporter::LoadASCIIFile()
|
void STLImporter::LoadASCIIFile()
|
||||||
{
|
{
|
||||||
aiMesh* pMesh = pScene->mMeshes[0];
|
std::vector<aiMesh*> meshes;
|
||||||
|
|
||||||
const char* sz = mBuffer;
|
const char* sz = mBuffer;
|
||||||
|
const char* bufferEnd = mBuffer + fileSize;
|
||||||
|
std::vector<aiVector3D> positionBuffer;
|
||||||
|
std::vector<aiVector3D> normalBuffer;
|
||||||
|
|
||||||
|
// try to guess how many vertices we could have
|
||||||
|
// assume we'll need 160 bytes for each face
|
||||||
|
size_t sizeEstimate = std::max(1u, fileSize / 160u ) * 3;
|
||||||
|
positionBuffer.reserve(sizeEstimate);
|
||||||
|
normalBuffer.reserve(sizeEstimate);
|
||||||
|
|
||||||
|
while (IsAsciiSTL(sz, bufferEnd - sz))
|
||||||
|
{
|
||||||
|
aiMesh* pMesh = new aiMesh();
|
||||||
|
pMesh->mMaterialIndex = 0;
|
||||||
|
meshes.push_back(pMesh);
|
||||||
|
|
||||||
SkipSpaces(&sz);
|
SkipSpaces(&sz);
|
||||||
ai_assert(!IsLineEnd(sz));
|
ai_assert(!IsLineEnd(sz));
|
||||||
|
|
||||||
|
@ -247,13 +276,7 @@ void STLImporter::LoadASCIIFile()
|
||||||
}
|
}
|
||||||
else pScene->mRootNode->mName.Set("<STL_ASCII>");
|
else pScene->mRootNode->mName.Set("<STL_ASCII>");
|
||||||
|
|
||||||
// try to guess how many vertices we could have
|
unsigned int faceVertexCounter = 0;
|
||||||
// assume we'll need 160 bytes for each face
|
|
||||||
pMesh->mNumVertices = ( pMesh->mNumFaces = std::max(1u,fileSize / 160u )) * 3;
|
|
||||||
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
|
|
||||||
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
|
||||||
|
|
||||||
unsigned int curFace = 0, curVertex = 3;
|
|
||||||
for ( ;; )
|
for ( ;; )
|
||||||
{
|
{
|
||||||
// go to the next token
|
// go to the next token
|
||||||
|
@ -264,42 +287,25 @@ void STLImporter::LoadASCIIFile()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// facet normal -0.13 -0.13 -0.98
|
// facet normal -0.13 -0.13 -0.98
|
||||||
if (!strncmp(sz,"facet",5) && IsSpaceOrNewLine(*(sz+5))) {
|
if (!strncmp(sz,"facet",5) && IsSpaceOrNewLine(*(sz+5)) && *(sz + 5) != '\0') {
|
||||||
|
|
||||||
if (3 != curVertex) {
|
if (faceVertexCounter != 3) {
|
||||||
DefaultLogger::get()->warn("STL: A new facet begins but the old is not yet complete");
|
DefaultLogger::get()->warn("STL: A new facet begins but the old is not yet complete");
|
||||||
}
|
}
|
||||||
if (pMesh->mNumFaces == curFace) {
|
faceVertexCounter = 0;
|
||||||
ai_assert(pMesh->mNumFaces != 0);
|
normalBuffer.push_back(aiVector3D());
|
||||||
|
aiVector3D* vn = &normalBuffer.back();
|
||||||
// need to resize the arrays, our size estimate was wrong
|
|
||||||
unsigned int iNeededSize = (unsigned int)(sz-mBuffer) / pMesh->mNumFaces;
|
|
||||||
if (iNeededSize <= 160)iNeededSize >>= 1; // prevent endless looping
|
|
||||||
unsigned int add = (unsigned int)((mBuffer+fileSize)-sz) / iNeededSize;
|
|
||||||
add += add >> 3; // add 12.5% as buffer
|
|
||||||
iNeededSize = (pMesh->mNumFaces + add)*3;
|
|
||||||
aiVector3D* pv = new aiVector3D[iNeededSize];
|
|
||||||
memcpy(pv,pMesh->mVertices,pMesh->mNumVertices*sizeof(aiVector3D));
|
|
||||||
delete[] pMesh->mVertices;
|
|
||||||
pMesh->mVertices = pv;
|
|
||||||
pv = new aiVector3D[iNeededSize];
|
|
||||||
memcpy(pv,pMesh->mNormals,pMesh->mNumVertices*sizeof(aiVector3D));
|
|
||||||
delete[] pMesh->mNormals;
|
|
||||||
pMesh->mNormals = pv;
|
|
||||||
|
|
||||||
pMesh->mNumVertices = iNeededSize;
|
|
||||||
pMesh->mNumFaces += add;
|
|
||||||
}
|
|
||||||
aiVector3D* vn = &pMesh->mNormals[curFace++*3];
|
|
||||||
|
|
||||||
sz += 6;
|
sz += 6;
|
||||||
curVertex = 0;
|
|
||||||
SkipSpaces(&sz);
|
SkipSpaces(&sz);
|
||||||
if (strncmp(sz,"normal",6)) {
|
if (strncmp(sz,"normal",6)) {
|
||||||
DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found");
|
DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (sz[6] == '\0') {
|
||||||
|
throw DeadlyImportError("STL: unexpected EOF while parsing facet");
|
||||||
|
}
|
||||||
sz += 7;
|
sz += 7;
|
||||||
SkipSpaces(&sz);
|
SkipSpaces(&sz);
|
||||||
sz = fast_atoreal_move<float>(sz, (float&)vn->x );
|
sz = fast_atoreal_move<float>(sz, (float&)vn->x );
|
||||||
|
@ -307,30 +313,39 @@ void STLImporter::LoadASCIIFile()
|
||||||
sz = fast_atoreal_move<float>(sz, (float&)vn->y );
|
sz = fast_atoreal_move<float>(sz, (float&)vn->y );
|
||||||
SkipSpaces(&sz);
|
SkipSpaces(&sz);
|
||||||
sz = fast_atoreal_move<float>(sz, (float&)vn->z );
|
sz = fast_atoreal_move<float>(sz, (float&)vn->z );
|
||||||
*(vn+1) = *vn;
|
normalBuffer.push_back(*vn);
|
||||||
*(vn+2) = *vn;
|
normalBuffer.push_back(*vn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// vertex 1.50000 1.50000 0.00000
|
// vertex 1.50000 1.50000 0.00000
|
||||||
else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6)))
|
else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6)))
|
||||||
{
|
{
|
||||||
if (3 == curVertex) {
|
if (faceVertexCounter >= 3) {
|
||||||
DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found");
|
DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found");
|
||||||
++sz;
|
++sz;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (sz[6] == '\0') {
|
||||||
|
throw DeadlyImportError("STL: unexpected EOF while parsing facet");
|
||||||
|
}
|
||||||
sz += 7;
|
sz += 7;
|
||||||
SkipSpaces(&sz);
|
SkipSpaces(&sz);
|
||||||
aiVector3D* vn = &pMesh->mVertices[(curFace-1)*3 + curVertex++];
|
positionBuffer.push_back(aiVector3D());
|
||||||
|
aiVector3D* vn = &positionBuffer.back();
|
||||||
sz = fast_atoreal_move<float>(sz, (float&)vn->x );
|
sz = fast_atoreal_move<float>(sz, (float&)vn->x );
|
||||||
SkipSpaces(&sz);
|
SkipSpaces(&sz);
|
||||||
sz = fast_atoreal_move<float>(sz, (float&)vn->y );
|
sz = fast_atoreal_move<float>(sz, (float&)vn->y );
|
||||||
SkipSpaces(&sz);
|
SkipSpaces(&sz);
|
||||||
sz = fast_atoreal_move<float>(sz, (float&)vn->z );
|
sz = fast_atoreal_move<float>(sz, (float&)vn->z );
|
||||||
|
faceVertexCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!::strncmp(sz,"endsolid",8)) {
|
else if (!::strncmp(sz,"endsolid",8)) {
|
||||||
|
do {
|
||||||
|
++sz;
|
||||||
|
} while (!::IsLineEnd(*sz));
|
||||||
|
SkipSpacesAndLineEnd(&sz);
|
||||||
// finished!
|
// finished!
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -342,19 +357,49 @@ void STLImporter::LoadASCIIFile()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!curFace) {
|
if (positionBuffer.empty()) {
|
||||||
pMesh->mNumFaces = 0;
|
pMesh->mNumFaces = 0;
|
||||||
throw DeadlyImportError("STL: ASCII file is empty or invalid; no data loaded");
|
throw DeadlyImportError("STL: ASCII file is empty or invalid; no data loaded");
|
||||||
}
|
}
|
||||||
pMesh->mNumFaces = curFace;
|
if (positionBuffer.size() % 3 != 0) {
|
||||||
pMesh->mNumVertices = curFace*3;
|
pMesh->mNumFaces = 0;
|
||||||
// we are finished!
|
throw DeadlyImportError("STL: Invalid number of vertices");
|
||||||
|
}
|
||||||
|
if (normalBuffer.size() != positionBuffer.size()) {
|
||||||
|
pMesh->mNumFaces = 0;
|
||||||
|
throw DeadlyImportError("Normal buffer size does not match position buffer size");
|
||||||
|
}
|
||||||
|
pMesh->mNumFaces = positionBuffer.size() / 3;
|
||||||
|
pMesh->mNumVertices = positionBuffer.size();
|
||||||
|
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
|
||||||
|
memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
|
||||||
|
positionBuffer.clear();
|
||||||
|
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
||||||
|
memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
|
||||||
|
normalBuffer.clear();
|
||||||
|
|
||||||
|
// now copy faces
|
||||||
|
addFacesToMesh(pMesh);
|
||||||
|
}
|
||||||
|
// now add the loaded meshes
|
||||||
|
pScene->mNumMeshes = (unsigned int)meshes.size();
|
||||||
|
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||||
|
for (size_t i = 0; i < meshes.size(); i++)
|
||||||
|
{
|
||||||
|
pScene->mMeshes[i] = meshes[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Read a binary STL file
|
// Read a binary STL file
|
||||||
bool STLImporter::LoadBinaryFile()
|
bool STLImporter::LoadBinaryFile()
|
||||||
{
|
{
|
||||||
|
// allocate one mesh
|
||||||
|
pScene->mNumMeshes = 1;
|
||||||
|
pScene->mMeshes = new aiMesh*[1];
|
||||||
|
aiMesh* pMesh = pScene->mMeshes[0] = new aiMesh();
|
||||||
|
pMesh->mMaterialIndex = 0;
|
||||||
|
|
||||||
// skip the first 80 bytes
|
// skip the first 80 bytes
|
||||||
if (fileSize < 84) {
|
if (fileSize < 84) {
|
||||||
throw DeadlyImportError("STL: file is too small for the header");
|
throw DeadlyImportError("STL: file is too small for the header");
|
||||||
|
@ -382,7 +427,6 @@ bool STLImporter::LoadBinaryFile()
|
||||||
const unsigned char* sz = (const unsigned char*)mBuffer + 80;
|
const unsigned char* sz = (const unsigned char*)mBuffer + 80;
|
||||||
|
|
||||||
// now read the number of facets
|
// now read the number of facets
|
||||||
aiMesh* pMesh = pScene->mMeshes[0];
|
|
||||||
pScene->mRootNode->mName.Set("<STL_BINARY>");
|
pScene->mRootNode->mName.Set("<STL_BINARY>");
|
||||||
|
|
||||||
pMesh->mNumFaces = *((uint32_t*)sz);
|
pMesh->mNumFaces = *((uint32_t*)sz);
|
||||||
|
@ -455,6 +499,10 @@ bool STLImporter::LoadBinaryFile()
|
||||||
*(clr+2) = *clr;
|
*(clr+2) = *clr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now copy faces
|
||||||
|
addFacesToMesh(pMesh);
|
||||||
|
|
||||||
if (bIsMaterialise && !pMesh->mColors[0])
|
if (bIsMaterialise && !pMesh->mColors[0])
|
||||||
{
|
{
|
||||||
// use the color as diffuse material color
|
// use the color as diffuse material color
|
||||||
|
|
|
@ -399,10 +399,14 @@ void CatmullClarkSubdivider::InternSubdivide (
|
||||||
bool haveit = false;
|
bool haveit = false;
|
||||||
for (unsigned int i = 0; i < f.mNumIndices; ++i) {
|
for (unsigned int i = 0; i < f.mNumIndices; ++i) {
|
||||||
if (maptbl[FLATTEN_VERTEX_IDX(n,f.mIndices[i])]==(unsigned int)t) {
|
if (maptbl[FLATTEN_VERTEX_IDX(n,f.mIndices[i])]==(unsigned int)t) {
|
||||||
haveit = true; break;
|
haveit = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ai_assert(haveit);
|
ai_assert(haveit);
|
||||||
|
if (!haveit) {
|
||||||
|
DefaultLogger::get()->debug("Catmull-Clark Subdivider: Index not used");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
class IOStream;
|
class IOStream;
|
||||||
|
|
||||||
|
@ -102,18 +105,14 @@ public:
|
||||||
* @param pFile Path to the file
|
* @param pFile Path to the file
|
||||||
* @return true if there is a file with this path, else false.
|
* @return true if there is a file with this path, else false.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
virtual bool Exists( const char* pFile) const = 0;
|
virtual bool Exists( const char* pFile) const = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** @brief Returns the system specific directory separator
|
/** @brief Returns the system specific directory separator
|
||||||
* @return System specific directory separator
|
* @return System specific directory separator
|
||||||
*/
|
*/
|
||||||
virtual char getOsSeparator() const = 0;
|
virtual char getOsSeparator() const = 0;
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** @brief Open a new file with a given path.
|
/** @brief Open a new file with a given path.
|
||||||
*
|
*
|
||||||
|
@ -139,8 +138,6 @@ public:
|
||||||
inline IOStream* Open(const std::string& pFile,
|
inline IOStream* Open(const std::string& pFile,
|
||||||
const std::string& pMode = std::string("rb"));
|
const std::string& pMode = std::string("rb"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** @brief Closes the given file and releases all resources
|
/** @brief Closes the given file and releases all resources
|
||||||
* associated with it.
|
* associated with it.
|
||||||
|
@ -170,10 +167,41 @@ public:
|
||||||
*/
|
*/
|
||||||
inline bool ComparePaths (const std::string& one,
|
inline bool ComparePaths (const std::string& one,
|
||||||
const std::string& second) const;
|
const std::string& second) const;
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** @brief Pushes a new directory onto the directory stack.
|
||||||
|
* @param path Path to push onto the stack.
|
||||||
|
* @return True, when push was successful, false if path is empty.
|
||||||
|
*/
|
||||||
|
virtual bool PushDirectory( const std::string &path );
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** @brief Returns the top directory from the stack.
|
||||||
|
* @return The directory on the top of the stack.
|
||||||
|
* Returns empty when no directory was pushed to the stack.
|
||||||
|
*/
|
||||||
|
virtual const std::string &CurrentDirectory() const;
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** @brief Returns the number of directories stored on the stack.
|
||||||
|
* @return The number of directories of the stack.
|
||||||
|
*/
|
||||||
|
virtual size_t StackSize() const;
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** @brief Pops the top directory from the stack.
|
||||||
|
* @return True, when a directory was on the stack. False if no
|
||||||
|
* directory was on the stack.
|
||||||
|
*/
|
||||||
|
virtual bool PopDirectory();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> m_pathStack;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
AI_FORCE_INLINE IOSystem::IOSystem()
|
AI_FORCE_INLINE IOSystem::IOSystem() :
|
||||||
|
m_pathStack()
|
||||||
{
|
{
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
@ -220,6 +248,43 @@ inline bool IOSystem::ComparePaths (const std::string& one,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
inline bool IOSystem::PushDirectory( const std::string &path ) {
|
||||||
|
if ( path.empty() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pathStack.push_back( path );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
inline const std::string &IOSystem::CurrentDirectory() const {
|
||||||
|
if ( m_pathStack.empty() ) {
|
||||||
|
static const std::string Dummy("");
|
||||||
|
return Dummy;
|
||||||
|
}
|
||||||
|
return m_pathStack[ m_pathStack.size()-1 ];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
inline size_t IOSystem::StackSize() const {
|
||||||
|
return m_pathStack.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
inline bool IOSystem::PopDirectory() {
|
||||||
|
if ( m_pathStack.empty() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pathStack.pop_back();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
} //!ns Assimp
|
} //!ns Assimp
|
||||||
|
|
||||||
#endif //AI_IOSYSTEM_H_INC
|
#endif //AI_IOSYSTEM_H_INC
|
||||||
|
|
|
@ -276,4 +276,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
# define AI_BUILD_BIG_ENDIAN
|
# define AI_BUILD_BIG_ENDIAN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* To avoid running out of memory
|
||||||
|
* This can be adjusted for specific use cases
|
||||||
|
* It's NOT a total limit, just a limit for individual allocations
|
||||||
|
*/
|
||||||
|
#define AI_MAX_ALLOC(type) ((256U * 1024 * 1024) / sizeof(type))
|
||||||
|
|
||||||
|
|
||||||
#endif // !! INCLUDED_AI_DEFINES_H
|
#endif // !! INCLUDED_AI_DEFINES_H
|
||||||
|
|
|
@ -42,7 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
/** @file Android extension of DefaultIOSystem using the standard C file functions */
|
/** @file Android extension of DefaultIOSystem using the standard C file functions */
|
||||||
|
|
||||||
|
|
||||||
#include <code/AssimpPCH.h>
|
#include <assimp/config.h>
|
||||||
|
#include <android/api-level.h>
|
||||||
#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
|
#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -50,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <android/asset_manager.h>
|
#include <android/asset_manager.h>
|
||||||
#include <android/asset_manager_jni.h>
|
#include <android/asset_manager_jni.h>
|
||||||
#include <android/native_activity.h>
|
#include <android/native_activity.h>
|
||||||
|
#include <assimp/ai_assert.h>
|
||||||
#include <assimp/port/AndroidJNI/AndroidJNIIOSystem.h>
|
#include <assimp/port/AndroidJNI/AndroidJNIIOSystem.h>
|
||||||
#include <code/DefaultIOStream.h>
|
#include <code/DefaultIOStream.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
@ -114,7 +116,7 @@ bool AndroidJNIIOSystem::AndroidExtractAsset(std::string name)
|
||||||
// Open file
|
// Open file
|
||||||
AAsset* asset = AAssetManager_open(mApkAssetManager, name.c_str(),
|
AAsset* asset = AAssetManager_open(mApkAssetManager, name.c_str(),
|
||||||
AASSET_MODE_UNKNOWN);
|
AASSET_MODE_UNKNOWN);
|
||||||
std::string assetContent;
|
std::vector<char> assetContent;
|
||||||
|
|
||||||
if (asset != NULL) {
|
if (asset != NULL) {
|
||||||
// Find size
|
// Find size
|
||||||
|
@ -138,7 +140,7 @@ bool AndroidJNIIOSystem::AndroidExtractAsset(std::string name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write output buffer into a file
|
// Write output buffer into a file
|
||||||
assetExtracted.write(assetContent.c_str(), strlen(assetContent.c_str()));
|
assetExtracted.write(&assetContent[0], assetContent.size());
|
||||||
assetExtracted.close();
|
assetExtracted.close();
|
||||||
|
|
||||||
__android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset extracted");
|
__android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset extracted");
|
||||||
|
|
|
@ -20,6 +20,7 @@ additional_dirs, ext_whitelist = [],[]
|
||||||
# populate search directories and lists of allowed file extensions
|
# populate search directories and lists of allowed file extensions
|
||||||
# depending on the platform we're running on.
|
# depending on the platform we're running on.
|
||||||
if os.name=='posix':
|
if os.name=='posix':
|
||||||
|
additional_dirs.append('./')
|
||||||
additional_dirs.append('/usr/lib/')
|
additional_dirs.append('/usr/lib/')
|
||||||
additional_dirs.append('/usr/local/lib/')
|
additional_dirs.append('/usr/local/lib/')
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ class PyAssimp3DViewer:
|
||||||
pygame.init()
|
pygame.init()
|
||||||
pygame.display.set_caption(self.base_name)
|
pygame.display.set_caption(self.base_name)
|
||||||
pygame.display.set_mode((w,h), pygame.OPENGL | pygame.DOUBLEBUF)
|
pygame.display.set_mode((w,h), pygame.OPENGL | pygame.DOUBLEBUF)
|
||||||
|
glutInit()
|
||||||
self.prepare_shaders()
|
self.prepare_shaders()
|
||||||
|
|
||||||
self.cameras = [DefaultCamera(w,h,fov)]
|
self.cameras = [DefaultCamera(w,h,fov)]
|
||||||
|
|
|
@ -24,6 +24,7 @@ SET( TEST_SRCS
|
||||||
unit/utGenNormals.cpp
|
unit/utGenNormals.cpp
|
||||||
unit/utImporter.cpp
|
unit/utImporter.cpp
|
||||||
unit/utImproveCacheLocality.cpp
|
unit/utImproveCacheLocality.cpp
|
||||||
|
unit/utIOSystem.cpp
|
||||||
unit/utJoinVertices.cpp
|
unit/utJoinVertices.cpp
|
||||||
unit/utLimitBoneWeights.cpp
|
unit/utLimitBoneWeights.cpp
|
||||||
unit/utMaterialSystem.cpp
|
unit/utMaterialSystem.cpp
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2014, assimp 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 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.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#include "UnitTestPCH.h"
|
||||||
|
|
||||||
|
#include <assimp/IOSystem.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Assimp;
|
||||||
|
|
||||||
|
static const string Sep = "/";
|
||||||
|
class TestIOSystem : public IOSystem {
|
||||||
|
public:
|
||||||
|
TestIOSystem() : IOSystem() {}
|
||||||
|
virtual ~TestIOSystem() {}
|
||||||
|
virtual bool Exists( const char* ) const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual char getOsSeparator() const {
|
||||||
|
return Sep[ 0 ];
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual IOStream* Open(const char* pFile, const char* pMode = "rb") {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Close( IOStream* pFile) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class IOSystemTest : public ::testing::Test {
|
||||||
|
public:
|
||||||
|
virtual void SetUp() { pImp = new TestIOSystem(); }
|
||||||
|
virtual void TearDown() { delete pImp; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TestIOSystem* pImp;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
virtual bool PushDirectory( const std::string &path );
|
||||||
|
virtual const std::string &CurrentDirectory() const;
|
||||||
|
virtual bool PopDirectory();
|
||||||
|
*/
|
||||||
|
|
||||||
|
TEST_F( IOSystemTest, accessDirectoryStackTest ) {
|
||||||
|
EXPECT_FALSE( pImp->PopDirectory() );
|
||||||
|
EXPECT_EQ( 0, pImp->StackSize() );
|
||||||
|
EXPECT_FALSE( pImp->PushDirectory( "" ) );
|
||||||
|
std::string path = "test/";
|
||||||
|
EXPECT_TRUE( pImp->PushDirectory( path ) );
|
||||||
|
EXPECT_EQ( 1, pImp->StackSize() );
|
||||||
|
EXPECT_EQ( path, pImp->CurrentDirectory() );
|
||||||
|
EXPECT_TRUE( pImp->PopDirectory() );
|
||||||
|
EXPECT_EQ( 0, pImp->StackSize() );
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:Assimp.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "0700"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7F79227F1AB43AC3005A8E5D"
|
||||||
|
BuildableName = "libassimp.a"
|
||||||
|
BlueprintName = "assimp"
|
||||||
|
ReferencedContainer = "container:workspaces/xcode6/Assimp.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7F79227F1AB43AC3005A8E5D"
|
||||||
|
BuildableName = "libassimp.a"
|
||||||
|
BlueprintName = "assimp"
|
||||||
|
ReferencedContainer = "container:workspaces/xcode6/Assimp.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7F79227F1AB43AC3005A8E5D"
|
||||||
|
BuildableName = "libassimp.a"
|
||||||
|
BlueprintName = "assimp"
|
||||||
|
ReferencedContainer = "container:workspaces/xcode6/Assimp.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
Loading…
Reference in New Issue