Merge branch 'master' into master
This commit is contained in:
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -43,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** @file Implementation of the 3ds importer class */
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
|
||||
|
||||
// internal headers
|
||||
|
||||
+45
-23
@@ -322,7 +322,7 @@ struct Face : public FaceWithSmoothingGroup {
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
# pragma warning(disable : 4315)
|
||||
#pragma warning(disable : 4315)
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -441,30 +441,52 @@ struct Material {
|
||||
// empty
|
||||
}
|
||||
|
||||
Material(const Material &other) = default;
|
||||
Material &operator=(const Material &other) = default;
|
||||
Material(const Material &other) :
|
||||
mName(other.mName),
|
||||
mDiffuse(other.mDiffuse),
|
||||
mSpecularExponent(other.mSpecularExponent),
|
||||
mShininessStrength(other.mShininessStrength),
|
||||
mSpecular(other.mSpecular),
|
||||
mAmbient(other.mAmbient),
|
||||
mShading(other.mShading),
|
||||
mTransparency(other.mTransparency),
|
||||
sTexDiffuse(other.sTexDiffuse),
|
||||
sTexOpacity(other.sTexOpacity),
|
||||
sTexSpecular(other.sTexSpecular),
|
||||
sTexReflective(other.sTexReflective),
|
||||
sTexBump(other.sTexBump),
|
||||
sTexEmissive(other.sTexEmissive),
|
||||
sTexShininess(other.sTexShininess),
|
||||
mBumpHeight(other.mBumpHeight),
|
||||
mEmissive(other.mEmissive),
|
||||
sTexAmbient(other.sTexAmbient),
|
||||
mTwoSided(other.mTwoSided) {
|
||||
// empty
|
||||
|
||||
}
|
||||
|
||||
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
|
||||
Material(Material &&other) AI_NO_EXCEPT
|
||||
: mName(std::move(other.mName)),
|
||||
mDiffuse(std::move(other.mDiffuse)),
|
||||
mSpecularExponent(std::move(other.mSpecularExponent)),
|
||||
mShininessStrength(std::move(other.mShininessStrength)),
|
||||
mSpecular(std::move(other.mSpecular)),
|
||||
mAmbient(std::move(other.mAmbient)),
|
||||
mShading(std::move(other.mShading)),
|
||||
mTransparency(std::move(other.mTransparency)),
|
||||
sTexDiffuse(std::move(other.sTexDiffuse)),
|
||||
sTexOpacity(std::move(other.sTexOpacity)),
|
||||
sTexSpecular(std::move(other.sTexSpecular)),
|
||||
sTexReflective(std::move(other.sTexReflective)),
|
||||
sTexBump(std::move(other.sTexBump)),
|
||||
sTexEmissive(std::move(other.sTexEmissive)),
|
||||
sTexShininess(std::move(other.sTexShininess)),
|
||||
mBumpHeight(std::move(other.mBumpHeight)),
|
||||
mEmissive(std::move(other.mEmissive)),
|
||||
sTexAmbient(std::move(other.sTexAmbient)),
|
||||
mTwoSided(std::move(other.mTwoSided)) {
|
||||
Material(Material &&other) AI_NO_EXCEPT :
|
||||
mName(std::move(other.mName)),
|
||||
mDiffuse(std::move(other.mDiffuse)),
|
||||
mSpecularExponent(std::move(other.mSpecularExponent)),
|
||||
mShininessStrength(std::move(other.mShininessStrength)),
|
||||
mSpecular(std::move(other.mSpecular)),
|
||||
mAmbient(std::move(other.mAmbient)),
|
||||
mShading(std::move(other.mShading)),
|
||||
mTransparency(std::move(other.mTransparency)),
|
||||
sTexDiffuse(std::move(other.sTexDiffuse)),
|
||||
sTexOpacity(std::move(other.sTexOpacity)),
|
||||
sTexSpecular(std::move(other.sTexSpecular)),
|
||||
sTexReflective(std::move(other.sTexReflective)),
|
||||
sTexBump(std::move(other.sTexBump)),
|
||||
sTexEmissive(std::move(other.sTexEmissive)),
|
||||
sTexShininess(std::move(other.sTexShininess)),
|
||||
mBumpHeight(std::move(other.mBumpHeight)),
|
||||
mEmissive(std::move(other.mEmissive)),
|
||||
sTexAmbient(std::move(other.sTexAmbient)),
|
||||
mTwoSided(std::move(other.mTwoSided)) {
|
||||
// empty
|
||||
}
|
||||
|
||||
Material &operator=(Material &&other) AI_NO_EXCEPT {
|
||||
|
||||
+5
-11
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -72,7 +70,6 @@ static const aiImporterDesc desc = {
|
||||
"3ds prj"
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Begins a new parsing block
|
||||
// - Reads the current chunk and validates it
|
||||
@@ -141,15 +138,13 @@ bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandle
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Loader registry entry
|
||||
const aiImporterDesc* Discreet3DSImporter::GetInfo () const
|
||||
{
|
||||
const aiImporterDesc* Discreet3DSImporter::GetInfo () const {
|
||||
return &desc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties
|
||||
void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/)
|
||||
{
|
||||
void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/) {
|
||||
// nothing to be done for the moment
|
||||
}
|
||||
|
||||
@@ -200,7 +195,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
|
||||
ComputeNormalsWithSmoothingsGroups<D3DS::Face>(mesh);
|
||||
}
|
||||
|
||||
// Replace all occurences of the default material with a
|
||||
// Replace all occurrences of the default material with a
|
||||
// valid material. Generate it if no material containing
|
||||
// DEFAULT in its name has been found in the file
|
||||
ReplaceDefaultMaterial();
|
||||
@@ -227,8 +222,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Applies a master-scaling factor to the imported scene
|
||||
void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene)
|
||||
{
|
||||
void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene) {
|
||||
// There are some 3DS files with a zero scaling factor
|
||||
if (!mMasterScale)mMasterScale = 1.0f;
|
||||
else mMasterScale = 1.0f / mMasterScale;
|
||||
@@ -1084,7 +1078,7 @@ void Discreet3DSImporter::ParseMeshChunk()
|
||||
mMesh.mFaceMaterials.resize(mMesh.mFaces.size(),0xcdcdcdcd);
|
||||
|
||||
// Larger 3DS files could have multiple FACE chunks here
|
||||
chunkSize = stream->GetRemainingSizeToLimit();
|
||||
chunkSize = (int)stream->GetRemainingSizeToLimit();
|
||||
if ( chunkSize > (int) sizeof(Discreet3DS::Chunk ) )
|
||||
ParseFaceChunk();
|
||||
}
|
||||
|
||||
@@ -65,15 +65,11 @@ using namespace D3DS;
|
||||
// ---------------------------------------------------------------------------------
|
||||
/** Importer class for 3D Studio r3 and r4 3DS files
|
||||
*/
|
||||
class Discreet3DSImporter : public BaseImporter
|
||||
{
|
||||
class Discreet3DSImporter : public BaseImporter {
|
||||
public:
|
||||
|
||||
Discreet3DSImporter();
|
||||
~Discreet3DSImporter();
|
||||
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the class can handle the format of the given file.
|
||||
* See BaseImporter::CanRead() for details.
|
||||
|
||||
+26
-14
@@ -181,7 +181,7 @@ bool D3MFExporter::export3DModel() {
|
||||
|
||||
writeHeader();
|
||||
mModelOutput << "<" << XmlTag::model << " " << XmlTag::model_unit << "=\"millimeter\""
|
||||
<< "xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\">"
|
||||
<< " xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\">"
|
||||
<< std::endl;
|
||||
mModelOutput << "<" << XmlTag::resources << ">";
|
||||
mModelOutput << std::endl;
|
||||
@@ -212,7 +212,7 @@ bool D3MFExporter::export3DModel() {
|
||||
}
|
||||
|
||||
void D3MFExporter::writeHeader() {
|
||||
mModelOutput << "<?xml version=\"1.0\" encoding=\"UTF - 8\"?>";
|
||||
mModelOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
||||
mModelOutput << std::endl;
|
||||
}
|
||||
|
||||
@@ -254,16 +254,28 @@ void D3MFExporter::writeBaseMaterials() {
|
||||
if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) {
|
||||
hexDiffuseColor.clear();
|
||||
tmp.clear();
|
||||
hexDiffuseColor = "#";
|
||||
|
||||
tmp = DecimalToHexa( (ai_real) color.r );
|
||||
hexDiffuseColor += tmp;
|
||||
tmp = DecimalToHexa((ai_real)color.g);
|
||||
hexDiffuseColor += tmp;
|
||||
tmp = DecimalToHexa((ai_real)color.b);
|
||||
hexDiffuseColor += tmp;
|
||||
tmp = DecimalToHexa((ai_real)color.a);
|
||||
hexDiffuseColor += tmp;
|
||||
// rgbs %
|
||||
if(color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1){
|
||||
|
||||
hexDiffuseColor = Rgba2Hex(
|
||||
(int)((ai_real)color.r)*255,
|
||||
(int)((ai_real)color.g)*255,
|
||||
(int)((ai_real)color.b)*255,
|
||||
(int)((ai_real)color.a)*255,
|
||||
true
|
||||
);
|
||||
|
||||
}else{
|
||||
hexDiffuseColor = "#";
|
||||
tmp = DecimalToHexa( (ai_real) color.r );
|
||||
hexDiffuseColor += tmp;
|
||||
tmp = DecimalToHexa((ai_real)color.g);
|
||||
hexDiffuseColor += tmp;
|
||||
tmp = DecimalToHexa((ai_real)color.b);
|
||||
hexDiffuseColor += tmp;
|
||||
tmp = DecimalToHexa((ai_real)color.a);
|
||||
hexDiffuseColor += tmp;
|
||||
}
|
||||
} else {
|
||||
hexDiffuseColor = "#FFFFFFFF";
|
||||
}
|
||||
@@ -284,7 +296,7 @@ void D3MFExporter::writeObjects() {
|
||||
if ( nullptr == currentNode ) {
|
||||
continue;
|
||||
}
|
||||
mModelOutput << "<" << XmlTag::object << " id=\"" << currentNode->mName.C_Str() << "\" type=\"model\">";
|
||||
mModelOutput << "<" << XmlTag::object << " id=\"" << i + 2 << "\" type=\"model\">";
|
||||
mModelOutput << std::endl;
|
||||
for ( unsigned int j = 0; j < currentNode->mNumMeshes; ++j ) {
|
||||
aiMesh *currentMesh = mScene->mMeshes[ currentNode->mMeshes[ j ] ];
|
||||
@@ -348,7 +360,7 @@ void D3MFExporter::writeBuild() {
|
||||
mModelOutput << "<" << XmlTag::build << ">" << std::endl;
|
||||
|
||||
for ( size_t i = 0; i < mBuildItems.size(); ++i ) {
|
||||
mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 1 << "\"/>";
|
||||
mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 2 << "\"/>";
|
||||
mModelOutput << std::endl;
|
||||
}
|
||||
mModelOutput << "</" << XmlTag::build << ">";
|
||||
|
||||
@@ -9,6 +9,9 @@ For details, see http://sourceforge.net/projects/libb64
|
||||
|
||||
const int CHARS_PER_LINE = 72;
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4244)
|
||||
|
||||
void base64_init_encodestate(base64_encodestate* state_in)
|
||||
{
|
||||
state_in->step = step_A;
|
||||
@@ -107,3 +110,4 @@ int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
|
||||
return (int)(codechar - code_out);
|
||||
}
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
@@ -50,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <assimp/IOSystem.hpp>
|
||||
#include <assimp/Exporter.hpp>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Assimp {
|
||||
|
||||
void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
|
||||
{
|
||||
|
||||
@@ -206,7 +206,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
|
||||
inflateInit2(&zstream, 16+MAX_WBITS);
|
||||
|
||||
zstream.next_in = reinterpret_cast<Bytef*>( reader->GetPtr() );
|
||||
zstream.avail_in = reader->GetRemainingSize();
|
||||
zstream.avail_in = (uInt) reader->GetRemainingSize();
|
||||
|
||||
size_t total = 0l;
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ SET( PUBLIC_HEADERS
|
||||
${HEADER_PATH}/GenericProperty.h
|
||||
${HEADER_PATH}/SpatialSort.h
|
||||
${HEADER_PATH}/SkeletonMeshBuilder.h
|
||||
${HEADER_PATH}/SmallVector.h
|
||||
${HEADER_PATH}/SmoothingGroups.h
|
||||
${HEADER_PATH}/SmoothingGroups.inl
|
||||
${HEADER_PATH}/StandardShapes.h
|
||||
|
||||
@@ -178,7 +178,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
|
||||
*ot++ = *buffer++;
|
||||
|
||||
*ot = '\0';
|
||||
nda->mNodeName.length = (ai_uint32)(ot-nda->mNodeName.data);
|
||||
nda->mNodeName.length = static_cast<ai_uint32>(ot-nda->mNodeName.data);
|
||||
}
|
||||
|
||||
anim->mNumChannels = static_cast<unsigned int>(anims_temp.size());
|
||||
|
||||
+328
-365
File diff suppressed because it is too large
Load Diff
@@ -83,32 +83,61 @@ namespace Assimp {
|
||||
void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
|
||||
// do not use const, because some exporter need to convert the scene temporary
|
||||
// Exporter worker function prototypes. Do not use const, because some exporter need to convert
|
||||
// the scene temporary
|
||||
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
|
||||
void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_X_EXPORTER
|
||||
void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
|
||||
void ExportSceneStep(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
|
||||
void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneObjNoMtl(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_STL_EXPORTER
|
||||
void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_PLY_EXPORTER
|
||||
void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
|
||||
void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
|
||||
void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneGLB2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
|
||||
void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
|
||||
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_EXPORTER
|
||||
void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
|
||||
void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_M3D_EXPORTER
|
||||
void ExportSceneM3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneM3DA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
|
||||
void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*);
|
||||
|
||||
#endif
|
||||
|
||||
static void setupExporterArray(std::vector<Exporter::ExportFormatEntry> &exporters) {
|
||||
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
|
||||
|
||||
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -50,27 +49,25 @@ namespace Assimp {
|
||||
namespace FBX {
|
||||
|
||||
/** FBX import settings, parts of which are publicly accessible via their corresponding AI_CONFIG constants */
|
||||
struct ImportSettings
|
||||
{
|
||||
ImportSettings()
|
||||
: strictMode(true)
|
||||
, readAllLayers(true)
|
||||
, readAllMaterials(false)
|
||||
, readMaterials(true)
|
||||
, readTextures(true)
|
||||
, readCameras(true)
|
||||
, readLights(true)
|
||||
, readAnimations(true)
|
||||
, readWeights(true)
|
||||
, preservePivots(true)
|
||||
, optimizeEmptyAnimationCurves(true)
|
||||
, useLegacyEmbeddedTextureNaming(false)
|
||||
, removeEmptyBones( true )
|
||||
, convertToMeters( false ) {
|
||||
struct ImportSettings {
|
||||
ImportSettings() :
|
||||
strictMode(true),
|
||||
readAllLayers(true),
|
||||
readAllMaterials(false),
|
||||
readMaterials(true),
|
||||
readTextures(true),
|
||||
readCameras(true),
|
||||
readLights(true),
|
||||
readAnimations(true),
|
||||
readWeights(true),
|
||||
preservePivots(true),
|
||||
optimizeEmptyAnimationCurves(true),
|
||||
useLegacyEmbeddedTextureNaming(false),
|
||||
removeEmptyBones(true),
|
||||
convertToMeters(false) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
/** enable strict mode:
|
||||
* - only accept fbx 2012, 2013 files
|
||||
* - on the slightest error, give up.
|
||||
@@ -94,7 +91,6 @@ struct ImportSettings
|
||||
* This bit is ignored unless readMaterials=true*/
|
||||
bool readAllMaterials;
|
||||
|
||||
|
||||
/** import materials (true) or skip them and assign a default
|
||||
* material. The default value is true.*/
|
||||
bool readMaterials;
|
||||
@@ -156,9 +152,7 @@ struct ImportSettings
|
||||
bool convertToMeters;
|
||||
};
|
||||
|
||||
|
||||
} // !FBX
|
||||
} // !Assimp
|
||||
} // namespace FBX
|
||||
} // namespace Assimp
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
||||
+21
-24
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -51,45 +50,44 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "FBXImportSettings.h"
|
||||
|
||||
namespace Assimp {
|
||||
namespace Assimp {
|
||||
|
||||
// TinyFormatter.h
|
||||
namespace Formatter {
|
||||
template <typename T,typename TR, typename A> class basic_formatter;
|
||||
typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
|
||||
}
|
||||
|
||||
template <typename T, typename TR, typename A>
|
||||
class basic_formatter;
|
||||
|
||||
typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>> format;
|
||||
|
||||
} // namespace Formatter
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
/** Load the Autodesk FBX file format.
|
||||
|
||||
See http://en.wikipedia.org/wiki/FBX
|
||||
*/
|
||||
/// Loads the Autodesk FBX file format.
|
||||
///
|
||||
/// See http://en.wikipedia.org/wiki/FBX
|
||||
// -------------------------------------------------------------------------------------------
|
||||
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter>
|
||||
{
|
||||
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
|
||||
public:
|
||||
FBXImporter();
|
||||
virtual ~FBXImporter();
|
||||
|
||||
// --------------------
|
||||
bool CanRead( const std::string& pFile,
|
||||
IOSystem* pIOHandler,
|
||||
bool checkSig
|
||||
) const;
|
||||
bool CanRead(const std::string &pFile,
|
||||
IOSystem *pIOHandler,
|
||||
bool checkSig) const;
|
||||
|
||||
protected:
|
||||
// --------------------
|
||||
const aiImporterDesc *GetInfo() const;
|
||||
|
||||
// --------------------
|
||||
const aiImporterDesc* GetInfo () const;
|
||||
void SetupProperties(const Importer *pImp);
|
||||
|
||||
// --------------------
|
||||
void SetupProperties(const Importer* pImp);
|
||||
|
||||
// --------------------
|
||||
void InternReadFile( const std::string& pFile,
|
||||
aiScene* pScene,
|
||||
IOSystem* pIOHandler
|
||||
);
|
||||
void InternReadFile(const std::string &pFile,
|
||||
aiScene *pScene,
|
||||
IOSystem *pIOHandler);
|
||||
|
||||
private:
|
||||
FBX::ImportSettings settings;
|
||||
@@ -97,4 +95,3 @@ private:
|
||||
|
||||
} // end of namespace Assimp
|
||||
#endif // !INCLUDED_AI_FBX_IMPORTER_H
|
||||
|
||||
|
||||
@@ -1483,6 +1483,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
||||
*/
|
||||
|
||||
delete root;
|
||||
delete reader;
|
||||
}
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER
|
||||
|
||||
+41
-36
@@ -189,42 +189,42 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
|
||||
continue;
|
||||
if (aiProps[k].pKey) {
|
||||
switch (m3d_propertytypes[k].format) {
|
||||
case m3dpf_color:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, c) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, mkColor(&c));
|
||||
break;
|
||||
case m3dpf_float:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, f) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id,
|
||||
/* not (uint32_t)f, because we don't want to convert
|
||||
case m3dpf_color:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, c) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, mkColor(&c));
|
||||
break;
|
||||
case m3dpf_float:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, f) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id,
|
||||
/* not (uint32_t)f, because we don't want to convert
|
||||
* it, we want to see it as 32 bits of memory */
|
||||
*((uint32_t *)&f));
|
||||
break;
|
||||
case m3dpf_uint8:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, j) == AI_SUCCESS) {
|
||||
// special conversion for illumination model property
|
||||
if (m3d_propertytypes[k].id == m3dp_il) {
|
||||
switch (j) {
|
||||
case aiShadingMode_NoShading: j = 0; break;
|
||||
case aiShadingMode_Phong: j = 2; break;
|
||||
default: j = 1; break;
|
||||
}
|
||||
*((uint32_t *)&f));
|
||||
break;
|
||||
case m3dpf_uint8:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, j) == AI_SUCCESS) {
|
||||
// special conversion for illumination model property
|
||||
if (m3d_propertytypes[k].id == m3dp_il) {
|
||||
switch (j) {
|
||||
case aiShadingMode_NoShading: j = 0; break;
|
||||
case aiShadingMode_Phong: j = 2; break;
|
||||
default: j = 1; break;
|
||||
}
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, j);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, j) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, j);
|
||||
break;
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, j);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, j) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aiTxProps[k].pKey &&
|
||||
@@ -292,8 +292,8 @@ void ExportSceneM3D(
|
||||
// Prototyped and registered in Exporter.cpp
|
||||
void ExportSceneM3DA(
|
||||
const char *,
|
||||
IOSystem*,
|
||||
const aiScene*,
|
||||
IOSystem *,
|
||||
const aiScene *,
|
||||
const ExportProperties *
|
||||
|
||||
) {
|
||||
@@ -312,7 +312,9 @@ void ExportSceneM3DA(
|
||||
M3DExporter::M3DExporter(const aiScene *pScene, const ExportProperties *pProperties) :
|
||||
mScene(pScene),
|
||||
mProperties(pProperties),
|
||||
outfile() {}
|
||||
outfile() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void M3DExporter::doExport(
|
||||
@@ -352,6 +354,9 @@ void M3DExporter::doExport(
|
||||
// explicitly release file pointer,
|
||||
// so we don't have to rely on class destruction.
|
||||
outfile.reset();
|
||||
|
||||
M3D_FREE(m3d->name);
|
||||
m3d->name = nullptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
+53
-52
@@ -50,15 +50,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifdef ASSIMP_USE_M3D_READFILECB
|
||||
|
||||
# if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards
|
||||
# define threadlocal thread_local
|
||||
# else
|
||||
# if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013
|
||||
# define threadlocal __declspec(thread)
|
||||
# else
|
||||
# define threadlocal
|
||||
# endif
|
||||
# endif
|
||||
#if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards
|
||||
#define threadlocal thread_local
|
||||
#else
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013
|
||||
#define threadlocal __declspec(thread)
|
||||
#else
|
||||
#define threadlocal
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -66,37 +66,37 @@ extern "C" {
|
||||
threadlocal void *m3dimporter_pIOHandler;
|
||||
|
||||
unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) {
|
||||
ai_assert(nullptr != fn);
|
||||
ai_assert(nullptr != size);
|
||||
std::string file(fn);
|
||||
std::unique_ptr<Assimp::IOStream> pStream(
|
||||
(reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
|
||||
size_t fileSize = 0;
|
||||
unsigned char *data = NULL;
|
||||
// sometimes pStream is nullptr in a single-threaded scenario too for some reason
|
||||
// (should be an empty object returning nothing I guess)
|
||||
if (pStream) {
|
||||
fileSize = pStream->FileSize();
|
||||
// should be allocated with malloc(), because the library will call free() to deallocate
|
||||
data = (unsigned char *)malloc(fileSize);
|
||||
if (!data || !pStream.get() || !fileSize || fileSize != pStream->Read(data, 1, fileSize)) {
|
||||
pStream.reset();
|
||||
*size = 0;
|
||||
// don't throw a deadly exception, it's not fatal if we can't read an external asset
|
||||
return nullptr;
|
||||
}
|
||||
pStream.reset();
|
||||
}
|
||||
*size = (int)fileSize;
|
||||
return data;
|
||||
ai_assert(nullptr != fn);
|
||||
ai_assert(nullptr != size);
|
||||
std::string file(fn);
|
||||
std::unique_ptr<Assimp::IOStream> pStream(
|
||||
(reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
|
||||
size_t fileSize = 0;
|
||||
unsigned char *data = NULL;
|
||||
// sometimes pStream is nullptr in a single-threaded scenario too for some reason
|
||||
// (should be an empty object returning nothing I guess)
|
||||
if (pStream) {
|
||||
fileSize = pStream->FileSize();
|
||||
// should be allocated with malloc(), because the library will call free() to deallocate
|
||||
data = (unsigned char *)malloc(fileSize);
|
||||
if (!data || !pStream.get() || !fileSize || fileSize != pStream->Read(data, 1, fileSize)) {
|
||||
pStream.reset();
|
||||
*size = 0;
|
||||
// don't throw a deadly exception, it's not fatal if we can't read an external asset
|
||||
return nullptr;
|
||||
}
|
||||
pStream.reset();
|
||||
}
|
||||
*size = (int)fileSize;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace Assimp {
|
||||
M3DWrapper::M3DWrapper() {
|
||||
// use malloc() here because m3d_free() will call free()
|
||||
m3d_ = (m3d_t *)calloc(1, sizeof(m3d_t));
|
||||
// use malloc() here because m3d_free() will call free()
|
||||
m3d_ = (m3d_t *)calloc(1, sizeof(m3d_t));
|
||||
}
|
||||
|
||||
M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer) {
|
||||
@@ -105,41 +105,42 @@ M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &b
|
||||
}
|
||||
|
||||
#ifdef ASSIMP_USE_M3D_READFILECB
|
||||
// pass this IOHandler to the C callback in a thread-local pointer
|
||||
m3dimporter_pIOHandler = pIOHandler;
|
||||
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
|
||||
// Clear the C callback
|
||||
m3dimporter_pIOHandler = nullptr;
|
||||
// pass this IOHandler to the C callback in a thread-local pointer
|
||||
m3dimporter_pIOHandler = pIOHandler;
|
||||
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
|
||||
// Clear the C callback
|
||||
m3dimporter_pIOHandler = nullptr;
|
||||
#else
|
||||
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), nullptr, nullptr, nullptr);
|
||||
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), nullptr, nullptr, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
M3DWrapper::~M3DWrapper() {
|
||||
reset();
|
||||
reset();
|
||||
}
|
||||
|
||||
void M3DWrapper::reset() {
|
||||
ClearSave();
|
||||
if (m3d_)
|
||||
m3d_free(m3d_);
|
||||
m3d_ = nullptr;
|
||||
ClearSave();
|
||||
if (m3d_) {
|
||||
m3d_free(m3d_);
|
||||
}
|
||||
m3d_ = nullptr;
|
||||
}
|
||||
|
||||
unsigned char *M3DWrapper::Save(int quality, int flags, unsigned int &size) {
|
||||
#if (!(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER))
|
||||
ClearSave();
|
||||
saved_output_ = m3d_save(m3d_, quality, flags, &size);
|
||||
return saved_output_;
|
||||
ClearSave();
|
||||
saved_output_ = m3d_save(m3d_, quality, flags, &size);
|
||||
return saved_output_;
|
||||
#else
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void M3DWrapper::ClearSave() {
|
||||
if (saved_output_)
|
||||
M3D_FREE(saved_output_);
|
||||
saved_output_ = nullptr;
|
||||
if (saved_output_)
|
||||
M3D_FREE(saved_output_);
|
||||
saved_output_ = nullptr;
|
||||
}
|
||||
} // namespace Assimp
|
||||
|
||||
|
||||
+20
-14
@@ -5440,13 +5440,13 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
|
||||
out += 2;
|
||||
break;
|
||||
case 4:
|
||||
*((float *)out) = vrtx[i].data.x;
|
||||
memcpy(out, &vrtx[i].data.x, sizeof(float));
|
||||
out += 4;
|
||||
*((float *)out) = vrtx[i].data.y;
|
||||
memcpy(out, &vrtx[i].data.y, sizeof(float));
|
||||
out += 4;
|
||||
*((float *)out) = vrtx[i].data.z;
|
||||
memcpy(out, &vrtx[i].data.z, sizeof(float));
|
||||
out += 4;
|
||||
*((float *)out) = vrtx[i].data.w;
|
||||
memcpy(out, &vrtx[i].data.w, sizeof(float));
|
||||
out += 4;
|
||||
break;
|
||||
case 8:
|
||||
@@ -5474,9 +5474,11 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
|
||||
}
|
||||
out = _m3d_addidx(out, sk_s, vrtx[i].data.skinid);
|
||||
}
|
||||
*length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
|
||||
uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
|
||||
memcpy(length, &v, sizeof(uint32_t));
|
||||
//*length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
|
||||
out = NULL;
|
||||
len += *length;
|
||||
len += v;
|
||||
}
|
||||
/* bones chunk */
|
||||
if (model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) {
|
||||
@@ -5660,8 +5662,9 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
|
||||
out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.normal[j]]);
|
||||
}
|
||||
}
|
||||
*length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
|
||||
len += *length;
|
||||
uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
|
||||
memcpy(length, &v, sizeof(uint32_t));
|
||||
len += v;
|
||||
out = NULL;
|
||||
}
|
||||
/* mathematical shapes face */
|
||||
@@ -5721,8 +5724,9 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
|
||||
}
|
||||
}
|
||||
}
|
||||
*length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
|
||||
len += *length;
|
||||
uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
|
||||
memcpy( length, &v, sizeof(uint32_t));
|
||||
len += v;
|
||||
out = NULL;
|
||||
}
|
||||
}
|
||||
@@ -5765,8 +5769,9 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
|
||||
out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].text));
|
||||
}
|
||||
if (length) {
|
||||
*length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
|
||||
len += *length;
|
||||
uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
|
||||
memcpy( length, &v, sizeof(uint32_t));
|
||||
len += v;
|
||||
}
|
||||
out = NULL;
|
||||
sn = sl = NULL;
|
||||
@@ -5796,8 +5801,9 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
|
||||
out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].ori]);
|
||||
}
|
||||
}
|
||||
*length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
|
||||
len += *length;
|
||||
uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
|
||||
memcpy( length, &v, sizeof(uint32_t));
|
||||
len += v;
|
||||
out = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,7 +503,7 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
|
||||
pcNew->mData = new char[pSizeInBytes];
|
||||
memcpy (pcNew->mData,pInput,pSizeInBytes);
|
||||
|
||||
pcNew->mKey.length = (ai_uint32)::strlen(pKey);
|
||||
pcNew->mKey.length = static_cast<ai_uint32>( ::strlen(pKey) );
|
||||
ai_assert ( MAXLEN > pcNew->mKey.length);
|
||||
strcpy( pcNew->mKey.data, pKey );
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include "LimitBoneWeightsProcess.h"
|
||||
#include <assimp/SmallVector.h>
|
||||
#include <assimp/StringUtils.h>
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
@@ -52,7 +53,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
LimitBoneWeightsProcess::LimitBoneWeightsProcess()
|
||||
@@ -76,10 +76,12 @@ bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void LimitBoneWeightsProcess::Execute( aiScene* pScene) {
|
||||
void LimitBoneWeightsProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin");
|
||||
for (unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
|
||||
ProcessMesh(pScene->mMeshes[a]);
|
||||
|
||||
for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) {
|
||||
ProcessMesh(pScene->mMeshes[m]);
|
||||
}
|
||||
|
||||
ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess end");
|
||||
@@ -95,107 +97,96 @@ void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Unites identical vertices in the given mesh
|
||||
void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
|
||||
void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh)
|
||||
{
|
||||
if( !pMesh->HasBones())
|
||||
if (!pMesh->HasBones())
|
||||
return;
|
||||
|
||||
// collect all bone weights per vertex
|
||||
typedef std::vector< std::vector< Weight > > WeightsPerVertex;
|
||||
WeightsPerVertex vertexWeights( pMesh->mNumVertices);
|
||||
typedef SmallVector<Weight,8> VertexWeightArray;
|
||||
typedef std::vector<VertexWeightArray> WeightsPerVertex;
|
||||
WeightsPerVertex vertexWeights(pMesh->mNumVertices);
|
||||
size_t maxVertexWeights = 0;
|
||||
|
||||
// collect all weights per vertex
|
||||
for( unsigned int a = 0; a < pMesh->mNumBones; a++)
|
||||
for (unsigned int b = 0; b < pMesh->mNumBones; ++b)
|
||||
{
|
||||
const aiBone* bone = pMesh->mBones[a];
|
||||
for( unsigned int b = 0; b < bone->mNumWeights; b++)
|
||||
const aiBone* bone = pMesh->mBones[b];
|
||||
for (unsigned int w = 0; w < bone->mNumWeights; ++w)
|
||||
{
|
||||
const aiVertexWeight& w = bone->mWeights[b];
|
||||
vertexWeights[w.mVertexId].push_back( Weight( a, w.mWeight));
|
||||
const aiVertexWeight& vw = bone->mWeights[w];
|
||||
vertexWeights[vw.mVertexId].push_back(Weight(b, vw.mWeight));
|
||||
maxVertexWeights = std::max(maxVertexWeights, vertexWeights[vw.mVertexId].size());
|
||||
}
|
||||
}
|
||||
|
||||
if (maxVertexWeights <= mMaxWeights)
|
||||
return;
|
||||
|
||||
unsigned int removed = 0, old_bones = pMesh->mNumBones;
|
||||
|
||||
// now cut the weight count if it exceeds the maximum
|
||||
bool bChanged = false;
|
||||
for( WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit)
|
||||
for (WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit)
|
||||
{
|
||||
if( vit->size() <= mMaxWeights)
|
||||
if (vit->size() <= mMaxWeights)
|
||||
continue;
|
||||
|
||||
bChanged = true;
|
||||
|
||||
// more than the defined maximum -> first sort by weight in descending order. That's
|
||||
// why we defined the < operator in such a weird way.
|
||||
std::sort( vit->begin(), vit->end());
|
||||
std::sort(vit->begin(), vit->end());
|
||||
|
||||
// now kill everything beyond the maximum count
|
||||
unsigned int m = static_cast<unsigned int>(vit->size());
|
||||
vit->erase( vit->begin() + mMaxWeights, vit->end());
|
||||
removed += static_cast<unsigned int>(m-vit->size());
|
||||
vit->resize(mMaxWeights);
|
||||
removed += static_cast<unsigned int>(m - vit->size());
|
||||
|
||||
// and renormalize the weights
|
||||
float sum = 0.0f;
|
||||
for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it ) {
|
||||
for(const Weight* it = vit->begin(); it != vit->end(); ++it) {
|
||||
sum += it->mWeight;
|
||||
}
|
||||
if( 0.0f != sum ) {
|
||||
if (0.0f != sum) {
|
||||
const float invSum = 1.0f / sum;
|
||||
for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it ) {
|
||||
for(Weight* it = vit->begin(); it != vit->end(); ++it) {
|
||||
it->mWeight *= invSum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bChanged) {
|
||||
// rebuild the vertex weight array for all bones
|
||||
typedef std::vector< std::vector< aiVertexWeight > > WeightsPerBone;
|
||||
WeightsPerBone boneWeights( pMesh->mNumBones);
|
||||
for( unsigned int a = 0; a < vertexWeights.size(); a++)
|
||||
// clear weight count for all bone
|
||||
for (unsigned int a = 0; a < pMesh->mNumBones; ++a)
|
||||
{
|
||||
pMesh->mBones[a]->mNumWeights = 0;
|
||||
}
|
||||
|
||||
// rebuild the vertex weight array for all bones
|
||||
for (unsigned int a = 0; a < vertexWeights.size(); ++a)
|
||||
{
|
||||
const VertexWeightArray& vw = vertexWeights[a];
|
||||
for (const Weight* it = vw.begin(); it != vw.end(); ++it)
|
||||
{
|
||||
const std::vector<Weight>& vw = vertexWeights[a];
|
||||
for( std::vector<Weight>::const_iterator it = vw.begin(); it != vw.end(); ++it)
|
||||
boneWeights[it->mBone].push_back( aiVertexWeight( a, it->mWeight));
|
||||
}
|
||||
|
||||
// and finally copy the vertex weight list over to the mesh's bones
|
||||
std::vector<bool> abNoNeed(pMesh->mNumBones,false);
|
||||
bChanged = false;
|
||||
|
||||
for( unsigned int a = 0; a < pMesh->mNumBones; a++)
|
||||
{
|
||||
const std::vector<aiVertexWeight>& bw = boneWeights[a];
|
||||
aiBone* bone = pMesh->mBones[a];
|
||||
|
||||
if ( bw.empty() )
|
||||
{
|
||||
abNoNeed[a] = bChanged = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// copy the weight list. should always be less weights than before, so we don't need a new allocation
|
||||
ai_assert( bw.size() <= bone->mNumWeights);
|
||||
bone->mNumWeights = static_cast<unsigned int>( bw.size() );
|
||||
::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight));
|
||||
}
|
||||
|
||||
if (bChanged) {
|
||||
// the number of new bones is smaller than before, so we can reuse the old array
|
||||
aiBone** ppcCur = pMesh->mBones;aiBone** ppcSrc = ppcCur;
|
||||
|
||||
for (std::vector<bool>::const_iterator iter = abNoNeed.begin();iter != abNoNeed.end() ;++iter) {
|
||||
if (*iter) {
|
||||
delete *ppcSrc;
|
||||
--pMesh->mNumBones;
|
||||
}
|
||||
else *ppcCur++ = *ppcSrc;
|
||||
++ppcSrc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
ASSIMP_LOG_INFO_F("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones );
|
||||
aiBone* bone = pMesh->mBones[it->mBone];
|
||||
bone->mWeights[bone->mNumWeights++] = aiVertexWeight(a, it->mWeight);
|
||||
}
|
||||
}
|
||||
|
||||
// remove empty bones
|
||||
unsigned int writeBone = 0;
|
||||
|
||||
for (unsigned int readBone = 0; readBone< pMesh->mNumBones; ++readBone)
|
||||
{
|
||||
aiBone* bone = pMesh->mBones[readBone];
|
||||
if (bone->mNumWeights > 0)
|
||||
{
|
||||
pMesh->mBones[writeBone++] = bone;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete bone;
|
||||
}
|
||||
}
|
||||
pMesh->mNumBones = writeBone;
|
||||
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
ASSIMP_LOG_INFO_F("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -617,7 +617,7 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *model
|
||||
// We'll leave it up to the user to figure out which extension the file has.
|
||||
aiString name;
|
||||
strncpy( name.data, pTexture->strName, sizeof name.data );
|
||||
name.length = (ai_uint32)strlen( name.data );
|
||||
name.length = static_cast<ai_uint32>(strlen( name.data ));
|
||||
pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -616,7 +616,7 @@ void SMDImporter::CreateOutputMaterials() {
|
||||
if (aszTextures[iMat].length())
|
||||
{
|
||||
::strncpy(szName.data, aszTextures[iMat].c_str(),MAXLEN-1);
|
||||
szName.length = (ai_uint32)aszTextures[iMat].length();
|
||||
szName.length = static_cast<ai_uint32>( aszTextures[iMat].length() );
|
||||
pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -43,17 +41,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** @file Implementation of the Terragen importer class */
|
||||
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER
|
||||
|
||||
#include "TerragenLoader.h"
|
||||
#include <assimp/StreamReader.h>
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
#include <assimp/Importer.hpp>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
@@ -72,78 +68,72 @@ static const aiImporterDesc desc = {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
TerragenImporter::TerragenImporter()
|
||||
: configComputeUVs (false)
|
||||
{}
|
||||
TerragenImporter::TerragenImporter() :
|
||||
configComputeUVs(false) {}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
TerragenImporter::~TerragenImporter()
|
||||
{}
|
||||
TerragenImporter::~TerragenImporter() {}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the class can handle the format of the given file.
|
||||
bool TerragenImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
|
||||
{
|
||||
bool TerragenImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
|
||||
// check file extension
|
||||
std::string extension = GetExtension(pFile);
|
||||
|
||||
if( extension == "ter")
|
||||
if (extension == "ter")
|
||||
return true;
|
||||
|
||||
if( !extension.length() || checkSig) {
|
||||
if (!extension.length() || checkSig) {
|
||||
/* If CanRead() is called in order to check whether we
|
||||
* support a specific file extension in general pIOHandler
|
||||
* might be NULL and it's our duty to return true here.
|
||||
*/
|
||||
if (!pIOHandler)return true;
|
||||
const char* tokens[] = {"terragen"};
|
||||
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
|
||||
if (!pIOHandler) return true;
|
||||
const char *tokens[] = { "terragen" };
|
||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build a string of all file extensions supported
|
||||
const aiImporterDesc* TerragenImporter::GetInfo () const
|
||||
{
|
||||
const aiImporterDesc *TerragenImporter::GetInfo() const {
|
||||
return &desc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup import properties
|
||||
void TerragenImporter::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
void TerragenImporter::SetupProperties(const Importer *pImp) {
|
||||
// AI_CONFIG_IMPORT_TER_MAKE_UVS
|
||||
configComputeUVs = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS,0) );
|
||||
configComputeUVs = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS, 0));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void TerragenImporter::InternReadFile( const std::string& pFile,
|
||||
aiScene* pScene, IOSystem* pIOHandler)
|
||||
{
|
||||
IOStream* file = pIOHandler->Open( pFile, "rb");
|
||||
void TerragenImporter::InternReadFile(const std::string &pFile,
|
||||
aiScene *pScene, IOSystem *pIOHandler) {
|
||||
IOStream *file = pIOHandler->Open(pFile, "rb");
|
||||
|
||||
// Check whether we can read from the file
|
||||
if( file == NULL)
|
||||
throw DeadlyImportError( "Failed to open TERRAGEN TERRAIN file " + pFile + ".");
|
||||
if (file == NULL)
|
||||
throw DeadlyImportError("Failed to open TERRAGEN TERRAIN file " + pFile + ".");
|
||||
|
||||
// Construct a stream reader to read all data in the correct endianness
|
||||
StreamReaderLE reader(file);
|
||||
if(reader.GetRemainingSize() < 16)
|
||||
throw DeadlyImportError( "TER: file is too small" );
|
||||
if (reader.GetRemainingSize() < 16)
|
||||
throw DeadlyImportError("TER: file is too small");
|
||||
|
||||
// Check for the existence of the two magic strings 'TERRAGEN' and 'TERRAIN '
|
||||
if (::strncmp((const char*)reader.GetPtr(),AI_TERR_BASE_STRING,8))
|
||||
throw DeadlyImportError( "TER: Magic string \'TERRAGEN\' not found" );
|
||||
if (::strncmp((const char *)reader.GetPtr(), AI_TERR_BASE_STRING, 8))
|
||||
throw DeadlyImportError("TER: Magic string \'TERRAGEN\' not found");
|
||||
|
||||
if (::strncmp((const char*)reader.GetPtr()+8,AI_TERR_TERRAIN_STRING,8))
|
||||
throw DeadlyImportError( "TER: Magic string \'TERRAIN\' not found" );
|
||||
if (::strncmp((const char *)reader.GetPtr() + 8, AI_TERR_TERRAIN_STRING, 8))
|
||||
throw DeadlyImportError("TER: Magic string \'TERRAIN\' not found");
|
||||
|
||||
unsigned int x = 0,y = 0,mode = 0;
|
||||
unsigned int x = 0, y = 0, mode = 0;
|
||||
|
||||
aiNode* root = pScene->mRootNode = new aiNode();
|
||||
aiNode *root = pScene->mRootNode = new aiNode();
|
||||
root->mName.Set("<TERRAGEN.TERRAIN>");
|
||||
|
||||
// Default scaling is 30
|
||||
@@ -151,104 +141,98 @@ void TerragenImporter::InternReadFile( const std::string& pFile,
|
||||
|
||||
// Now read all chunks until we're finished or an EOF marker is encountered
|
||||
reader.IncPtr(16);
|
||||
while (reader.GetRemainingSize() >= 4)
|
||||
{
|
||||
const char* head = (const char*)reader.GetPtr();
|
||||
while (reader.GetRemainingSize() >= 4) {
|
||||
const char *head = (const char *)reader.GetPtr();
|
||||
reader.IncPtr(4);
|
||||
|
||||
// EOF, break in every case
|
||||
if (!::strncmp(head,AI_TERR_EOF_STRING,4))
|
||||
if (!::strncmp(head, AI_TERR_EOF_STRING, 4))
|
||||
break;
|
||||
|
||||
// Number of x-data points
|
||||
if (!::strncmp(head,AI_TERR_CHUNK_XPTS,4))
|
||||
{
|
||||
if (!::strncmp(head, AI_TERR_CHUNK_XPTS, 4)) {
|
||||
x = (uint16_t)reader.GetI2();
|
||||
}
|
||||
// Number of y-data points
|
||||
else if (!::strncmp(head,AI_TERR_CHUNK_YPTS,4))
|
||||
{
|
||||
else if (!::strncmp(head, AI_TERR_CHUNK_YPTS, 4)) {
|
||||
y = (uint16_t)reader.GetI2();
|
||||
}
|
||||
// Squared terrains width-1.
|
||||
else if (!::strncmp(head,AI_TERR_CHUNK_SIZE,4))
|
||||
{
|
||||
x = y = (uint16_t)reader.GetI2()+1;
|
||||
else if (!::strncmp(head, AI_TERR_CHUNK_SIZE, 4)) {
|
||||
x = y = (uint16_t)reader.GetI2() + 1;
|
||||
}
|
||||
// terrain scaling
|
||||
else if (!::strncmp(head,AI_TERR_CHUNK_SCAL,4))
|
||||
{
|
||||
else if (!::strncmp(head, AI_TERR_CHUNK_SCAL, 4)) {
|
||||
root->mTransformation.a1 = reader.GetF4();
|
||||
root->mTransformation.b2 = reader.GetF4();
|
||||
root->mTransformation.c3 = reader.GetF4();
|
||||
}
|
||||
// mapping == 1: earth radius
|
||||
else if (!::strncmp(head,AI_TERR_CHUNK_CRAD,4))
|
||||
{
|
||||
else if (!::strncmp(head, AI_TERR_CHUNK_CRAD, 4)) {
|
||||
reader.GetF4();
|
||||
}
|
||||
// mapping mode
|
||||
else if (!::strncmp(head,AI_TERR_CHUNK_CRVM,4))
|
||||
{
|
||||
else if (!::strncmp(head, AI_TERR_CHUNK_CRVM, 4)) {
|
||||
mode = reader.GetI1();
|
||||
if (0 != mode)
|
||||
ASSIMP_LOG_ERROR("TER: Unsupported mapping mode, a flat terrain is returned");
|
||||
}
|
||||
// actual terrain data
|
||||
else if (!::strncmp(head,AI_TERR_CHUNK_ALTW,4))
|
||||
{
|
||||
float hscale = (float)reader.GetI2() / 65536;
|
||||
else if (!::strncmp(head, AI_TERR_CHUNK_ALTW, 4)) {
|
||||
float hscale = (float)reader.GetI2() / 65536;
|
||||
float bheight = (float)reader.GetI2();
|
||||
|
||||
if (!hscale)hscale = 1;
|
||||
if (!hscale) hscale = 1;
|
||||
|
||||
// Ensure we have enough data
|
||||
if (reader.GetRemainingSize() < x*y*2)
|
||||
if (reader.GetRemainingSize() < x * y * 2)
|
||||
throw DeadlyImportError("TER: ALTW chunk is too small");
|
||||
|
||||
if (x <= 1 || y <= 1)
|
||||
throw DeadlyImportError("TER: Invalid terrain size");
|
||||
|
||||
// Allocate the output mesh
|
||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes = 1];
|
||||
aiMesh* m = pScene->mMeshes[0] = new aiMesh();
|
||||
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes = 1];
|
||||
aiMesh *m = pScene->mMeshes[0] = new aiMesh();
|
||||
|
||||
// We return quads
|
||||
aiFace* f = m->mFaces = new aiFace[m->mNumFaces = (x-1)*(y-1)];
|
||||
aiVector3D* pv = m->mVertices = new aiVector3D[m->mNumVertices = m->mNumFaces*4];
|
||||
aiFace *f = m->mFaces = new aiFace[m->mNumFaces = (x - 1) * (y - 1)];
|
||||
aiVector3D *pv = m->mVertices = new aiVector3D[m->mNumVertices = m->mNumFaces * 4];
|
||||
|
||||
aiVector3D *uv( NULL );
|
||||
float step_y( 0.0f ), step_x( 0.0f );
|
||||
aiVector3D *uv(NULL);
|
||||
float step_y(0.0f), step_x(0.0f);
|
||||
if (configComputeUVs) {
|
||||
uv = m->mTextureCoords[0] = new aiVector3D[m->mNumVertices];
|
||||
step_y = 1.f/y;
|
||||
step_x = 1.f/x;
|
||||
step_y = 1.f / y;
|
||||
step_x = 1.f / x;
|
||||
}
|
||||
const int16_t* data = (const int16_t*)reader.GetPtr();
|
||||
const int16_t *data = (const int16_t *)reader.GetPtr();
|
||||
|
||||
for (unsigned int yy = 0, t = 0; yy < y-1;++yy) {
|
||||
for (unsigned int xx = 0; xx < x-1;++xx,++f) {
|
||||
for (unsigned int yy = 0, t = 0; yy < y - 1; ++yy) {
|
||||
for (unsigned int xx = 0; xx < x - 1; ++xx, ++f) {
|
||||
|
||||
// make verts
|
||||
const float fy = (float)yy, fx = (float)xx;
|
||||
unsigned tmp,tmp2;
|
||||
*pv++ = aiVector3D(fx,fy, (float)data[(tmp2=x*yy) + xx] * hscale + bheight);
|
||||
*pv++ = aiVector3D(fx,fy+1, (float)data[(tmp=x*(yy+1)) + xx] * hscale + bheight);
|
||||
*pv++ = aiVector3D(fx+1,fy+1,(float)data[tmp + xx+1] * hscale + bheight);
|
||||
*pv++ = aiVector3D(fx+1,fy, (float)data[tmp2 + xx+1] * hscale + bheight);
|
||||
unsigned tmp, tmp2;
|
||||
*pv++ = aiVector3D(fx, fy, (float)data[(tmp2 = x * yy) + xx] * hscale + bheight);
|
||||
*pv++ = aiVector3D(fx, fy + 1, (float)data[(tmp = x * (yy + 1)) + xx] * hscale + bheight);
|
||||
*pv++ = aiVector3D(fx + 1, fy + 1, (float)data[tmp + xx + 1] * hscale + bheight);
|
||||
*pv++ = aiVector3D(fx + 1, fy, (float)data[tmp2 + xx + 1] * hscale + bheight);
|
||||
|
||||
// also make texture coordinates, if necessary
|
||||
if (configComputeUVs) {
|
||||
*uv++ = aiVector3D( step_x*xx, step_y*yy, 0.f );
|
||||
*uv++ = aiVector3D( step_x*xx, step_y*(yy+1), 0.f );
|
||||
*uv++ = aiVector3D( step_x*(xx+1), step_y*(yy+1), 0.f );
|
||||
*uv++ = aiVector3D( step_x*(xx+1), step_y*yy, 0.f );
|
||||
*uv++ = aiVector3D(step_x * xx, step_y * yy, 0.f);
|
||||
*uv++ = aiVector3D(step_x * xx, step_y * (yy + 1), 0.f);
|
||||
*uv++ = aiVector3D(step_x * (xx + 1), step_y * (yy + 1), 0.f);
|
||||
*uv++ = aiVector3D(step_x * (xx + 1), step_y * yy, 0.f);
|
||||
}
|
||||
|
||||
// make indices
|
||||
f->mIndices = new unsigned int[f->mNumIndices = 4];
|
||||
for (unsigned int i = 0; i < 4;++i)
|
||||
f->mIndices[i] = t++;
|
||||
for (unsigned int i = 0; i < 4; ++i) {
|
||||
f->mIndices[i] = t;
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -47,21 +46,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define INCLUDED_AI_TERRAGEN_TERRAIN_LOADER_H
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
namespace Assimp {
|
||||
namespace Assimp {
|
||||
|
||||
// Magic strings
|
||||
#define AI_TERR_BASE_STRING "TERRAGEN"
|
||||
#define AI_TERR_TERRAIN_STRING "TERRAIN "
|
||||
#define AI_TERR_EOF_STRING "EOF "
|
||||
#define AI_TERR_BASE_STRING "TERRAGEN"
|
||||
#define AI_TERR_TERRAIN_STRING "TERRAIN "
|
||||
#define AI_TERR_EOF_STRING "EOF "
|
||||
|
||||
// Chunka
|
||||
#define AI_TERR_CHUNK_XPTS "XPTS"
|
||||
#define AI_TERR_CHUNK_YPTS "YPTS"
|
||||
#define AI_TERR_CHUNK_SIZE "SIZE"
|
||||
#define AI_TERR_CHUNK_SCAL "SCAL"
|
||||
#define AI_TERR_CHUNK_CRAD "CRAD"
|
||||
#define AI_TERR_CHUNK_CRVM "CRVM"
|
||||
#define AI_TERR_CHUNK_ALTW "ALTW"
|
||||
#define AI_TERR_CHUNK_XPTS "XPTS"
|
||||
#define AI_TERR_CHUNK_YPTS "YPTS"
|
||||
#define AI_TERR_CHUNK_SIZE "SIZE"
|
||||
#define AI_TERR_CHUNK_SCAL "SCAL"
|
||||
#define AI_TERR_CHUNK_CRAD "CRAD"
|
||||
#define AI_TERR_CHUNK_CRVM "CRVM"
|
||||
#define AI_TERR_CHUNK_ALTW "ALTW"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Importer class to load Terragen (0.9) terrain files.
|
||||
@@ -69,33 +68,28 @@ namespace Assimp {
|
||||
* The loader is basing on the information found here:
|
||||
* http://www.planetside.co.uk/terragen/dev/tgterrain.html#chunks
|
||||
*/
|
||||
class TerragenImporter : public BaseImporter
|
||||
{
|
||||
class TerragenImporter : public BaseImporter {
|
||||
public:
|
||||
TerragenImporter();
|
||||
~TerragenImporter();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
|
||||
bool checkSig) const;
|
||||
bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
|
||||
bool checkSig) const;
|
||||
|
||||
protected:
|
||||
// -------------------------------------------------------------------
|
||||
const aiImporterDesc *GetInfo() const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
const aiImporterDesc* GetInfo () const;
|
||||
void InternReadFile(const std::string &pFile, aiScene *pScene,
|
||||
IOSystem *pIOHandler);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void InternReadFile( const std::string& pFile, aiScene* pScene,
|
||||
IOSystem* pIOHandler);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void SetupProperties(const Importer* pImp);
|
||||
void SetupProperties(const Importer *pImp);
|
||||
|
||||
private:
|
||||
|
||||
bool configComputeUVs;
|
||||
|
||||
}; //! class TerragenImporter
|
||||
|
||||
+211
-140
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -48,26 +46,112 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* http://local.wasp.uwa.edu.au/~pbourke/dataformats/unreal/
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_3D_IMPORTER
|
||||
|
||||
#include "Unreal/UnrealLoader.h"
|
||||
#include "PostProcessing/ConvertToLHProcess.h"
|
||||
|
||||
#include <assimp/StreamReader.h>
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include <assimp/StreamReader.h>
|
||||
#include <assimp/fast_atof.h>
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/Importer.hpp>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
namespace Unreal {
|
||||
|
||||
/*
|
||||
0 = Normal one-sided
|
||||
1 = Normal two-sided
|
||||
2 = Translucent two-sided
|
||||
3 = Masked two-sided
|
||||
4 = Modulation blended two-sided
|
||||
8 = Placeholder triangle for weapon positioning (invisible)
|
||||
*/
|
||||
enum MeshFlags {
|
||||
MF_NORMAL_OS = 0,
|
||||
MF_NORMAL_TS = 1,
|
||||
MF_NORMAL_TRANS_TS = 2,
|
||||
MF_NORMAL_MASKED_TS = 3,
|
||||
MF_NORMAL_MOD_TS = 4,
|
||||
MF_WEAPON_PLACEHOLDER = 8
|
||||
};
|
||||
|
||||
// a single triangle
|
||||
struct Triangle {
|
||||
uint16_t mVertex[3]; // Vertex indices
|
||||
char mType; // James' Mesh Type
|
||||
char mColor; // Color for flat and Gourand Shaded
|
||||
unsigned char mTex[3][2]; // Texture UV coordinates
|
||||
unsigned char mTextureNum; // Source texture offset
|
||||
char mFlags; // Unreal Mesh Flags (unused)
|
||||
unsigned int matIndex;
|
||||
};
|
||||
|
||||
// temporary representation for a material
|
||||
struct TempMat {
|
||||
TempMat() :
|
||||
type(MF_NORMAL_OS), tex(), numFaces(0) {}
|
||||
|
||||
explicit TempMat(const Triangle &in) :
|
||||
type((Unreal::MeshFlags)in.mType), tex(in.mTextureNum), numFaces(0) {}
|
||||
|
||||
// type of mesh
|
||||
Unreal::MeshFlags type;
|
||||
|
||||
// index of texture
|
||||
unsigned int tex;
|
||||
|
||||
// number of faces using us
|
||||
unsigned int numFaces;
|
||||
|
||||
// for std::find
|
||||
bool operator==(const TempMat &o) {
|
||||
return (tex == o.tex && type == o.type);
|
||||
}
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
int32_t X : 11;
|
||||
int32_t Y : 11;
|
||||
int32_t Z : 10;
|
||||
};
|
||||
|
||||
// UNREAL vertex compression
|
||||
inline void CompressVertex(const aiVector3D &v, uint32_t &out) {
|
||||
union {
|
||||
Vertex n;
|
||||
int32_t t;
|
||||
};
|
||||
t = 0;
|
||||
n.X = (int32_t)v.x;
|
||||
n.Y = (int32_t)v.y;
|
||||
n.Z = (int32_t)v.z;
|
||||
::memcpy(&out, &t, sizeof(int32_t));
|
||||
}
|
||||
|
||||
// UNREAL vertex decompression
|
||||
inline void DecompressVertex(aiVector3D &v, int32_t in) {
|
||||
union {
|
||||
Vertex n;
|
||||
int32_t i;
|
||||
};
|
||||
i = in;
|
||||
|
||||
v.x = (float)n.X;
|
||||
v.y = (float)n.Y;
|
||||
v.z = (float)n.Z;
|
||||
}
|
||||
|
||||
} // end namespace Unreal
|
||||
|
||||
static const aiImporterDesc desc = {
|
||||
"Unreal Mesh Importer",
|
||||
"",
|
||||
@@ -81,79 +165,70 @@ static const aiImporterDesc desc = {
|
||||
"3d uc"
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
UnrealImporter::UnrealImporter()
|
||||
: configFrameID (0)
|
||||
, configHandleFlags (true)
|
||||
{}
|
||||
UnrealImporter::UnrealImporter() :
|
||||
mConfigFrameID(0), mConfigHandleFlags(true) {}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
UnrealImporter::~UnrealImporter()
|
||||
{}
|
||||
UnrealImporter::~UnrealImporter() {}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the class can handle the format of the given file.
|
||||
bool UnrealImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
|
||||
{
|
||||
return SimpleExtensionCheck(pFile,"3d","uc");
|
||||
bool UnrealImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
|
||||
return SimpleExtensionCheck(pFile, "3d", "uc");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build a string of all file extensions supported
|
||||
const aiImporterDesc* UnrealImporter::GetInfo () const
|
||||
{
|
||||
const aiImporterDesc *UnrealImporter::GetInfo() const {
|
||||
return &desc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties for the loader
|
||||
void UnrealImporter::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
void UnrealImporter::SetupProperties(const Importer *pImp) {
|
||||
// The
|
||||
// AI_CONFIG_IMPORT_UNREAL_KEYFRAME option overrides the
|
||||
// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
|
||||
configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_KEYFRAME,-1);
|
||||
if(static_cast<unsigned int>(-1) == configFrameID) {
|
||||
configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
|
||||
mConfigFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_KEYFRAME, -1);
|
||||
if (static_cast<unsigned int>(-1) == mConfigFrameID) {
|
||||
mConfigFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME, 0);
|
||||
}
|
||||
|
||||
// AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS, default is true
|
||||
configHandleFlags = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS,1));
|
||||
mConfigHandleFlags = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS, 1));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void UnrealImporter::InternReadFile( const std::string& pFile,
|
||||
aiScene* pScene, IOSystem* pIOHandler)
|
||||
{
|
||||
void UnrealImporter::InternReadFile(const std::string &pFile,
|
||||
aiScene *pScene, IOSystem *pIOHandler) {
|
||||
// For any of the 3 files being passed get the three correct paths
|
||||
// First of all, determine file extension
|
||||
std::string::size_type pos = pFile.find_last_of('.');
|
||||
std::string extension = GetExtension(pFile);
|
||||
|
||||
std::string d_path,a_path,uc_path;
|
||||
if (extension == "3d") {
|
||||
std::string d_path, a_path, uc_path;
|
||||
if (extension == "3d") {
|
||||
// jjjj_d.3d
|
||||
// jjjj_a.3d
|
||||
pos = pFile.find_last_of('_');
|
||||
if (std::string::npos == pos) {
|
||||
throw DeadlyImportError("UNREAL: Unexpected naming scheme");
|
||||
}
|
||||
extension = pFile.substr(0,pos);
|
||||
}
|
||||
else {
|
||||
extension = pFile.substr(0,pos);
|
||||
extension = pFile.substr(0, pos);
|
||||
} else {
|
||||
extension = pFile.substr(0, pos);
|
||||
}
|
||||
|
||||
// build proper paths
|
||||
d_path = extension+"_d.3d";
|
||||
a_path = extension+"_a.3d";
|
||||
uc_path = extension+".uc";
|
||||
d_path = extension + "_d.3d";
|
||||
a_path = extension + "_a.3d";
|
||||
uc_path = extension + ".uc";
|
||||
|
||||
ASSIMP_LOG_DEBUG_F( "UNREAL: data file is ", d_path);
|
||||
ASSIMP_LOG_DEBUG_F("UNREAL: data file is ", d_path);
|
||||
ASSIMP_LOG_DEBUG_F("UNREAL: aniv file is ", a_path);
|
||||
ASSIMP_LOG_DEBUG_F("UNREAL: uc file is ", uc_path);
|
||||
|
||||
@@ -174,11 +249,11 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
|
||||
|
||||
// collect triangles
|
||||
std::vector<Unreal::Triangle> triangles(numTris);
|
||||
for (auto & tri : triangles) {
|
||||
for (unsigned int i = 0; i < 3;++i) {
|
||||
for (auto &tri : triangles) {
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
|
||||
tri.mVertex[i] = d_reader.GetI2();
|
||||
if (tri.mVertex[i] >= numTris) {
|
||||
if (tri.mVertex[i] >= numTris) {
|
||||
ASSIMP_LOG_WARN("UNREAL: vertex index out of range");
|
||||
tri.mVertex[i] = 0;
|
||||
}
|
||||
@@ -186,7 +261,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
|
||||
tri.mType = d_reader.GetI1();
|
||||
|
||||
// handle mesh flagss?
|
||||
if (configHandleFlags)
|
||||
if (mConfigHandleFlags)
|
||||
tri.mType = Unreal::MF_NORMAL_OS;
|
||||
else {
|
||||
// ignore MOD and MASKED for the moment, treat them as two-sided
|
||||
@@ -195,12 +270,12 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
|
||||
}
|
||||
d_reader.IncPtr(1);
|
||||
|
||||
for (unsigned int i = 0; i < 3;++i)
|
||||
for (unsigned int i2 = 0; i2 < 2;++i2)
|
||||
for (unsigned int i = 0; i < 3; ++i)
|
||||
for (unsigned int i2 = 0; i2 < 2; ++i2)
|
||||
tri.mTex[i][i2] = d_reader.GetI1();
|
||||
|
||||
tri.mTextureNum = d_reader.GetI1();
|
||||
maxTexIdx = std::max(maxTexIdx,(unsigned int)tri.mTextureNum);
|
||||
maxTexIdx = std::max(maxTexIdx, (unsigned int)tri.mTextureNum);
|
||||
d_reader.IncPtr(1);
|
||||
}
|
||||
|
||||
@@ -211,63 +286,64 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
|
||||
|
||||
// read number of frames
|
||||
const uint32_t numFrames = a_reader.GetI2();
|
||||
if (configFrameID >= numFrames) {
|
||||
if (mConfigFrameID >= numFrames) {
|
||||
throw DeadlyImportError("UNREAL: The requested frame does not exist");
|
||||
}
|
||||
|
||||
uint32_t st = a_reader.GetI2();
|
||||
if (st != numVert*4u)
|
||||
if (st != numVert * 4u)
|
||||
throw DeadlyImportError("UNREAL: Unexpected aniv file length");
|
||||
|
||||
// skip to our frame
|
||||
a_reader.IncPtr(configFrameID *numVert*4);
|
||||
a_reader.IncPtr(mConfigFrameID * numVert * 4);
|
||||
|
||||
// collect vertices
|
||||
std::vector<aiVector3D> vertices(numVert);
|
||||
for (auto &vertex : vertices) {
|
||||
for (auto &vertex : vertices) {
|
||||
int32_t val = a_reader.GetI4();
|
||||
Unreal::DecompressVertex(vertex ,val);
|
||||
Unreal::DecompressVertex(vertex, val);
|
||||
}
|
||||
|
||||
// list of textures.
|
||||
std::vector< std::pair<unsigned int, std::string> > textures;
|
||||
std::vector<std::pair<unsigned int, std::string>> textures;
|
||||
|
||||
// allocate the output scene
|
||||
aiNode* nd = pScene->mRootNode = new aiNode();
|
||||
aiNode *nd = pScene->mRootNode = new aiNode();
|
||||
nd->mName.Set("<UnrealRoot>");
|
||||
|
||||
// we can live without the uc file if necessary
|
||||
std::unique_ptr<IOStream> pb (pIOHandler->Open(uc_path));
|
||||
if (pb.get()) {
|
||||
std::unique_ptr<IOStream> pb(pIOHandler->Open(uc_path));
|
||||
if (pb.get()) {
|
||||
|
||||
std::vector<char> _data;
|
||||
TextFileToBuffer(pb.get(),_data);
|
||||
const char* data = &_data[0];
|
||||
TextFileToBuffer(pb.get(), _data);
|
||||
const char *data = &_data[0];
|
||||
|
||||
std::vector< std::pair< std::string,std::string > > tempTextures;
|
||||
std::vector<std::pair<std::string, std::string>> tempTextures;
|
||||
|
||||
// do a quick search in the UC file for some known, usually texture-related, tags
|
||||
for (;*data;++data) {
|
||||
if (TokenMatchI(data,"#exec",5)) {
|
||||
for (; *data; ++data) {
|
||||
if (TokenMatchI(data, "#exec", 5)) {
|
||||
SkipSpacesAndLineEnd(&data);
|
||||
|
||||
// #exec TEXTURE IMPORT [...] NAME=jjjjj [...] FILE=jjjj.pcx [...]
|
||||
if (TokenMatchI(data,"TEXTURE",7)) {
|
||||
if (TokenMatchI(data, "TEXTURE", 7)) {
|
||||
SkipSpacesAndLineEnd(&data);
|
||||
|
||||
if (TokenMatchI(data,"IMPORT",6)) {
|
||||
tempTextures.push_back(std::pair< std::string,std::string >());
|
||||
std::pair< std::string,std::string >& me = tempTextures.back();
|
||||
for (;!IsLineEnd(*data);++data) {
|
||||
if (!::ASSIMP_strincmp(data,"NAME=",5)) {
|
||||
const char *d = data+=5;
|
||||
for (;!IsSpaceOrNewLine(*data);++data);
|
||||
me.first = std::string(d,(size_t)(data-d));
|
||||
}
|
||||
else if (!::ASSIMP_strincmp(data,"FILE=",5)) {
|
||||
const char *d = data+=5;
|
||||
for (;!IsSpaceOrNewLine(*data);++data);
|
||||
me.second = std::string(d,(size_t)(data-d));
|
||||
if (TokenMatchI(data, "IMPORT", 6)) {
|
||||
tempTextures.push_back(std::pair<std::string, std::string>());
|
||||
std::pair<std::string, std::string> &me = tempTextures.back();
|
||||
for (; !IsLineEnd(*data); ++data) {
|
||||
if (!::ASSIMP_strincmp(data, "NAME=", 5)) {
|
||||
const char *d = data += 5;
|
||||
for (; !IsSpaceOrNewLine(*data); ++data)
|
||||
;
|
||||
me.first = std::string(d, (size_t)(data - d));
|
||||
} else if (!::ASSIMP_strincmp(data, "FILE=", 5)) {
|
||||
const char *d = data += 5;
|
||||
for (; !IsSpaceOrNewLine(*data); ++data)
|
||||
;
|
||||
me.second = std::string(d, (size_t)(data - d));
|
||||
}
|
||||
}
|
||||
if (!me.first.length() || !me.second.length())
|
||||
@@ -276,65 +352,61 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
|
||||
}
|
||||
// #exec MESHMAP SETTEXTURE MESHMAP=box NUM=1 TEXTURE=Jtex1
|
||||
// #exec MESHMAP SCALE MESHMAP=box X=0.1 Y=0.1 Z=0.2
|
||||
else if (TokenMatchI(data,"MESHMAP",7)) {
|
||||
else if (TokenMatchI(data, "MESHMAP", 7)) {
|
||||
SkipSpacesAndLineEnd(&data);
|
||||
|
||||
if (TokenMatchI(data,"SETTEXTURE",10)) {
|
||||
if (TokenMatchI(data, "SETTEXTURE", 10)) {
|
||||
|
||||
textures.push_back(std::pair<unsigned int, std::string>());
|
||||
std::pair<unsigned int, std::string>& me = textures.back();
|
||||
std::pair<unsigned int, std::string> &me = textures.back();
|
||||
|
||||
for (;!IsLineEnd(*data);++data) {
|
||||
if (!::ASSIMP_strincmp(data,"NUM=",4)) {
|
||||
for (; !IsLineEnd(*data); ++data) {
|
||||
if (!::ASSIMP_strincmp(data, "NUM=", 4)) {
|
||||
data += 4;
|
||||
me.first = strtoul10(data,&data);
|
||||
}
|
||||
else if (!::ASSIMP_strincmp(data,"TEXTURE=",8)) {
|
||||
me.first = strtoul10(data, &data);
|
||||
} else if (!::ASSIMP_strincmp(data, "TEXTURE=", 8)) {
|
||||
data += 8;
|
||||
const char *d = data;
|
||||
for (;!IsSpaceOrNewLine(*data);++data);
|
||||
me.second = std::string(d,(size_t)(data-d));
|
||||
for (; !IsSpaceOrNewLine(*data); ++data)
|
||||
;
|
||||
me.second = std::string(d, (size_t)(data - d));
|
||||
|
||||
// try to find matching path names, doesn't care if we don't find them
|
||||
for (std::vector< std::pair< std::string,std::string > >::const_iterator it = tempTextures.begin();
|
||||
it != tempTextures.end(); ++it) {
|
||||
if ((*it).first == me.second) {
|
||||
for (std::vector<std::pair<std::string, std::string>>::const_iterator it = tempTextures.begin();
|
||||
it != tempTextures.end(); ++it) {
|
||||
if ((*it).first == me.second) {
|
||||
me.second = (*it).second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (TokenMatchI(data,"SCALE",5)) {
|
||||
} else if (TokenMatchI(data, "SCALE", 5)) {
|
||||
|
||||
for (;!IsLineEnd(*data);++data) {
|
||||
if (data[0] == 'X' && data[1] == '=') {
|
||||
data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.a1);
|
||||
}
|
||||
else if (data[0] == 'Y' && data[1] == '=') {
|
||||
data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.b2);
|
||||
}
|
||||
else if (data[0] == 'Z' && data[1] == '=') {
|
||||
data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.c3);
|
||||
for (; !IsLineEnd(*data); ++data) {
|
||||
if (data[0] == 'X' && data[1] == '=') {
|
||||
data = fast_atoreal_move<float>(data + 2, (float &)nd->mTransformation.a1);
|
||||
} else if (data[0] == 'Y' && data[1] == '=') {
|
||||
data = fast_atoreal_move<float>(data + 2, (float &)nd->mTransformation.b2);
|
||||
} else if (data[0] == 'Z' && data[1] == '=') {
|
||||
data = fast_atoreal_move<float>(data + 2, (float &)nd->mTransformation.c3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Unable to open .uc file");
|
||||
}
|
||||
|
||||
std::vector<Unreal::TempMat> materials;
|
||||
materials.reserve(textures.size()*2+5);
|
||||
materials.reserve(textures.size() * 2 + 5);
|
||||
|
||||
// find out how many output meshes and materials we'll have and build material indices
|
||||
for (Unreal::Triangle &tri : triangles) {
|
||||
for (Unreal::Triangle &tri : triangles) {
|
||||
Unreal::TempMat mat(tri);
|
||||
std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat);
|
||||
std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(), materials.end(), mat);
|
||||
if (nt == materials.end()) {
|
||||
// add material
|
||||
tri.matIndex = static_cast<unsigned int>(materials.size());
|
||||
@@ -342,9 +414,8 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
|
||||
materials.push_back(mat);
|
||||
|
||||
++pScene->mNumMeshes;
|
||||
}
|
||||
else {
|
||||
tri.matIndex = static_cast<unsigned int>(nt-materials.begin());
|
||||
} else {
|
||||
tri.matIndex = static_cast<unsigned int>(nt - materials.begin());
|
||||
++nt->numFaces;
|
||||
}
|
||||
}
|
||||
@@ -354,65 +425,65 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
|
||||
}
|
||||
|
||||
// allocate meshes and bind them to the node graph
|
||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes];
|
||||
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
|
||||
pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials = pScene->mNumMeshes];
|
||||
|
||||
nd->mNumMeshes = pScene->mNumMeshes;
|
||||
nd->mNumMeshes = pScene->mNumMeshes;
|
||||
nd->mMeshes = new unsigned int[nd->mNumMeshes];
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
|
||||
aiMesh* m = pScene->mMeshes[i] = new aiMesh();
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
aiMesh *m = pScene->mMeshes[i] = new aiMesh();
|
||||
m->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
|
||||
|
||||
const unsigned int num = materials[i].numFaces;
|
||||
m->mFaces = new aiFace [num];
|
||||
m->mVertices = new aiVector3D [num*3];
|
||||
m->mTextureCoords[0] = new aiVector3D [num*3];
|
||||
m->mFaces = new aiFace[num];
|
||||
m->mVertices = new aiVector3D[num * 3];
|
||||
m->mTextureCoords[0] = new aiVector3D[num * 3];
|
||||
|
||||
nd->mMeshes[i] = i;
|
||||
|
||||
// create materials, too
|
||||
aiMaterial* mat = new aiMaterial();
|
||||
aiMaterial *mat = new aiMaterial();
|
||||
pScene->mMaterials[i] = mat;
|
||||
|
||||
// all white by default - texture rulez
|
||||
aiColor3D color(1.f,1.f,1.f);
|
||||
aiColor3D color(1.f, 1.f, 1.f);
|
||||
|
||||
aiString s;
|
||||
::ai_snprintf( s.data, MAXLEN, "mat%u_tx%u_",i,materials[i].tex );
|
||||
::ai_snprintf(s.data, MAXLEN, "mat%u_tx%u_", i, materials[i].tex);
|
||||
|
||||
// set the two-sided flag
|
||||
if (materials[i].type == Unreal::MF_NORMAL_TS) {
|
||||
const int twosided = 1;
|
||||
mat->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED);
|
||||
::strcat(s.data,"ts_");
|
||||
}
|
||||
else ::strcat(s.data,"os_");
|
||||
mat->AddProperty(&twosided, 1, AI_MATKEY_TWOSIDED);
|
||||
::strcat(s.data, "ts_");
|
||||
} else
|
||||
::strcat(s.data, "os_");
|
||||
|
||||
// make TRANS faces 90% opaque that RemRedundantMaterials won't catch us
|
||||
if (materials[i].type == Unreal::MF_NORMAL_TRANS_TS) {
|
||||
if (materials[i].type == Unreal::MF_NORMAL_TRANS_TS) {
|
||||
const float opac = 0.9f;
|
||||
mat->AddProperty(&opac,1,AI_MATKEY_OPACITY);
|
||||
::strcat(s.data,"tran_");
|
||||
}
|
||||
else ::strcat(s.data,"opaq_");
|
||||
mat->AddProperty(&opac, 1, AI_MATKEY_OPACITY);
|
||||
::strcat(s.data, "tran_");
|
||||
} else
|
||||
::strcat(s.data, "opaq_");
|
||||
|
||||
// a special name for the weapon attachment point
|
||||
if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER) {
|
||||
s.length = ::ai_snprintf( s.data, MAXLEN, "$WeaponTag$" );
|
||||
color = aiColor3D(0.f,0.f,0.f);
|
||||
s.length = ::ai_snprintf(s.data, MAXLEN, "$WeaponTag$");
|
||||
color = aiColor3D(0.f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
// set color and name
|
||||
mat->AddProperty(&color,1,AI_MATKEY_COLOR_DIFFUSE);
|
||||
s.length = (ai_uint32)::strlen(s.data);
|
||||
mat->AddProperty(&s,AI_MATKEY_NAME);
|
||||
mat->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
s.length = static_cast<ai_uint32>(::strlen(s.data));
|
||||
mat->AddProperty(&s, AI_MATKEY_NAME);
|
||||
|
||||
// set texture, if any
|
||||
const unsigned int tex = materials[i].tex;
|
||||
for (std::vector< std::pair< unsigned int, std::string > >::const_iterator it = textures.begin();it != textures.end();++it) {
|
||||
for (std::vector<std::pair<unsigned int, std::string>>::const_iterator it = textures.begin(); it != textures.end(); ++it) {
|
||||
if ((*it).first == tex) {
|
||||
s.Set((*it).second);
|
||||
mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
mat->AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -421,17 +492,17 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
|
||||
// fill them.
|
||||
for (const Unreal::Triangle &tri : triangles) {
|
||||
Unreal::TempMat mat(tri);
|
||||
std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat);
|
||||
std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(), materials.end(), mat);
|
||||
|
||||
aiMesh* mesh = pScene->mMeshes[nt-materials.begin()];
|
||||
aiFace& f = mesh->mFaces[mesh->mNumFaces++];
|
||||
f.mIndices = new unsigned int[f.mNumIndices = 3];
|
||||
aiMesh *mesh = pScene->mMeshes[nt - materials.begin()];
|
||||
aiFace &f = mesh->mFaces[mesh->mNumFaces++];
|
||||
f.mIndices = new unsigned int[f.mNumIndices = 3];
|
||||
|
||||
for (unsigned int i = 0; i < 3;++i,mesh->mNumVertices++) {
|
||||
for (unsigned int i = 0; i < 3; ++i, mesh->mNumVertices++) {
|
||||
f.mIndices[i] = mesh->mNumVertices;
|
||||
|
||||
mesh->mVertices[mesh->mNumVertices] = vertices[ tri.mVertex[i] ];
|
||||
mesh->mTextureCoords[0][mesh->mNumVertices] = aiVector3D( tri.mTex[i][0] / 255.f, 1.f - tri.mTex[i][1] / 255.f, 0.f);
|
||||
mesh->mVertices[mesh->mNumVertices] = vertices[tri.mVertex[i]];
|
||||
mesh->mTextureCoords[0][mesh->mNumVertices] = aiVector3D(tri.mTex[i][0] / 255.f, 1.f - tri.mTex[i][1] / 255.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-116
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -47,161 +46,57 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define INCLUDED_AI_3D_LOADER_H
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Unreal {
|
||||
|
||||
/*
|
||||
0 = Normal one-sided
|
||||
1 = Normal two-sided
|
||||
2 = Translucent two-sided
|
||||
3 = Masked two-sided
|
||||
4 = Modulation blended two-sided
|
||||
8 = Placeholder triangle for weapon positioning (invisible)
|
||||
*/
|
||||
enum MeshFlags {
|
||||
MF_NORMAL_OS = 0,
|
||||
MF_NORMAL_TS = 1,
|
||||
MF_NORMAL_TRANS_TS = 2,
|
||||
MF_NORMAL_MASKED_TS = 3,
|
||||
MF_NORMAL_MOD_TS = 4,
|
||||
MF_WEAPON_PLACEHOLDER = 8
|
||||
};
|
||||
|
||||
// a single triangle
|
||||
struct Triangle {
|
||||
uint16_t mVertex[3]; // Vertex indices
|
||||
char mType; // James' Mesh Type
|
||||
char mColor; // Color for flat and Gourand Shaded
|
||||
unsigned char mTex[3][2]; // Texture UV coordinates
|
||||
unsigned char mTextureNum; // Source texture offset
|
||||
char mFlags; // Unreal Mesh Flags (unused)
|
||||
|
||||
unsigned int matIndex;
|
||||
};
|
||||
|
||||
// temporary representation for a material
|
||||
struct TempMat {
|
||||
TempMat()
|
||||
: type()
|
||||
, tex()
|
||||
, numFaces (0)
|
||||
{}
|
||||
|
||||
explicit TempMat(const Triangle& in)
|
||||
: type ((Unreal::MeshFlags)in.mType)
|
||||
, tex (in.mTextureNum)
|
||||
, numFaces (0)
|
||||
{}
|
||||
|
||||
// type of mesh
|
||||
Unreal::MeshFlags type;
|
||||
|
||||
// index of texture
|
||||
unsigned int tex;
|
||||
|
||||
// number of faces using us
|
||||
unsigned int numFaces;
|
||||
|
||||
// for std::find
|
||||
bool operator == (const TempMat& o ) {
|
||||
return (tex == o.tex && type == o.type);
|
||||
}
|
||||
};
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
int32_t X : 11;
|
||||
int32_t Y : 11;
|
||||
int32_t Z : 10;
|
||||
};
|
||||
|
||||
// UNREAL vertex compression
|
||||
inline void CompressVertex(const aiVector3D& v, uint32_t& out)
|
||||
{
|
||||
union {
|
||||
Vertex n;
|
||||
int32_t t;
|
||||
};
|
||||
n.X = (int32_t)v.x;
|
||||
n.Y = (int32_t)v.y;
|
||||
n.Z = (int32_t)v.z;
|
||||
::memcpy( &out, &t, sizeof(int32_t));
|
||||
//out = t;
|
||||
}
|
||||
|
||||
// UNREAL vertex decompression
|
||||
inline void DecompressVertex(aiVector3D& v, int32_t in)
|
||||
{
|
||||
union {
|
||||
Vertex n;
|
||||
int32_t i;
|
||||
};
|
||||
i = in;
|
||||
|
||||
v.x = (float)n.X;
|
||||
v.y = (float)n.Y;
|
||||
v.z = (float)n.Z;
|
||||
}
|
||||
|
||||
} // end namespace Unreal
|
||||
namespace Assimp {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Importer class to load UNREAL files (*.3d)
|
||||
*/
|
||||
class UnrealImporter : public BaseImporter
|
||||
{
|
||||
class UnrealImporter : public BaseImporter {
|
||||
public:
|
||||
UnrealImporter();
|
||||
~UnrealImporter();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Returns whether we can handle the format of the given file
|
||||
*
|
||||
* See BaseImporter::CanRead() for details.
|
||||
**/
|
||||
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
|
||||
bool checkSig) const;
|
||||
bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
|
||||
bool checkSig) const;
|
||||
|
||||
protected:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Called by Importer::GetExtensionList()
|
||||
*
|
||||
* See #BaseImporter::GetInfo for the details
|
||||
*/
|
||||
const aiImporterDesc* GetInfo () const;
|
||||
|
||||
const aiImporterDesc *GetInfo() const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Setup properties for the importer
|
||||
*
|
||||
* See BaseImporter::SetupProperties() for details
|
||||
*/
|
||||
void SetupProperties(const Importer* pImp);
|
||||
|
||||
void SetupProperties(const Importer *pImp);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Imports the given file into the given scene structure.
|
||||
*
|
||||
* See BaseImporter::InternReadFile() for details
|
||||
*/
|
||||
void InternReadFile( const std::string& pFile, aiScene* pScene,
|
||||
IOSystem* pIOHandler);
|
||||
void InternReadFile(const std::string &pFile, aiScene *pScene,
|
||||
IOSystem *pIOHandler);
|
||||
|
||||
private:
|
||||
|
||||
//! frame to be loaded
|
||||
uint32_t configFrameID;
|
||||
uint32_t mConfigFrameID;
|
||||
|
||||
//! process surface flags
|
||||
bool configHandleFlags;
|
||||
bool mConfigHandleFlags;
|
||||
|
||||
}; // !class UnrealImporter
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // AI_UNREALIMPORTER_H_INC
|
||||
|
||||
@@ -176,7 +176,7 @@ void XGLImporter::InternReadFile( const std::string& pFile,
|
||||
raw_reader->IncPtr(2);
|
||||
|
||||
zstream.next_in = reinterpret_cast<Bytef*>( raw_reader->GetPtr() );
|
||||
zstream.avail_in = raw_reader->GetRemainingSize();
|
||||
zstream.avail_in = (uInt) raw_reader->GetRemainingSize();
|
||||
|
||||
size_t total = 0l;
|
||||
|
||||
|
||||
+10
-2
@@ -58,6 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -81,14 +82,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
|
||||
#else
|
||||
#define gltf_unordered_map map
|
||||
#define gltf_unordered_set set
|
||||
#endif
|
||||
|
||||
#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#if _MSC_VER > 1600
|
||||
#define gltf_unordered_map unordered_map
|
||||
#define gltf_unordered_set unordered_set
|
||||
#else
|
||||
#define gltf_unordered_map tr1::unordered_map
|
||||
#define gltf_unordered_set tr1::unordered_set
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -375,8 +380,8 @@ struct Accessor : public Object {
|
||||
|
||||
inline uint8_t *GetPointer();
|
||||
|
||||
template <class T>
|
||||
bool ExtractData(T *&outData);
|
||||
template<class T>
|
||||
void ExtractData(T *&outData);
|
||||
|
||||
void WriteData(size_t count, const void *src_buffer, size_t src_stride);
|
||||
|
||||
@@ -720,6 +725,7 @@ struct Mesh : public Object {
|
||||
std::vector<Primitive> primitives;
|
||||
|
||||
std::vector<float> weights;
|
||||
std::vector<std::string> targetNames;
|
||||
|
||||
Mesh() {}
|
||||
|
||||
@@ -874,6 +880,8 @@ class LazyDict : public LazyDictBase {
|
||||
Value *mDict; //! JSON dictionary object
|
||||
Asset &mAsset; //! The asset instance
|
||||
|
||||
std::gltf_unordered_set<unsigned int> mRecursiveReferenceCheck; //! Used by Retrieve to prevent recursive lookups
|
||||
|
||||
void AttachToDocument(Document &doc);
|
||||
void DetachFromDocument();
|
||||
|
||||
|
||||
+38
-12
@@ -280,6 +280,11 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
|
||||
throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object");
|
||||
}
|
||||
|
||||
if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
|
||||
throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" has recursive reference to itself");
|
||||
}
|
||||
mRecursiveReferenceCheck.insert(i);
|
||||
|
||||
// Unique ptr prevents memory leak in case of Read throws an exception
|
||||
auto inst = std::unique_ptr<T>(new T());
|
||||
inst->id = std::string(mDictId) + "_" + to_string(i);
|
||||
@@ -287,7 +292,9 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
|
||||
ReadMember(obj, "name", inst->name);
|
||||
inst->Read(obj, mAsset);
|
||||
|
||||
return Add(inst.release());
|
||||
Ref<T> result = Add(inst.release());
|
||||
mRecursiveReferenceCheck.erase(i);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -508,18 +515,23 @@ inline size_t Buffer::AppendData(uint8_t *data, size_t length) {
|
||||
}
|
||||
|
||||
inline void Buffer::Grow(size_t amount) {
|
||||
if (amount <= 0) return;
|
||||
if (amount <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Capacity is big enough
|
||||
if (capacity >= byteLength + amount) {
|
||||
byteLength += amount;
|
||||
return;
|
||||
}
|
||||
|
||||
// Shift operation is standard way to divide integer by 2, it doesn't cast it to float back and forth, also works for odd numbers,
|
||||
// originally it would look like: static_cast<size_t>(capacity * 1.5f)
|
||||
capacity = std::max(capacity + (capacity >> 1), byteLength + amount);
|
||||
// Just allocate data which we need
|
||||
capacity = byteLength + amount;
|
||||
|
||||
uint8_t *b = new uint8_t[capacity];
|
||||
if (mData) memcpy(b, mData.get(), byteLength);
|
||||
if (nullptr != mData) {
|
||||
memcpy(b, mData.get(), byteLength);
|
||||
}
|
||||
mData.reset(b, std::default_delete<uint8_t[]>());
|
||||
byteLength += amount;
|
||||
}
|
||||
@@ -608,10 +620,13 @@ inline void CopyData(size_t count,
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <class T>
|
||||
bool Accessor::ExtractData(T *&outData) {
|
||||
uint8_t *data = GetPointer();
|
||||
if (!data) return false;
|
||||
template<class T>
|
||||
void Accessor::ExtractData(T *&outData)
|
||||
{
|
||||
uint8_t* data = GetPointer();
|
||||
if (!data) {
|
||||
throw DeadlyImportError("GLTF: data is NULL");
|
||||
}
|
||||
|
||||
const size_t elemSize = GetElementSize();
|
||||
const size_t totalSize = elemSize * count;
|
||||
@@ -631,8 +646,6 @@ bool Accessor::ExtractData(T *&outData) {
|
||||
memcpy(outData + i, data + i * stride, elemSize);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t src_stride) {
|
||||
@@ -1021,6 +1034,19 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Value *extras = FindObject(pJSON_Object, "extras");
|
||||
if (nullptr != extras ) {
|
||||
if (Value* curTargetNames = FindArray(*extras, "targetNames")) {
|
||||
this->targetNames.resize(curTargetNames->Size());
|
||||
for (unsigned int i = 0; i < curTargetNames->Size(); ++i) {
|
||||
Value& targetNameValue = (*curTargetNames)[i];
|
||||
if (targetNameValue.IsString()) {
|
||||
this->targetNames[i] = targetNameValue.GetString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void Camera::Read(Value &obj, Asset & /*r*/) {
|
||||
|
||||
@@ -472,6 +472,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||
if (mesh.weights.size() > i) {
|
||||
aiAnimMesh.mWeight = mesh.weights[i];
|
||||
}
|
||||
if (mesh.targetNames.size() > i) {
|
||||
aiAnimMesh.mName = mesh.targetNames[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -680,6 +683,7 @@ void glTF2Importer::ImportCameras(glTF2::Asset &r) {
|
||||
aicam->mClipPlaneFar = cam.cameraProperties.ortographic.zfar;
|
||||
aicam->mClipPlaneNear = cam.cameraProperties.ortographic.znear;
|
||||
aicam->mHorizontalFOV = 0.0;
|
||||
aicam->mOrthographicWidth = cam.cameraProperties.ortographic.xmag;
|
||||
aicam->mAspect = 1.0f;
|
||||
if (0.f != cam.cameraProperties.ortographic.ymag) {
|
||||
aicam->mAspect = cam.cameraProperties.ortographic.xmag / cam.cameraProperties.ortographic.ymag;
|
||||
|
||||
Reference in New Issue
Block a user