Merge branch 'master' into added_check_before_using

This commit is contained in:
Rafał Mikrut
2020-04-28 18:33:29 +00:00
committed by GitHub
117 changed files with 4331 additions and 3667 deletions
-3
View File
@@ -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
View File
@@ -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
View File
@@ -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();
}
+1 -5
View File
@@ -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
View File
@@ -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 << ">";
+2 -2
View File
@@ -142,11 +142,11 @@ void Parser::LogWarning(const char* szWarn)
{
ai_assert(NULL != szWarn);
char szTemp[1024];
char szTemp[2048];
#if _MSC_VER >= 1400
sprintf_s(szTemp, "Line %u: %s",iLineNumber,szWarn);
#else
ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn);
ai_snprintf(szTemp,sizeof(szTemp),"Line %u: %s",iLineNumber,szWarn);
#endif
// output the warning to the logger ...
+4
View File
@@ -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)
+1 -1
View File
@@ -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*/)
{
+1 -1
View File
@@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Conversion of Blender's new BMesh stuff
*/
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
#include "BlenderDNA.h"
@@ -181,6 +180,7 @@ void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
face.v2 = v2;
face.v3 = v3;
face.v4 = v4;
face.flag = 0;
// TODO - Work out how materials work
face.mat_nr = 0;
triMesh->mface.push_back( face );
+1 -1
View File
@@ -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;
+3 -3
View File
@@ -73,11 +73,11 @@ ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index)
aiExportFormatDesc *desc = new aiExportFormatDesc;
desc->description = new char[ strlen( orig->description ) + 1 ]();
::strncpy( (char*) desc->description, orig->description, strlen( orig->description ) );
::memcpy( (char*) desc->description, orig->description, strlen( orig->description ) );
desc->fileExtension = new char[ strlen( orig->fileExtension ) + 1 ]();
::strncpy( ( char* ) desc->fileExtension, orig->fileExtension, strlen( orig->fileExtension ) );
::memcpy( ( char* ) desc->fileExtension, orig->fileExtension, strlen( orig->fileExtension ) );
desc->id = new char[ strlen( orig->id ) + 1 ]();
::strncpy( ( char* ) desc->id, orig->id, strlen( orig->id ) );
::memcpy( ( char* ) desc->id, orig->id, strlen( orig->id ) );
return desc;
}
+8
View File
@@ -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
@@ -1133,6 +1134,13 @@ ENDIF ()
ADD_LIBRARY( assimp ${assimp_src} )
ADD_LIBRARY(assimp::assimp ALIAS assimp)
# enable warnings as errors ########################################
IF (MSVC)
TARGET_COMPILE_OPTIONS(assimp PRIVATE /WX)
ELSE()
TARGET_COMPILE_OPTIONS(assimp PRIVATE -Werror)
ENDIF()
TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/../include>
+1 -1
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+32 -3
View File
@@ -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
+12 -13
View File
@@ -979,7 +979,7 @@ void GetArrayCopy(Type*& dest, ai_uint num ) {
dest = new Type[num];
::memcpy(dest, old, sizeof(Type) * num);
}
}
// ------------------------------------------------------------------------------------------------
void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) {
@@ -994,8 +994,7 @@ void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) {
} else {
*_dest = new aiScene();
}
::memcpy(*_dest,src,sizeof(aiScene));
CopyScene(_dest, src, false);
}
// ------------------------------------------------------------------------------------------------
@@ -1066,7 +1065,7 @@ void SceneCombiner::Copy( aiMesh** _dest, const aiMesh* src ) {
aiMesh* dest = *_dest = new aiMesh();
// get a flat copy
::memcpy(dest,src,sizeof(aiMesh));
*dest = *src;
// and reallocate all arrays
GetArrayCopy( dest->mVertices, dest->mNumVertices );
@@ -1105,7 +1104,7 @@ void SceneCombiner::Copy(aiAnimMesh** _dest, const aiAnimMesh* src) {
aiAnimMesh* dest = *_dest = new aiAnimMesh();
// get a flat copy
::memcpy(dest, src, sizeof(aiAnimMesh));
*dest = *src;
// and reallocate all arrays
GetArrayCopy(dest->mVertices, dest->mNumVertices);
@@ -1162,7 +1161,7 @@ void SceneCombiner::Copy(aiTexture** _dest, const aiTexture* src) {
aiTexture* dest = *_dest = new aiTexture();
// get a flat copy
::memcpy(dest,src,sizeof(aiTexture));
*dest = *src;
// and reallocate all arrays. We must do it manually here
const char* old = (const char*)dest->pcData;
@@ -1192,7 +1191,7 @@ void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) {
aiAnimation* dest = *_dest = new aiAnimation();
// get a flat copy
::memcpy(dest,src,sizeof(aiAnimation));
*dest = *src;
// and reallocate all arrays
CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels );
@@ -1208,7 +1207,7 @@ void SceneCombiner::Copy(aiNodeAnim** _dest, const aiNodeAnim* src) {
aiNodeAnim* dest = *_dest = new aiNodeAnim();
// get a flat copy
::memcpy(dest,src,sizeof(aiNodeAnim));
*dest = *src;
// and reallocate all arrays
GetArrayCopy( dest->mPositionKeys, dest->mNumPositionKeys );
@@ -1224,7 +1223,7 @@ void SceneCombiner::Copy(aiMeshMorphAnim** _dest, const aiMeshMorphAnim* src) {
aiMeshMorphAnim* dest = *_dest = new aiMeshMorphAnim();
// get a flat copy
::memcpy(dest,src,sizeof(aiMeshMorphAnim));
*dest = *src;
// and reallocate all arrays
GetArrayCopy( dest->mKeys, dest->mNumKeys );
@@ -1245,7 +1244,7 @@ void SceneCombiner::Copy( aiCamera** _dest,const aiCamera* src) {
aiCamera* dest = *_dest = new aiCamera();
// get a flat copy, that's already OK
::memcpy(dest,src,sizeof(aiCamera));
*dest = *src;
}
// ------------------------------------------------------------------------------------------------
@@ -1257,7 +1256,7 @@ void SceneCombiner::Copy(aiLight** _dest, const aiLight* src) {
aiLight* dest = *_dest = new aiLight();
// get a flat copy, that's already OK
::memcpy(dest,src,sizeof(aiLight));
*dest = *src;
}
// ------------------------------------------------------------------------------------------------
@@ -1269,7 +1268,7 @@ void SceneCombiner::Copy(aiBone** _dest, const aiBone* src) {
aiBone* dest = *_dest = new aiBone();
// get a flat copy
::memcpy(dest,src,sizeof(aiBone));
*dest = *src;
// and reallocate all arrays
GetArrayCopy( dest->mWeights, dest->mNumWeights );
@@ -1283,7 +1282,7 @@ void SceneCombiner::Copy (aiNode** _dest, const aiNode* src)
aiNode* dest = *_dest = new aiNode();
// get a flat copy
::memcpy(dest,src,sizeof(aiNode));
*dest = *src;
if (src->mMetaData) {
Copy(&dest->mMetaData, src->mMetaData);
+111 -128
View File
@@ -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,
@@ -50,71 +48,60 @@ using namespace Assimp;
// CHAR_BIT seems to be defined under MVSC, but not under GCC. Pray that the correct value is 8.
#ifndef CHAR_BIT
# define CHAR_BIT 8
#define CHAR_BIT 8
#endif
#ifdef _WIN32
# pragma warning(disable : 4127)
#endif // _WIN32
const aiVector3D PlaneInit(0.8523f, 0.34321f, 0.5736f);
// ------------------------------------------------------------------------------------------------
// Constructs a spatially sorted representation from the given position array.
SpatialSort::SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions,
unsigned int pElementOffset)
// define the reference plane. We choose some arbitrary vector away from all basic axises
// in the hope that no model spreads all its vertices along this plane.
: mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
{
// define the reference plane. We choose some arbitrary vector away from all basic axises
// in the hope that no model spreads all its vertices along this plane.
SpatialSort::SpatialSort(const aiVector3D *pPositions, unsigned int pNumPositions, unsigned int pElementOffset) :
mPlaneNormal(PlaneInit) {
mPlaneNormal.Normalize();
Fill(pPositions,pNumPositions,pElementOffset);
Fill(pPositions, pNumPositions, pElementOffset);
}
// ------------------------------------------------------------------------------------------------
SpatialSort :: SpatialSort()
: mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
{
SpatialSort::SpatialSort() :
mPlaneNormal(PlaneInit) {
mPlaneNormal.Normalize();
}
// ------------------------------------------------------------------------------------------------
// Destructor
SpatialSort::~SpatialSort()
{
// nothing to do here, everything destructs automatically
SpatialSort::~SpatialSort() {
// empty
}
// ------------------------------------------------------------------------------------------------
void SpatialSort::Fill( const aiVector3D* pPositions, unsigned int pNumPositions,
unsigned int pElementOffset,
bool pFinalize /*= true */)
{
void SpatialSort::Fill(const aiVector3D *pPositions, unsigned int pNumPositions,
unsigned int pElementOffset,
bool pFinalize /*= true */) {
mPositions.clear();
Append(pPositions,pNumPositions,pElementOffset,pFinalize);
Append(pPositions, pNumPositions, pElementOffset, pFinalize);
}
// ------------------------------------------------------------------------------------------------
void SpatialSort :: Finalize()
{
std::sort( mPositions.begin(), mPositions.end());
void SpatialSort::Finalize() {
std::sort(mPositions.begin(), mPositions.end());
}
// ------------------------------------------------------------------------------------------------
void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositions,
unsigned int pElementOffset,
bool pFinalize /*= true */)
{
void SpatialSort::Append(const aiVector3D *pPositions, unsigned int pNumPositions,
unsigned int pElementOffset,
bool pFinalize /*= true */) {
// store references to all given positions along with their distance to the reference plane
const size_t initial = mPositions.size();
mPositions.reserve(initial + (pFinalize?pNumPositions:pNumPositions*2));
for( unsigned int a = 0; a < pNumPositions; a++)
{
const char* tempPointer = reinterpret_cast<const char*> (pPositions);
const aiVector3D* vec = reinterpret_cast<const aiVector3D*> (tempPointer + a * pElementOffset);
mPositions.reserve(initial + (pFinalize ? pNumPositions : pNumPositions * 2));
for (unsigned int a = 0; a < pNumPositions; a++) {
const char *tempPointer = reinterpret_cast<const char *>(pPositions);
const aiVector3D *vec = reinterpret_cast<const aiVector3D *>(tempPointer + a * pElementOffset);
// store position by index and distance
ai_real distance = *vec * mPlaneNormal;
mPositions.push_back( Entry( static_cast<unsigned int>(a+initial), *vec, distance));
mPositions.push_back(Entry(static_cast<unsigned int>(a + initial), *vec, distance));
}
if (pFinalize) {
@@ -125,9 +112,8 @@ void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositio
// ------------------------------------------------------------------------------------------------
// Returns an iterator for all positions close to the given position.
void SpatialSort::FindPositions( const aiVector3D& pPosition,
ai_real pRadius, std::vector<unsigned int>& poResults) const
{
void SpatialSort::FindPositions(const aiVector3D &pPosition,
ai_real pRadius, std::vector<unsigned int> &poResults) const {
const ai_real dist = pPosition * mPlaneNormal;
const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
@@ -135,19 +121,18 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
poResults.clear();
// quick check for positions outside the range
if( mPositions.size() == 0)
if (mPositions.size() == 0)
return;
if( maxDist < mPositions.front().mDistance)
if (maxDist < mPositions.front().mDistance)
return;
if( minDist > mPositions.back().mDistance)
if (minDist > mPositions.back().mDistance)
return;
// do a binary search for the minimal distance to start the iteration there
unsigned int index = (unsigned int)mPositions.size() / 2;
unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
while( binaryStepSize > 1)
{
if( mPositions[index].mDistance < minDist)
while (binaryStepSize > 1) {
if (mPositions[index].mDistance < minDist)
index += binaryStepSize;
else
index -= binaryStepSize;
@@ -157,21 +142,20 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
// depending on the direction of the last step we need to single step a bit back or forth
// to find the actual beginning element of the range
while( index > 0 && mPositions[index].mDistance > minDist)
while (index > 0 && mPositions[index].mDistance > minDist)
index--;
while( index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
while (index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
index++;
// Mow start iterating from there until the first position lays outside of the distance range.
// Add all positions inside the distance range within the given radius to the result aray
std::vector<Entry>::const_iterator it = mPositions.begin() + index;
const ai_real pSquared = pRadius*pRadius;
while( it->mDistance < maxDist)
{
if( (it->mPosition - pPosition).SquareLength() < pSquared)
poResults.push_back( it->mIndex);
const ai_real pSquared = pRadius * pRadius;
while (it->mDistance < maxDist) {
if ((it->mPosition - pPosition).SquareLength() < pSquared)
poResults.push_back(it->mIndex);
++it;
if( it == mPositions.end())
if (it == mPositions.end())
break;
}
@@ -180,70 +164,74 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
namespace {
// Binary, signed-integer representation of a single-precision floating-point value.
// IEEE 754 says: "If two floating-point numbers in the same format are ordered then they are
// ordered the same way when their bits are reinterpreted as sign-magnitude integers."
// This allows us to convert all floating-point numbers to signed integers of arbitrary size
// and then use them to work with ULPs (Units in the Last Place, for high-precision
// computations) or to compare them (integer comparisons are faster than floating-point
// comparisons on many platforms).
typedef ai_int BinFloat;
// Binary, signed-integer representation of a single-precision floating-point value.
// IEEE 754 says: "If two floating-point numbers in the same format are ordered then they are
// ordered the same way when their bits are reinterpreted as sign-magnitude integers."
// This allows us to convert all floating-point numbers to signed integers of arbitrary size
// and then use them to work with ULPs (Units in the Last Place, for high-precision
// computations) or to compare them (integer comparisons are faster than floating-point
// comparisons on many platforms).
typedef ai_int BinFloat;
// --------------------------------------------------------------------------------------------
// Converts the bit pattern of a floating-point number to its signed integer representation.
BinFloat ToBinary( const ai_real & pValue) {
// --------------------------------------------------------------------------------------------
// Converts the bit pattern of a floating-point number to its signed integer representation.
BinFloat ToBinary(const ai_real &pValue) {
// If this assertion fails, signed int is not big enough to store a float on your platform.
// Please correct the declaration of BinFloat a few lines above - but do it in a portable,
// #ifdef'd manner!
static_assert( sizeof(BinFloat) >= sizeof(ai_real), "sizeof(BinFloat) >= sizeof(ai_real)");
// If this assertion fails, signed int is not big enough to store a float on your platform.
// Please correct the declaration of BinFloat a few lines above - but do it in a portable,
// #ifdef'd manner!
static_assert(sizeof(BinFloat) >= sizeof(ai_real), "sizeof(BinFloat) >= sizeof(ai_real)");
#if defined( _MSC_VER)
// If this assertion fails, Visual C++ has finally moved to ILP64. This means that this
// code has just become legacy code! Find out the current value of _MSC_VER and modify
// the #if above so it evaluates false on the current and all upcoming VC versions (or
// on the current platform, if LP64 or LLP64 are still used on other platforms).
static_assert( sizeof(BinFloat) == sizeof(ai_real), "sizeof(BinFloat) == sizeof(ai_real)");
#if defined(_MSC_VER)
// If this assertion fails, Visual C++ has finally moved to ILP64. This means that this
// code has just become legacy code! Find out the current value of _MSC_VER and modify
// the #if above so it evaluates false on the current and all upcoming VC versions (or
// on the current platform, if LP64 or LLP64 are still used on other platforms).
static_assert(sizeof(BinFloat) == sizeof(ai_real), "sizeof(BinFloat) == sizeof(ai_real)");
// This works best on Visual C++, but other compilers have their problems with it.
const BinFloat binValue = reinterpret_cast<BinFloat const &>(pValue);
#else
// On many compilers, reinterpreting a float address as an integer causes aliasing
// problems. This is an ugly but more or less safe way of doing it.
union {
ai_real asFloat;
BinFloat asBin;
} conversion;
conversion.asBin = 0; // zero empty space in case sizeof(BinFloat) > sizeof(float)
conversion.asFloat = pValue;
const BinFloat binValue = conversion.asBin;
#endif
// This works best on Visual C++, but other compilers have their problems with it.
const BinFloat binValue = reinterpret_cast<BinFloat const &>(pValue);
//::memcpy(&binValue, &pValue, sizeof(pValue));
//return binValue;
#else
// On many compilers, reinterpreting a float address as an integer causes aliasing
// problems. This is an ugly but more or less safe way of doing it.
union {
ai_real asFloat;
BinFloat asBin;
} conversion;
conversion.asBin = 0; // zero empty space in case sizeof(BinFloat) > sizeof(float)
conversion.asFloat = pValue;
const BinFloat binValue = conversion.asBin;
#endif
// floating-point numbers are of sign-magnitude format, so find out what signed number
// representation we must convert negative values to.
// See http://en.wikipedia.org/wiki/Signed_number_representations.
// floating-point numbers are of sign-magnitude format, so find out what signed number
// representation we must convert negative values to.
// See http://en.wikipedia.org/wiki/Signed_number_representations.
// Two's complement?
if( (-42 == (~42 + 1)) && (binValue & 0x80000000))
return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue;
// One's complement?
else if ( (-42 == ~42) && (binValue & 0x80000000))
return BinFloat(-0) - binValue;
// Sign-magnitude?
else if( (-42 == (42 | (-0))) && (binValue & 0x80000000)) // -0 = 1000... binary
return binValue;
else
return binValue;
}
// Two's complement?
bool DefaultValue = ((-42 == (~42 + 1)) && (binValue & 0x80000000));
bool OneComplement = ((-42 == ~42) && (binValue & 0x80000000));
bool SignedMagnitude = ((-42 == (42 | (-0))) && (binValue & 0x80000000));
if (DefaultValue)
return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue;
// One's complement?
else if (OneComplement)
return BinFloat(-0) - binValue;
// Sign-magnitude?
else if (SignedMagnitude) // -0 = 1000... binary
return binValue;
else
return binValue;
}
} // namespace
// ------------------------------------------------------------------------------------------------
// Fills an array with indices of all positions identical to the given position. In opposite to
// FindPositions(), not an epsilon is used but a (very low) tolerance of four floating-point units.
void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
std::vector<unsigned int>& poResults) const
{
void SpatialSort::FindIdenticalPositions(const aiVector3D &pPosition, std::vector<unsigned int> &poResults) const {
// Epsilons have a huge disadvantage: they are of constant precision, while floating-point
// values are of log2 precision. If you apply e=0.01 to 100, the epsilon is rather small, but
// if you apply it to 0.001, it is enormous.
@@ -269,20 +257,19 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
// Convert the plane distance to its signed integer representation so the ULPs tolerance can be
// applied. For some reason, VC won't optimize two calls of the bit pattern conversion.
const BinFloat minDistBinary = ToBinary( pPosition * mPlaneNormal) - distanceToleranceInULPs;
const BinFloat minDistBinary = ToBinary(pPosition * mPlaneNormal) - distanceToleranceInULPs;
const BinFloat maxDistBinary = minDistBinary + 2 * distanceToleranceInULPs;
// clear the array in this strange fashion because a simple clear() would also deallocate
// the array which we want to avoid
poResults.resize( 0 );
poResults.resize(0);
// do a binary search for the minimal distance to start the iteration there
unsigned int index = (unsigned int)mPositions.size() / 2;
unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
while( binaryStepSize > 1)
{
while (binaryStepSize > 1) {
// Ugly, but conditional jumps are faster with integers than with floats
if( minDistBinary > ToBinary(mPositions[index].mDistance))
if (minDistBinary > ToBinary(mPositions[index].mDistance))
index += binaryStepSize;
else
index -= binaryStepSize;
@@ -292,20 +279,19 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
// depending on the direction of the last step we need to single step a bit back or forth
// to find the actual beginning element of the range
while( index > 0 && minDistBinary < ToBinary(mPositions[index].mDistance) )
while (index > 0 && minDistBinary < ToBinary(mPositions[index].mDistance))
index--;
while( index < (mPositions.size() - 1) && minDistBinary > ToBinary(mPositions[index].mDistance))
while (index < (mPositions.size() - 1) && minDistBinary > ToBinary(mPositions[index].mDistance))
index++;
// Now start iterating from there until the first position lays outside of the distance range.
// Add all positions inside the distance range within the tolerance to the result array
std::vector<Entry>::const_iterator it = mPositions.begin() + index;
while( ToBinary(it->mDistance) < maxDistBinary)
{
if( distance3DToleranceInULPs >= ToBinary((it->mPosition - pPosition).SquareLength()))
while (ToBinary(it->mDistance) < maxDistBinary) {
if (distance3DToleranceInULPs >= ToBinary((it->mPosition - pPosition).SquareLength()))
poResults.push_back(it->mIndex);
++it;
if( it == mPositions.end())
if (it == mPositions.end())
break;
}
@@ -313,22 +299,19 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
}
// ------------------------------------------------------------------------------------------------
unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill, ai_real pRadius) const
{
fill.resize(mPositions.size(),UINT_MAX);
unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int> &fill, ai_real pRadius) const {
fill.resize(mPositions.size(), UINT_MAX);
ai_real dist, maxDist;
unsigned int t=0;
const ai_real pSquared = pRadius*pRadius;
unsigned int t = 0;
const ai_real pSquared = pRadius * pRadius;
for (size_t i = 0; i < mPositions.size();) {
dist = mPositions[i].mPosition * mPlaneNormal;
maxDist = dist + pRadius;
fill[mPositions[i].mIndex] = t;
const aiVector3D& oldpos = mPositions[i].mPosition;
for (++i; i < fill.size() && mPositions[i].mDistance < maxDist
&& (mPositions[i].mPosition - oldpos).SquareLength() < pSquared; ++i)
{
const aiVector3D &oldpos = mPositions[i].mPosition;
for (++i; i < fill.size() && mPositions[i].mDistance < maxDist && (mPositions[i].mPosition - oldpos).SquareLength() < pSquared; ++i) {
fill[mPositions[i].mIndex] = t;
}
++t;
@@ -338,7 +321,7 @@ unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill,
// debug invariant: mPositions[i].mIndex values must range from 0 to mPositions.size()-1
for (size_t i = 0; i < fill.size(); ++i) {
ai_assert(fill[i]<mPositions.size());
ai_assert(fill[i] < mPositions.size());
}
#endif
+100 -171
View File
@@ -655,7 +655,8 @@ bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
const TransformationComp comp = static_cast<TransformationComp>(i);
if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation) {
if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation ||
comp == TransformationComp_PreRotation || comp == TransformationComp_PostRotation) {
continue;
}
@@ -2739,15 +2740,12 @@ void FBXConverter::GenerateNodeAnimations(std::vector<aiNodeAnim *> &node_anims,
// be invoked _later_ (animations come first). If this node has only rotation,
// scaling and translation _and_ there are no animated other components either,
// we can use a single node and also a single node animation channel.
if (!has_complex && !NeedsComplexTransformationChain(target)) {
aiNodeAnim *const nd = GenerateSimpleNodeAnim(fixed_name, target, chain,
if( !has_complex && !NeedsComplexTransformationChain(target)) {
aiNodeAnim* const nd = GenerateSimpleNodeAnim(fixed_name, target, chain,
node_property_map.end(),
layer_map,
start, stop,
max_time,
min_time,
true // input is TRS order, assimp is SRT
min_time
);
ai_assert(nd);
@@ -3021,133 +3019,121 @@ aiNodeAnim *FBXConverter::GenerateTranslationNodeAnim(const std::string &name,
return na.release();
}
aiNodeAnim *FBXConverter::GenerateSimpleNodeAnim(const std::string &name,
const Model &target,
aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
const Model& target,
NodeMap::const_iterator chain[TransformationComp_MAXIMUM],
NodeMap::const_iterator iter_end,
const LayerMap &layer_map,
NodeMap::const_iterator iterEnd,
int64_t start, int64_t stop,
double &max_time,
double &min_time,
bool reverse_order)
double& maxTime,
double& minTime)
{
std::unique_ptr<aiNodeAnim> na(new aiNodeAnim());
na->mNodeName.Set(name);
const PropertyTable &props = target.Props();
// need to convert from TRS order to SRT?
if (reverse_order) {
// collect unique times and keyframe lists
KeyFrameListList keyframeLists[TransformationComp_MAXIMUM];
KeyTimeList keytimes;
aiVector3D def_scale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f));
aiVector3D def_translate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f));
aiVector3D def_rot = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f));
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
if (chain[i] == iterEnd)
continue;
KeyFrameListList scaling;
KeyFrameListList translation;
KeyFrameListList rotation;
keyframeLists[i] = GetKeyframeList((*chain[i]).second, start, stop);
if (chain[TransformationComp_Scaling] != iter_end) {
scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second, start, stop);
for (KeyFrameListList::const_iterator it = keyframeLists[i].begin(); it != keyframeLists[i].end(); ++it) {
const KeyTimeList& times = *std::get<0>(*it);
keytimes.insert(keytimes.end(), times.begin(), times.end());
}
if (chain[TransformationComp_Translation] != iter_end) {
translation = GetKeyframeList((*chain[TransformationComp_Translation]).second, start, stop);
}
// remove duplicates
std::sort(keytimes.begin(), keytimes.end());
if (chain[TransformationComp_Rotation] != iter_end) {
rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second, start, stop);
}
auto last = std::unique(keytimes.begin(), keytimes.end());
keytimes.erase(last, keytimes.end());
}
KeyFrameListList joined;
joined.insert(joined.end(), scaling.begin(), scaling.end());
joined.insert(joined.end(), translation.begin(), translation.end());
joined.insert(joined.end(), rotation.begin(), rotation.end());
const Model::RotOrder rotOrder = target.RotationOrder();
const size_t keyCount = keytimes.size();
const KeyTimeList &times = GetKeyTimeList(joined);
aiVector3D defTranslate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f));
aiVector3D defRotation = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f));
aiVector3D defScale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f));
aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder);
aiQuatKey *out_quat = new aiQuatKey[times.size()];
aiVectorKey *out_scale = new aiVectorKey[times.size()];
aiVectorKey *out_translation = new aiVectorKey[times.size()];
aiVectorKey* outTranslations = new aiVectorKey[keyCount];
aiQuatKey* outRotations = new aiQuatKey[keyCount];
aiVectorKey* outScales = new aiVectorKey[keyCount];
if (times.size()) {
ConvertTransformOrder_TRStoSRT(out_quat, out_scale, out_translation,
scaling,
translation,
rotation,
times,
max_time,
min_time,
target.RotationOrder(),
def_scale,
def_translate,
def_rot);
}
// XXX remove duplicates / redundant keys which this operation did
// likely produce if not all three channels were equally dense.
na->mNumScalingKeys = static_cast<unsigned int>(times.size());
na->mNumRotationKeys = na->mNumScalingKeys;
na->mNumPositionKeys = na->mNumScalingKeys;
na->mScalingKeys = out_scale;
na->mRotationKeys = out_quat;
na->mPositionKeys = out_translation;
if (keyframeLists[TransformationComp_Translation].size() > 0) {
InterpolateKeys(outTranslations, keytimes, keyframeLists[TransformationComp_Translation], defTranslate, maxTime, minTime);
} else {
// if a particular transformation is not given, grab it from
// the corresponding node to meet the semantics of aiNodeAnim,
// which requires all of rotation, scaling and translation
// to be set.
if (chain[TransformationComp_Scaling] != iter_end) {
ConvertScaleKeys(na.get(), (*chain[TransformationComp_Scaling]).second,
layer_map,
start, stop,
max_time,
min_time);
} else {
na->mScalingKeys = new aiVectorKey[1];
na->mNumScalingKeys = 1;
na->mScalingKeys[0].mTime = 0.;
na->mScalingKeys[0].mValue = PropertyGet(props, "Lcl Scaling",
aiVector3D(1.f, 1.f, 1.f));
}
if (chain[TransformationComp_Rotation] != iter_end) {
ConvertRotationKeys(na.get(), (*chain[TransformationComp_Rotation]).second,
layer_map,
start, stop,
max_time,
min_time,
target.RotationOrder());
} else {
na->mRotationKeys = new aiQuatKey[1];
na->mNumRotationKeys = 1;
na->mRotationKeys[0].mTime = 0.;
na->mRotationKeys[0].mValue = EulerToQuaternion(
PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f)),
target.RotationOrder());
}
if (chain[TransformationComp_Translation] != iter_end) {
ConvertTranslationKeys(na.get(), (*chain[TransformationComp_Translation]).second,
layer_map,
start, stop,
max_time,
min_time);
} else {
na->mPositionKeys = new aiVectorKey[1];
na->mNumPositionKeys = 1;
na->mPositionKeys[0].mTime = 0.;
na->mPositionKeys[0].mValue = PropertyGet(props, "Lcl Translation",
aiVector3D(0.f, 0.f, 0.f));
for (size_t i = 0; i < keyCount; ++i) {
outTranslations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
outTranslations[i].mValue = defTranslate;
}
}
if (keyframeLists[TransformationComp_Rotation].size() > 0) {
InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder);
} else {
for (size_t i = 0; i < keyCount; ++i) {
outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
outRotations[i].mValue = defQuat;
}
}
if (keyframeLists[TransformationComp_Scaling].size() > 0) {
InterpolateKeys(outScales, keytimes, keyframeLists[TransformationComp_Scaling], defScale, maxTime, minTime);
} else {
for (size_t i = 0; i < keyCount; ++i) {
outScales[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
outScales[i].mValue = defScale;
}
}
bool ok = false;
const float zero_epsilon = 1e-6f;
const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
if (ok && preRotation.SquareLength() > zero_epsilon) {
const aiQuaternion preQuat = EulerToQuaternion(preRotation, Model::RotOrder_EulerXYZ);
for (size_t i = 0; i < keyCount; ++i) {
outRotations[i].mValue = preQuat * outRotations[i].mValue;
}
}
const aiVector3D& postRotation = PropertyGet<aiVector3D>(props, "PostRotation", ok);
if (ok && postRotation.SquareLength() > zero_epsilon) {
const aiQuaternion postQuat = EulerToQuaternion(postRotation, Model::RotOrder_EulerXYZ);
for (size_t i = 0; i < keyCount; ++i) {
outRotations[i].mValue = outRotations[i].mValue * postQuat;
}
}
// convert TRS to SRT
for (size_t i = 0; i < keyCount; ++i) {
aiQuaternion& r = outRotations[i].mValue;
aiVector3D& s = outScales[i].mValue;
aiVector3D& t = outTranslations[i].mValue;
aiMatrix4x4 mat, temp;
aiMatrix4x4::Translation(t, mat);
mat *= aiMatrix4x4(r.GetMatrix());
mat *= aiMatrix4x4::Scaling(s, temp);
mat.Decompose(s, r, t);
}
na->mNumScalingKeys = static_cast<unsigned int>(keyCount);
na->mNumRotationKeys = na->mNumScalingKeys;
na->mNumPositionKeys = na->mNumScalingKeys;
na->mScalingKeys = outScales;
na->mRotationKeys = outRotations;
na->mPositionKeys = outTranslations;
return na.release();
}
@@ -3328,10 +3314,7 @@ void FBXConverter::InterpolateKeys(aiQuatKey *valOut, const KeyTimeList &keys, c
// take shortest path by checking the inner product
// http://www.3dkingdoms.com/weekly/weekly.php?a=36
if (quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0) {
quat.x = -quat.x;
quat.y = -quat.y;
quat.z = -quat.z;
quat.w = -quat.w;
quat.Conjugate();
}
lastq = quat;
@@ -3339,60 +3322,6 @@ void FBXConverter::InterpolateKeys(aiQuatKey *valOut, const KeyTimeList &keys, c
}
}
void FBXConverter::ConvertTransformOrder_TRStoSRT(aiQuatKey *out_quat, aiVectorKey *out_scale,
aiVectorKey *out_translation,
const KeyFrameListList &scaling,
const KeyFrameListList &translation,
const KeyFrameListList &rotation,
const KeyTimeList &times,
double &maxTime,
double &minTime,
Model::RotOrder order,
const aiVector3D &def_scale,
const aiVector3D &def_translate,
const aiVector3D &def_rotation) {
if (rotation.size()) {
InterpolateKeys(out_quat, times, rotation, def_rotation, maxTime, minTime, order);
} else {
for (size_t i = 0; i < times.size(); ++i) {
out_quat[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps;
out_quat[i].mValue = EulerToQuaternion(def_rotation, order);
}
}
if (scaling.size()) {
InterpolateKeys(out_scale, times, scaling, def_scale, maxTime, minTime);
} else {
for (size_t i = 0; i < times.size(); ++i) {
out_scale[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps;
out_scale[i].mValue = def_scale;
}
}
if (translation.size()) {
InterpolateKeys(out_translation, times, translation, def_translate, maxTime, minTime);
} else {
for (size_t i = 0; i < times.size(); ++i) {
out_translation[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps;
out_translation[i].mValue = def_translate;
}
}
const size_t count = times.size();
for (size_t i = 0; i < count; ++i) {
aiQuaternion &r = out_quat[i].mValue;
aiVector3D &s = out_scale[i].mValue;
aiVector3D &t = out_translation[i].mValue;
aiMatrix4x4 mat, temp;
aiMatrix4x4::Translation(t, mat);
mat *= aiMatrix4x4(r.GetMatrix());
mat *= aiMatrix4x4::Scaling(s, temp);
mat.Decompose(s, r, t);
}
}
aiQuaternion FBXConverter::EulerToQuaternion(const aiVector3D &rot, Model::RotOrder order) {
aiMatrix4x4 m;
GetRotationMatrix(order, rot, m);
+3 -19
View File
@@ -349,12 +349,10 @@ private:
aiNodeAnim* GenerateSimpleNodeAnim(const std::string& name,
const Model& target,
NodeMap::const_iterator chain[TransformationComp_MAXIMUM],
NodeMap::const_iterator iter_end,
const LayerMap& layer_map,
NodeMap::const_iterator iterEnd,
int64_t start, int64_t stop,
double& max_time,
double& min_time,
bool reverse_order = false);
double& maxTime,
double& minTime);
// key (time), value, mapto (component index)
typedef std::tuple<std::shared_ptr<KeyTimeList>, std::shared_ptr<KeyValueList>, unsigned int > KeyFrameList;
@@ -379,20 +377,6 @@ private:
double& minTime,
Model::RotOrder order);
// ------------------------------------------------------------------------------------------------
void ConvertTransformOrder_TRStoSRT(aiQuatKey* out_quat, aiVectorKey* out_scale,
aiVectorKey* out_translation,
const KeyFrameListList& scaling,
const KeyFrameListList& translation,
const KeyFrameListList& rotation,
const KeyTimeList& times,
double& maxTime,
double& minTime,
Model::RotOrder order,
const aiVector3D& def_scale,
const aiVector3D& def_translate,
const aiVector3D& def_rotation);
// ------------------------------------------------------------------------------------------------
// euler xyz -> quat
aiQuaternion EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order);
+18 -24
View File
@@ -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
-1
View File
@@ -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
View File
@@ -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
+1
View File
@@ -1483,6 +1483,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
*/
delete root;
delete reader;
}
#endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER
+41 -36
View File
@@ -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
View File
@@ -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
+23 -17
View File
@@ -1556,7 +1556,7 @@ static int _m3dstbi__create_png_image(_m3dstbi__png *a, unsigned char *image_dat
return 1;
}
static int _m3dstbi__compute_transparency(_m3dstbi__png *z, unsigned char tc[3], int out_n) {
static int _m3dstbi__compute_transparency(_m3dstbi__png *z, unsigned char* tc, int out_n) {
_m3dstbi__context *s = z->s;
_m3dstbi__uint32 i, pixel_count = s->img_x * s->img_y;
unsigned char *p = z->out;
@@ -1639,7 +1639,7 @@ static int _m3dstbi__expand_png_palette(_m3dstbi__png *a, unsigned char *palette
static int _m3dstbi__parse_png_file(_m3dstbi__png *z, int scan, int req_comp) {
unsigned char palette[1024], pal_img_n = 0;
unsigned char has_trans = 0, tc[3];
unsigned char has_trans = 0, tc[3] = {};
_m3dstbi__uint16 tc16[3];
_m3dstbi__uint32 ioff = 0, idata_limit = 0, i, pal_len = 0;
int first = 1, k, interlace = 0, color = 0;
@@ -4350,7 +4350,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
M3D_INDEX last, *vrtxidx = NULL, *mtrlidx = NULL, *tmapidx = NULL, *skinidx = NULL;
uint32_t idx, numcmap = 0, *cmap = NULL, numvrtx = 0, maxvrtx = 0, numtmap = 0, maxtmap = 0, numproc = 0;
uint32_t numskin = 0, maxskin = 0, numstr = 0, maxt = 0, maxbone = 0, numgrp = 0, maxgrp = 0, *grpidx = NULL;
uint8_t *opa;
uint8_t *opa = nullptr;
m3dcd_t *cd;
m3dc_t *cmd;
m3dstr_t *str = NULL;
@@ -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;
}
}
+1 -1
View File
@@ -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 );
+63 -72
View File
@@ -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);
}
}
+1 -1
View File
@@ -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 ) );
}
}
+1 -1
View File
@@ -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));
}
}
+66 -82
View File
@@ -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++;
}
}
}
+19 -25
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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;
+6 -1
View File
@@ -382,7 +382,12 @@ namespace glTF
{
friend struct Accessor;
Accessor& accessor;
// This field is reported as not used, making it protectd is the easiest way to work around it without going to the bottom of what the problem is:
// ../code/glTF2/glTF2Asset.h:392:19: error: private field 'accessor' is not used [-Werror,-Wunused-private-field]
protected:
Accessor &accessor;
private:
uint8_t* data;
size_t elemSize, stride;
+17 -3
View File
@@ -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);
@@ -384,12 +389,18 @@ struct Accessor : public Object {
class Indexer {
friend struct Accessor;
// This field is reported as not used, making it protectd is the easiest way to work around it without going to the bottom of what the problem is:
// ../code/glTF2/glTF2Asset.h:392:19: error: private field 'accessor' is not used [-Werror,-Wunused-private-field]
protected:
Accessor &accessor;
private:
uint8_t *data;
size_t elemSize, stride;
Indexer(Accessor &acc);
public:
//! Accesses the i-th value as defined by the accessor
template <class T>
@@ -720,6 +731,7 @@ struct Mesh : public Object {
std::vector<Primitive> primitives;
std::vector<float> weights;
std::vector<std::string> targetNames;
Mesh() {}
@@ -874,6 +886,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
View File
@@ -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*/) {
+4
View File
@@ -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;