Model loading and texturing
This commit is contained in:
206
thirdparty/assimp/code/Blender/BlenderBMesh.cpp
vendored
Normal file
206
thirdparty/assimp/code/Blender/BlenderBMesh.cpp
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2013, assimp team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderBMesh.cpp
|
||||
* @brief Conversion of Blender's new BMesh stuff
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
|
||||
#include "BlenderDNA.h"
|
||||
#include "BlenderScene.h"
|
||||
#include "BlenderBMesh.h"
|
||||
#include "BlenderTessellator.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
template< > const char* LogFunctions< BlenderBMeshConverter >::Prefix()
|
||||
{
|
||||
static auto prefix = "BLEND_BMESH: ";
|
||||
return prefix;
|
||||
}
|
||||
}
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Blender;
|
||||
using namespace Assimp::Formatter;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ):
|
||||
BMesh( mesh ),
|
||||
triMesh( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BlenderBMeshConverter::~BlenderBMeshConverter( )
|
||||
{
|
||||
DestroyTriMesh( );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool BlenderBMeshConverter::ContainsBMesh( ) const
|
||||
{
|
||||
// TODO - Should probably do some additional verification here
|
||||
return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const Mesh* BlenderBMeshConverter::TriangulateBMesh( )
|
||||
{
|
||||
AssertValidMesh( );
|
||||
AssertValidSizes( );
|
||||
PrepareTriMesh( );
|
||||
|
||||
for ( int i = 0; i < BMesh->totpoly; ++i )
|
||||
{
|
||||
const MPoly& poly = BMesh->mpoly[ i ];
|
||||
ConvertPolyToFaces( poly );
|
||||
}
|
||||
|
||||
return triMesh;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::AssertValidMesh( )
|
||||
{
|
||||
if ( !ContainsBMesh( ) )
|
||||
{
|
||||
ThrowException( "BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first" );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::AssertValidSizes( )
|
||||
{
|
||||
if ( BMesh->totpoly != static_cast<int>( BMesh->mpoly.size( ) ) )
|
||||
{
|
||||
ThrowException( "BMesh poly array has incorrect size" );
|
||||
}
|
||||
if ( BMesh->totloop != static_cast<int>( BMesh->mloop.size( ) ) )
|
||||
{
|
||||
ThrowException( "BMesh loop array has incorrect size" );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::PrepareTriMesh( )
|
||||
{
|
||||
if ( triMesh )
|
||||
{
|
||||
DestroyTriMesh( );
|
||||
}
|
||||
|
||||
triMesh = new Mesh( *BMesh );
|
||||
triMesh->totface = 0;
|
||||
triMesh->mface.clear( );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::DestroyTriMesh( )
|
||||
{
|
||||
delete triMesh;
|
||||
triMesh = NULL;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly )
|
||||
{
|
||||
const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ];
|
||||
|
||||
if ( poly.totloop == 3 || poly.totloop == 4 )
|
||||
{
|
||||
AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 );
|
||||
|
||||
// UVs are optional, so only convert when present.
|
||||
if ( BMesh->mloopuv.size() )
|
||||
{
|
||||
if ( (poly.loopstart + poly.totloop ) > static_cast<int>( BMesh->mloopuv.size() ) )
|
||||
{
|
||||
ThrowException( "BMesh uv loop array has incorrect size" );
|
||||
}
|
||||
const MLoopUV* loopUV = &BMesh->mloopuv[ poly.loopstart ];
|
||||
AddTFace( loopUV[ 0 ].uv, loopUV[ 1 ].uv, loopUV[ 2 ].uv, poly.totloop == 4 ? loopUV[ 3 ].uv : 0 );
|
||||
}
|
||||
}
|
||||
else if ( poly.totloop > 4 )
|
||||
{
|
||||
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
||||
BlenderTessellatorGL tessGL( *this );
|
||||
tessGL.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
|
||||
#elif ASSIMP_BLEND_WITH_POLY_2_TRI
|
||||
BlenderTessellatorP2T tessP2T( *this );
|
||||
tessP2T.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
|
||||
{
|
||||
MFace face;
|
||||
face.v1 = v1;
|
||||
face.v2 = v2;
|
||||
face.v3 = v3;
|
||||
face.v4 = v4;
|
||||
// TODO - Work out how materials work
|
||||
face.mat_nr = 0;
|
||||
triMesh->mface.push_back( face );
|
||||
triMesh->totface = static_cast<int>(triMesh->mface.size( ));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::AddTFace( const float* uv1, const float *uv2, const float *uv3, const float* uv4 )
|
||||
{
|
||||
MTFace mtface;
|
||||
memcpy( &mtface.uv[ 0 ], uv1, sizeof(float) * 2 );
|
||||
memcpy( &mtface.uv[ 1 ], uv2, sizeof(float) * 2 );
|
||||
memcpy( &mtface.uv[ 2 ], uv3, sizeof(float) * 2 );
|
||||
|
||||
if ( uv4 )
|
||||
{
|
||||
memcpy( &mtface.uv[ 3 ], uv4, sizeof(float) * 2 );
|
||||
}
|
||||
|
||||
triMesh->mtface.push_back( mtface );
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
94
thirdparty/assimp/code/Blender/BlenderBMesh.h
vendored
Normal file
94
thirdparty/assimp/code/Blender/BlenderBMesh.h
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2013, assimp team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderBMesh.h
|
||||
* @brief Conversion of Blender's new BMesh stuff
|
||||
*/
|
||||
#ifndef INCLUDED_AI_BLEND_BMESH_H
|
||||
#define INCLUDED_AI_BLEND_BMESH_H
|
||||
|
||||
#include <assimp/LogAux.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// BlenderScene.h
|
||||
namespace Blender
|
||||
{
|
||||
struct Mesh;
|
||||
struct MPoly;
|
||||
struct MLoop;
|
||||
}
|
||||
|
||||
class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter >
|
||||
{
|
||||
public:
|
||||
BlenderBMeshConverter( const Blender::Mesh* mesh );
|
||||
~BlenderBMeshConverter( );
|
||||
|
||||
bool ContainsBMesh( ) const;
|
||||
|
||||
const Blender::Mesh* TriangulateBMesh( );
|
||||
|
||||
private:
|
||||
void AssertValidMesh( );
|
||||
void AssertValidSizes( );
|
||||
void PrepareTriMesh( );
|
||||
void DestroyTriMesh( );
|
||||
void ConvertPolyToFaces( const Blender::MPoly& poly );
|
||||
void AddFace( int v1, int v2, int v3, int v4 = 0 );
|
||||
void AddTFace( const float* uv1, const float* uv2, const float *uv3, const float* uv4 = 0 );
|
||||
|
||||
const Blender::Mesh* BMesh;
|
||||
Blender::Mesh* triMesh;
|
||||
|
||||
friend class BlenderTessellatorGL;
|
||||
friend class BlenderTessellatorP2T;
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // INCLUDED_AI_BLEND_BMESH_H
|
||||
189
thirdparty/assimp/code/Blender/BlenderCustomData.cpp
vendored
Normal file
189
thirdparty/assimp/code/Blender/BlenderCustomData.cpp
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
#include "BlenderCustomData.h"
|
||||
#include "BlenderDNA.h"
|
||||
#include <array>
|
||||
#include <functional>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Blender {
|
||||
/**
|
||||
* @brief read/convert of Structure array to memory
|
||||
*/
|
||||
template<typename T>
|
||||
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
|
||||
for (size_t i = 0; i < cnt; ++i) {
|
||||
T read;
|
||||
s.Convert(read, db);
|
||||
*p = read;
|
||||
p++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief pointer to function read memory for n CustomData types
|
||||
*/
|
||||
typedef bool (*PRead)(ElemBase *pOut, const size_t cnt, const FileDatabase &db);
|
||||
typedef ElemBase * (*PCreate)(const size_t cnt);
|
||||
typedef void(*PDestroy)(ElemBase *);
|
||||
|
||||
#define IMPL_STRUCT_READ(ty) \
|
||||
bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
|
||||
ty *ptr = dynamic_cast<ty*>(v); \
|
||||
if (nullptr == ptr) { \
|
||||
return false; \
|
||||
} \
|
||||
return read<ty>(db.dna[#ty], ptr, cnt, db); \
|
||||
}
|
||||
|
||||
#define IMPL_STRUCT_CREATE(ty) \
|
||||
ElemBase *create##ty(const size_t cnt) { \
|
||||
return new ty[cnt]; \
|
||||
}
|
||||
|
||||
#define IMPL_STRUCT_DESTROY(ty) \
|
||||
void destroy##ty(ElemBase *pE) { \
|
||||
ty *p = dynamic_cast<ty *>(pE); \
|
||||
delete[]p; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief helper macro to define Structure functions
|
||||
*/
|
||||
#define IMPL_STRUCT(ty) \
|
||||
IMPL_STRUCT_READ(ty) \
|
||||
IMPL_STRUCT_CREATE(ty) \
|
||||
IMPL_STRUCT_DESTROY(ty)
|
||||
|
||||
// supported structures for CustomData
|
||||
IMPL_STRUCT(MVert)
|
||||
IMPL_STRUCT(MEdge)
|
||||
IMPL_STRUCT(MFace)
|
||||
IMPL_STRUCT(MTFace)
|
||||
IMPL_STRUCT(MTexPoly)
|
||||
IMPL_STRUCT(MLoopUV)
|
||||
IMPL_STRUCT(MLoopCol)
|
||||
IMPL_STRUCT(MPoly)
|
||||
IMPL_STRUCT(MLoop)
|
||||
|
||||
/**
|
||||
* @brief describes the size of data and the read function to be used for single CustomerData.type
|
||||
*/
|
||||
struct CustomDataTypeDescription {
|
||||
PRead Read; ///< function to read one CustomData type element
|
||||
PCreate Create; ///< function to allocate n type elements
|
||||
PDestroy Destroy;
|
||||
|
||||
CustomDataTypeDescription(PRead read, PCreate create, PDestroy destroy)
|
||||
: Read(read)
|
||||
, Create(create)
|
||||
, Destroy(destroy)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief helper macro to define Structure type specific CustomDataTypeDescription
|
||||
* @note IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function
|
||||
*/
|
||||
#define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \
|
||||
CustomDataTypeDescription{&read##ty, &create##ty, &destroy##ty}
|
||||
|
||||
/**
|
||||
* @brief helper macro to define CustomDataTypeDescription for UNSUPPORTED type
|
||||
*/
|
||||
#define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \
|
||||
CustomDataTypeDescription{nullptr, nullptr, nullptr}
|
||||
|
||||
/**
|
||||
* @brief descriptors for data pointed to from CustomDataLayer.data
|
||||
* @note some of the CustomData uses already well defined Structures
|
||||
* other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
|
||||
* use a special readfunction for that cases
|
||||
*/
|
||||
std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MFace),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTFace),
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol),
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop),
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION
|
||||
}};
|
||||
|
||||
|
||||
bool isValidCustomDataType(const int cdtype) {
|
||||
return cdtype >= 0 && cdtype < CD_NUMTYPES;
|
||||
}
|
||||
|
||||
bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) {
|
||||
if (!isValidCustomDataType(cdtype)) {
|
||||
throw Error((Formatter::format(), "CustomData.type ", cdtype, " out of index"));
|
||||
}
|
||||
|
||||
const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype];
|
||||
if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) {
|
||||
// allocate cnt elements and parse them from file
|
||||
out.reset(cdtd.Create(cnt), cdtd.Destroy);
|
||||
return cdtd.Read(out.get(), cnt, db);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
|
||||
for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) {
|
||||
if (it->get()->type == cdtype && name == it->get()->name) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ElemBase * getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name)
|
||||
{
|
||||
const std::shared_ptr<CustomDataLayer> pLayer = getCustomDataLayer(customdata, cdtype, name);
|
||||
if (pLayer && pLayer->data) {
|
||||
return pLayer->data.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
89
thirdparty/assimp/code/Blender/BlenderCustomData.h
vendored
Normal file
89
thirdparty/assimp/code/Blender/BlenderCustomData.h
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlenderDNA.h"
|
||||
#include "BlenderScene.h"
|
||||
#include <memory>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Blender {
|
||||
/* CustomData.type from Blender (2.79b) */
|
||||
enum CustomDataType {
|
||||
CD_AUTO_FROM_NAME = -1,
|
||||
CD_MVERT = 0,
|
||||
#ifdef DNA_DEPRECATED
|
||||
CD_MSTICKY = 1, /* DEPRECATED */
|
||||
#endif
|
||||
CD_MDEFORMVERT = 2,
|
||||
CD_MEDGE = 3,
|
||||
CD_MFACE = 4,
|
||||
CD_MTFACE = 5,
|
||||
CD_MCOL = 6,
|
||||
CD_ORIGINDEX = 7,
|
||||
CD_NORMAL = 8,
|
||||
/* CD_POLYINDEX = 9, */
|
||||
CD_PROP_FLT = 10,
|
||||
CD_PROP_INT = 11,
|
||||
CD_PROP_STR = 12,
|
||||
CD_ORIGSPACE = 13, /* for modifier stack face location mapping */
|
||||
CD_ORCO = 14,
|
||||
CD_MTEXPOLY = 15,
|
||||
CD_MLOOPUV = 16,
|
||||
CD_MLOOPCOL = 17,
|
||||
CD_TANGENT = 18,
|
||||
CD_MDISPS = 19,
|
||||
CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */
|
||||
/* CD_ID_MCOL = 21, */
|
||||
CD_TEXTURE_MLOOPCOL = 22,
|
||||
CD_CLOTH_ORCO = 23,
|
||||
CD_RECAST = 24,
|
||||
|
||||
/* BMESH ONLY START */
|
||||
CD_MPOLY = 25,
|
||||
CD_MLOOP = 26,
|
||||
CD_SHAPE_KEYINDEX = 27,
|
||||
CD_SHAPEKEY = 28,
|
||||
CD_BWEIGHT = 29,
|
||||
CD_CREASE = 30,
|
||||
CD_ORIGSPACE_MLOOP = 31,
|
||||
CD_PREVIEW_MLOOPCOL = 32,
|
||||
CD_BM_ELEM_PYPTR = 33,
|
||||
/* BMESH ONLY END */
|
||||
|
||||
CD_PAINT_MASK = 34,
|
||||
CD_GRID_PAINT_MASK = 35,
|
||||
CD_MVERT_SKIN = 36,
|
||||
CD_FREESTYLE_EDGE = 37,
|
||||
CD_FREESTYLE_FACE = 38,
|
||||
CD_MLOOPTANGENT = 39,
|
||||
CD_TESSLOOPNORMAL = 40,
|
||||
CD_CUSTOMLOOPNORMAL = 41,
|
||||
|
||||
CD_NUMTYPES = 42
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief check if given cdtype is valid (ie >= 0 and < CD_NUMTYPES)
|
||||
* @param[in] cdtype to check
|
||||
* @return true when valid
|
||||
*/
|
||||
bool isValidCustomDataType(const int cdtype);
|
||||
|
||||
/**
|
||||
* @brief returns CustomDataLayer ptr for given cdtype and name
|
||||
* @param[in] customdata CustomData to search for wanted layer
|
||||
* @param[in] cdtype to search for
|
||||
* @param[in] name to search for
|
||||
* @return CustomDataLayer * or nullptr if not found
|
||||
*/
|
||||
std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, CustomDataType cdtype, const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief returns CustomDataLayer data ptr for given cdtype and name
|
||||
* @param[in] customdata CustomData to search for wanted layer
|
||||
* @param[in] cdtype to search for
|
||||
* @param[in] name to search for
|
||||
* @return * to struct data or nullptr if not found
|
||||
*/
|
||||
const ElemBase * getCustomDataLayerData(const CustomData &customdata, CustomDataType cdtype, const std::string &name);
|
||||
}
|
||||
}
|
||||
375
thirdparty/assimp/code/Blender/BlenderDNA.cpp
vendored
Normal file
375
thirdparty/assimp/code/Blender/BlenderDNA.cpp
vendored
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderDNA.cpp
|
||||
* @brief Implementation of the Blender `DNA`, that is its own
|
||||
* serialized set of data structures.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
#include "BlenderDNA.h"
|
||||
#include <assimp/StreamReader.h>
|
||||
#include <assimp/fast_atof.h>
|
||||
#include <assimp/TinyFormatter.h>
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Blender;
|
||||
using namespace Assimp::Formatter;
|
||||
|
||||
static bool match4(StreamReaderAny& stream, const char* string) {
|
||||
ai_assert( nullptr != string );
|
||||
char tmp[4];
|
||||
tmp[ 0 ] = ( stream ).GetI1();
|
||||
tmp[ 1 ] = ( stream ).GetI1();
|
||||
tmp[ 2 ] = ( stream ).GetI1();
|
||||
tmp[ 3 ] = ( stream ).GetI1();
|
||||
return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]);
|
||||
}
|
||||
|
||||
struct Type {
|
||||
size_t size;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DNAParser::Parse ()
|
||||
{
|
||||
StreamReaderAny& stream = *db.reader.get();
|
||||
DNA& dna = db.dna;
|
||||
|
||||
if(!match4(stream,"SDNA")) {
|
||||
throw DeadlyImportError("BlenderDNA: Expected SDNA chunk");
|
||||
}
|
||||
|
||||
// name dictionary
|
||||
if(!match4(stream,"NAME")) {
|
||||
throw DeadlyImportError("BlenderDNA: Expected NAME field");
|
||||
}
|
||||
|
||||
std::vector<std::string> names (stream.GetI4());
|
||||
for(std::string& s : names) {
|
||||
while (char c = stream.GetI1()) {
|
||||
s += c;
|
||||
}
|
||||
}
|
||||
|
||||
// type dictionary
|
||||
for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
|
||||
if(!match4(stream,"TYPE")) {
|
||||
throw DeadlyImportError("BlenderDNA: Expected TYPE field");
|
||||
}
|
||||
|
||||
std::vector<Type> types (stream.GetI4());
|
||||
for(Type& s : types) {
|
||||
while (char c = stream.GetI1()) {
|
||||
s.name += c;
|
||||
}
|
||||
}
|
||||
|
||||
// type length dictionary
|
||||
for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
|
||||
if(!match4(stream,"TLEN")) {
|
||||
throw DeadlyImportError("BlenderDNA: Expected TLEN field");
|
||||
}
|
||||
|
||||
for(Type& s : types) {
|
||||
s.size = stream.GetI2();
|
||||
}
|
||||
|
||||
// structures dictionary
|
||||
for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
|
||||
if(!match4(stream,"STRC")) {
|
||||
throw DeadlyImportError("BlenderDNA: Expected STRC field");
|
||||
}
|
||||
|
||||
size_t end = stream.GetI4(), fields = 0;
|
||||
|
||||
dna.structures.reserve(end);
|
||||
for(size_t i = 0; i != end; ++i) {
|
||||
|
||||
uint16_t n = stream.GetI2();
|
||||
if (n >= types.size()) {
|
||||
throw DeadlyImportError((format(),
|
||||
"BlenderDNA: Invalid type index in structure name" ,n,
|
||||
" (there are only ", types.size(), " entries)"
|
||||
));
|
||||
}
|
||||
|
||||
// maintain separate indexes
|
||||
dna.indices[types[n].name] = dna.structures.size();
|
||||
|
||||
dna.structures.push_back(Structure());
|
||||
Structure& s = dna.structures.back();
|
||||
s.name = types[n].name;
|
||||
//s.index = dna.structures.size()-1;
|
||||
|
||||
n = stream.GetI2();
|
||||
s.fields.reserve(n);
|
||||
|
||||
size_t offset = 0;
|
||||
for (size_t m = 0; m < n; ++m, ++fields) {
|
||||
|
||||
uint16_t j = stream.GetI2();
|
||||
if (j >= types.size()) {
|
||||
throw DeadlyImportError((format(),
|
||||
"BlenderDNA: Invalid type index in structure field ", j,
|
||||
" (there are only ", types.size(), " entries)"
|
||||
));
|
||||
}
|
||||
s.fields.push_back(Field());
|
||||
Field& f = s.fields.back();
|
||||
f.offset = offset;
|
||||
|
||||
f.type = types[j].name;
|
||||
f.size = types[j].size;
|
||||
|
||||
j = stream.GetI2();
|
||||
if (j >= names.size()) {
|
||||
throw DeadlyImportError((format(),
|
||||
"BlenderDNA: Invalid name index in structure field ", j,
|
||||
" (there are only ", names.size(), " entries)"
|
||||
));
|
||||
}
|
||||
|
||||
f.name = names[j];
|
||||
f.flags = 0u;
|
||||
|
||||
// pointers always specify the size of the pointee instead of their own.
|
||||
// The pointer asterisk remains a property of the lookup name.
|
||||
if (f.name[0] == '*') {
|
||||
f.size = db.i64bit ? 8 : 4;
|
||||
f.flags |= FieldFlag_Pointer;
|
||||
}
|
||||
|
||||
// arrays, however, specify the size of a single element so we
|
||||
// need to parse the (possibly multi-dimensional) array declaration
|
||||
// in order to obtain the actual size of the array in the file.
|
||||
// Also we need to alter the lookup name to include no array
|
||||
// brackets anymore or size fixup won't work (if our size does
|
||||
// not match the size read from the DNA).
|
||||
if (*f.name.rbegin() == ']') {
|
||||
const std::string::size_type rb = f.name.find('[');
|
||||
if (rb == std::string::npos) {
|
||||
throw DeadlyImportError((format(),
|
||||
"BlenderDNA: Encountered invalid array declaration ",
|
||||
f.name
|
||||
));
|
||||
}
|
||||
|
||||
f.flags |= FieldFlag_Array;
|
||||
DNA::ExtractArraySize(f.name,f.array_sizes);
|
||||
f.name = f.name.substr(0,rb);
|
||||
|
||||
f.size *= f.array_sizes[0] * f.array_sizes[1];
|
||||
}
|
||||
|
||||
// maintain separate indexes
|
||||
s.indices[f.name] = s.fields.size()-1;
|
||||
offset += f.size;
|
||||
}
|
||||
s.size = offset;
|
||||
}
|
||||
|
||||
ASSIMP_LOG_DEBUG_F( "BlenderDNA: Got ", dna.structures.size()," structures with totally ",fields," fields");
|
||||
|
||||
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
|
||||
dna.DumpToFile();
|
||||
#endif
|
||||
|
||||
dna.AddPrimitiveStructures();
|
||||
dna.RegisterConverters();
|
||||
}
|
||||
|
||||
|
||||
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
|
||||
|
||||
#include <fstream>
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DNA :: DumpToFile()
|
||||
{
|
||||
// we don't bother using the VFS here for this is only for debugging.
|
||||
// (and all your bases are belong to us).
|
||||
|
||||
std::ofstream f("dna.txt");
|
||||
if (f.fail()) {
|
||||
ASSIMP_LOG_ERROR("Could not dump dna to dna.txt");
|
||||
return;
|
||||
}
|
||||
f << "Field format: type name offset size" << "\n";
|
||||
f << "Structure format: name size" << "\n";
|
||||
|
||||
for(const Structure& s : structures) {
|
||||
f << s.name << " " << s.size << "\n\n";
|
||||
for(const Field& ff : s.fields) {
|
||||
f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << "\n";
|
||||
}
|
||||
f << "\n";
|
||||
}
|
||||
f << std::flush;
|
||||
|
||||
ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt");
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/*static*/ void DNA :: ExtractArraySize(
|
||||
const std::string& out,
|
||||
size_t array_sizes[2]
|
||||
)
|
||||
{
|
||||
array_sizes[0] = array_sizes[1] = 1;
|
||||
std::string::size_type pos = out.find('[');
|
||||
if (pos++ == std::string::npos) {
|
||||
return;
|
||||
}
|
||||
array_sizes[0] = strtoul10(&out[pos]);
|
||||
|
||||
pos = out.find('[',pos);
|
||||
if (pos++ == std::string::npos) {
|
||||
return;
|
||||
}
|
||||
array_sizes[1] = strtoul10(&out[pos]);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure(
|
||||
const Structure& structure,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
std::map<std::string, FactoryPair >::const_iterator it = converters.find(structure.name);
|
||||
if (it == converters.end()) {
|
||||
return std::shared_ptr< ElemBase >();
|
||||
}
|
||||
|
||||
std::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))();
|
||||
(structure.*((*it).second.second))(ret,db);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
DNA::FactoryPair DNA :: GetBlobToStructureConverter(
|
||||
const Structure& structure,
|
||||
const FileDatabase& /*db*/
|
||||
) const
|
||||
{
|
||||
std::map<std::string, FactoryPair>::const_iterator it = converters.find(structure.name);
|
||||
return it == converters.end() ? FactoryPair() : (*it).second;
|
||||
}
|
||||
|
||||
// basing on http://www.blender.org/development/architecture/notes-on-sdna/
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DNA :: AddPrimitiveStructures()
|
||||
{
|
||||
// NOTE: these are just dummies. Their presence enforces
|
||||
// Structure::Convert<target_type> to be called on these
|
||||
// empty structures. These converters are special
|
||||
// overloads which scan the name of the structure and
|
||||
// perform the required data type conversion if one
|
||||
// of these special names is found in the structure
|
||||
// in question.
|
||||
|
||||
indices["int"] = structures.size();
|
||||
structures.push_back( Structure() );
|
||||
structures.back().name = "int";
|
||||
structures.back().size = 4;
|
||||
|
||||
indices["short"] = structures.size();
|
||||
structures.push_back( Structure() );
|
||||
structures.back().name = "short";
|
||||
structures.back().size = 2;
|
||||
|
||||
|
||||
indices["char"] = structures.size();
|
||||
structures.push_back( Structure() );
|
||||
structures.back().name = "char";
|
||||
structures.back().size = 1;
|
||||
|
||||
|
||||
indices["float"] = structures.size();
|
||||
structures.push_back( Structure() );
|
||||
structures.back().name = "float";
|
||||
structures.back().size = 4;
|
||||
|
||||
|
||||
indices["double"] = structures.size();
|
||||
structures.push_back( Structure() );
|
||||
structures.back().name = "double";
|
||||
structures.back().size = 8;
|
||||
|
||||
// no long, seemingly.
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SectionParser :: Next()
|
||||
{
|
||||
stream.SetCurrentPos(current.start + current.size);
|
||||
|
||||
const char tmp[] = {
|
||||
(const char)stream.GetI1(),
|
||||
(const char)stream.GetI1(),
|
||||
(const char)stream.GetI1(),
|
||||
(const char)stream.GetI1()
|
||||
};
|
||||
current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1);
|
||||
|
||||
current.size = stream.GetI4();
|
||||
current.address.val = ptr64 ? stream.GetU8() : stream.GetU4();
|
||||
|
||||
current.dna_index = stream.GetI4();
|
||||
current.num = stream.GetI4();
|
||||
|
||||
current.start = stream.GetCurrentPos();
|
||||
if (stream.GetRemainingSizeToLimit() < current.size) {
|
||||
throw DeadlyImportError("BLEND: invalid size of file block");
|
||||
}
|
||||
|
||||
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
|
||||
ASSIMP_LOG_DEBUG(current.id);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
844
thirdparty/assimp/code/Blender/BlenderDNA.h
vendored
Normal file
844
thirdparty/assimp/code/Blender/BlenderDNA.h
vendored
Normal file
@@ -0,0 +1,844 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderDNA.h
|
||||
* @brief Blender `DNA` (file format specification embedded in
|
||||
* blend file itself) loader.
|
||||
*/
|
||||
#ifndef INCLUDED_AI_BLEND_DNA_H
|
||||
#define INCLUDED_AI_BLEND_DNA_H
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/StreamReader.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
// enable verbose log output. really verbose, so be careful.
|
||||
#ifdef ASSIMP_BUILD_DEBUG
|
||||
# define ASSIMP_BUILD_BLENDER_DEBUG
|
||||
#endif
|
||||
|
||||
// #define ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
template <bool,bool> class StreamReader;
|
||||
typedef StreamReader<true,true> StreamReaderAny;
|
||||
|
||||
namespace Blender {
|
||||
|
||||
class FileDatabase;
|
||||
struct FileBlockHead;
|
||||
|
||||
template <template <typename> class TOUT>
|
||||
class ObjectCache;
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Exception class used by the blender loader to selectively catch exceptions
|
||||
* thrown in its own code (DeadlyImportErrors thrown in general utility
|
||||
* functions are untouched then). If such an exception is not caught by
|
||||
* the loader itself, it will still be caught by Assimp due to its
|
||||
* ancestry. */
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Error : DeadlyImportError {
|
||||
Error (const std::string& s)
|
||||
: DeadlyImportError(s) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** The only purpose of this structure is to feed a virtual dtor into its
|
||||
* descendents. It serves as base class for all data structure fields. */
|
||||
// -------------------------------------------------------------------------------
|
||||
struct ElemBase {
|
||||
ElemBase()
|
||||
: dna_type(nullptr)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual ~ElemBase() {
|
||||
// empty
|
||||
}
|
||||
|
||||
/** Type name of the element. The type
|
||||
* string points is the `c_str` of the `name` attribute of the
|
||||
* corresponding `Structure`, that is, it is only valid as long
|
||||
* as the DNA is not modified. The dna_type is only set if the
|
||||
* data type is not static, i.e. a std::shared_ptr<ElemBase>
|
||||
* in the scene description would have its type resolved
|
||||
* at runtime, so this member is always set. */
|
||||
const char* dna_type;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Represents a generic pointer to a memory location, which can be either 32
|
||||
* or 64 bits. These pointers are loaded from the BLEND file and finally
|
||||
* fixed to point to the real, converted representation of the objects
|
||||
* they used to point to.*/
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Pointer {
|
||||
Pointer()
|
||||
: val() {
|
||||
// empty
|
||||
}
|
||||
uint64_t val;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Represents a generic offset within a BLEND file */
|
||||
// -------------------------------------------------------------------------------
|
||||
struct FileOffset {
|
||||
FileOffset()
|
||||
: val() {
|
||||
// empty
|
||||
}
|
||||
uint64_t val;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Dummy derivate of std::vector to be able to use it in templates simultaenously
|
||||
* with std::shared_ptr, which takes only one template argument
|
||||
* while std::vector takes three. Also we need to provide some special member
|
||||
* functions of shared_ptr */
|
||||
// -------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
class vector : public std::vector<T> {
|
||||
public:
|
||||
using std::vector<T>::resize;
|
||||
using std::vector<T>::empty;
|
||||
|
||||
void reset() {
|
||||
resize(0);
|
||||
}
|
||||
|
||||
operator bool () const {
|
||||
return !empty();
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Mixed flags for use in #Field */
|
||||
// -------------------------------------------------------------------------------
|
||||
enum FieldFlags {
|
||||
FieldFlag_Pointer = 0x1,
|
||||
FieldFlag_Array = 0x2
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Represents a single member of a data structure in a BLEND file */
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Field {
|
||||
std::string name;
|
||||
std::string type;
|
||||
|
||||
size_t size;
|
||||
size_t offset;
|
||||
|
||||
/** Size of each array dimension. For flat arrays,
|
||||
* the second dimension is set to 1. */
|
||||
size_t array_sizes[2];
|
||||
|
||||
/** Any of the #FieldFlags enumerated values */
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Range of possible behaviours for fields absend in the input file. Some are
|
||||
* mission critical so we need them, while others can silently be default
|
||||
* initialized and no animations are harmed. */
|
||||
// -------------------------------------------------------------------------------
|
||||
enum ErrorPolicy {
|
||||
/** Substitute default value and ignore */
|
||||
ErrorPolicy_Igno,
|
||||
/** Substitute default value and write to log */
|
||||
ErrorPolicy_Warn,
|
||||
/** Substitute a massive error message and crash the whole matrix. Its time for another zion */
|
||||
ErrorPolicy_Fail
|
||||
};
|
||||
|
||||
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
|
||||
# define ErrorPolicy_Igno ErrorPolicy_Warn
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Represents a data structure in a BLEND file. A Structure defines n fields
|
||||
* and their locations and encodings the input stream. Usually, every
|
||||
* Structure instance pertains to one equally-named data structure in the
|
||||
* BlenderScene.h header. This class defines various utilities to map a
|
||||
* binary `blob` read from the file to such a structure instance with
|
||||
* meaningful contents. */
|
||||
// -------------------------------------------------------------------------------
|
||||
class Structure {
|
||||
template <template <typename> class> friend class ObjectCache;
|
||||
|
||||
public:
|
||||
Structure()
|
||||
: cache_idx(static_cast<size_t>(-1) ){
|
||||
// empty
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// publicly accessible members
|
||||
std::string name;
|
||||
vector< Field > fields;
|
||||
std::map<std::string, size_t> indices;
|
||||
|
||||
size_t size;
|
||||
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Access a field of the structure by its canonical name. The pointer version
|
||||
* returns NULL on failure while the reference version raises an import error. */
|
||||
inline const Field& operator [] (const std::string& ss) const;
|
||||
inline const Field* Get (const std::string& ss) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Access a field of the structure by its index */
|
||||
inline const Field& operator [] (const size_t i) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
inline bool operator== (const Structure& other) const {
|
||||
return name == other.name; // name is meant to be an unique identifier
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
inline bool operator!= (const Structure& other) const {
|
||||
return name != other.name;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Try to read an instance of the structure from the stream
|
||||
* and attempt to convert to `T`. This is done by
|
||||
* an appropriate specialization. If none is available,
|
||||
* a compiler complain is the result.
|
||||
* @param dest Destination value to be written
|
||||
* @param db File database, including input stream. */
|
||||
template <typename T> void Convert (T& dest, const FileDatabase& db) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// generic converter
|
||||
template <typename T>
|
||||
void Convert(std::shared_ptr<ElemBase> in,const FileDatabase& db) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// generic allocator
|
||||
template <typename T> std::shared_ptr<ElemBase> Allocate() const;
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// field parsing for 1d arrays
|
||||
template <int error_policy, typename T, size_t M>
|
||||
void ReadFieldArray(T (& out)[M], const char* name,
|
||||
const FileDatabase& db) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// field parsing for 2d arrays
|
||||
template <int error_policy, typename T, size_t M, size_t N>
|
||||
void ReadFieldArray2(T (& out)[M][N], const char* name,
|
||||
const FileDatabase& db) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// field parsing for pointer or dynamic array types
|
||||
// (std::shared_ptr)
|
||||
// The return value indicates whether the data was already cached.
|
||||
template <int error_policy, template <typename> class TOUT, typename T>
|
||||
bool ReadFieldPtr(TOUT<T>& out, const char* name,
|
||||
const FileDatabase& db,
|
||||
bool non_recursive = false) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// field parsing for static arrays of pointer or dynamic
|
||||
// array types (std::shared_ptr[])
|
||||
// The return value indicates whether the data was already cached.
|
||||
template <int error_policy, template <typename> class TOUT, typename T, size_t N>
|
||||
bool ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
|
||||
const FileDatabase& db) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// field parsing for `normal` values
|
||||
// The return value indicates whether the data was already cached.
|
||||
template <int error_policy, typename T>
|
||||
void ReadField(T& out, const char* name,
|
||||
const FileDatabase& db) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
/**
|
||||
* @brief field parsing for dynamic vectors
|
||||
* @param[in] out vector of struct to be filled
|
||||
* @param[in] name of field
|
||||
* @param[in] db to access the file, dna, ...
|
||||
* @return true when read was successful
|
||||
*/
|
||||
template <int error_policy, template <typename> class TOUT, typename T>
|
||||
bool ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const;
|
||||
|
||||
/**
|
||||
* @brief parses raw customdata
|
||||
* @param[in] out shared_ptr to be filled
|
||||
* @param[in] cdtype customdata type to read
|
||||
* @param[in] name of field ptr
|
||||
* @param[in] db to access the file, dna, ...
|
||||
* @return true when read was successful
|
||||
*/
|
||||
template <int error_policy>
|
||||
bool ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const;
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------
|
||||
template <template <typename> class TOUT, typename T>
|
||||
bool ResolvePointer(TOUT<T>& out, const Pointer & ptrval,
|
||||
const FileDatabase& db, const Field& f,
|
||||
bool non_recursive = false) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
template <template <typename> class TOUT, typename T>
|
||||
bool ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
|
||||
const FileDatabase& db, const Field& f, bool) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
bool ResolvePointer( std::shared_ptr< FileOffset >& out, const Pointer & ptrval,
|
||||
const FileDatabase& db, const Field& f, bool) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
inline const FileBlockHead* LocateFileBlockForAddress(
|
||||
const Pointer & ptrval,
|
||||
const FileDatabase& db) const;
|
||||
|
||||
private:
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
template <typename T> T* _allocate(std::shared_ptr<T>& out, size_t& s) const {
|
||||
out = std::shared_ptr<T>(new T());
|
||||
s = 1;
|
||||
return out.get();
|
||||
}
|
||||
|
||||
template <typename T> T* _allocate(vector<T>& out, size_t& s) const {
|
||||
out.resize(s);
|
||||
return s ? &out.front() : NULL;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
template <int error_policy>
|
||||
struct _defaultInitializer {
|
||||
|
||||
template <typename T, unsigned int N>
|
||||
void operator ()(T (& out)[N], const char* = NULL) {
|
||||
for (unsigned int i = 0; i < N; ++i) {
|
||||
out[i] = T();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, unsigned int N, unsigned int M>
|
||||
void operator ()(T (& out)[N][M], const char* = NULL) {
|
||||
for (unsigned int i = 0; i < N; ++i) {
|
||||
for (unsigned int j = 0; j < M; ++j) {
|
||||
out[i][j] = T();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator ()(T& out, const char* = NULL) {
|
||||
out = T();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
mutable size_t cache_idx;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------
|
||||
template <> struct Structure :: _defaultInitializer<ErrorPolicy_Warn> {
|
||||
|
||||
template <typename T>
|
||||
void operator ()(T& out, const char* reason = "<add reason>") {
|
||||
ASSIMP_LOG_WARN(reason);
|
||||
|
||||
// ... and let the show go on
|
||||
_defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct Structure :: _defaultInitializer<ErrorPolicy_Fail> {
|
||||
|
||||
template <typename T>
|
||||
void operator ()(T& /*out*/,const char* = "") {
|
||||
// obviously, it is crucial that _DefaultInitializer is used
|
||||
// only from within a catch clause.
|
||||
throw DeadlyImportError("Constructing BlenderDNA Structure encountered an error");
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------
|
||||
template <> inline bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(std::shared_ptr<ElemBase>& out,
|
||||
const Pointer & ptrval,
|
||||
const FileDatabase& db,
|
||||
const Field& f,
|
||||
bool
|
||||
) const;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Represents the full data structure information for a single BLEND file.
|
||||
* This data is extracted from the DNA1 chunk in the file.
|
||||
* #DNAParser does the reading and represents currently the only place where
|
||||
* DNA is altered.*/
|
||||
// -------------------------------------------------------------------------------
|
||||
class DNA
|
||||
{
|
||||
public:
|
||||
|
||||
typedef void (Structure::*ConvertProcPtr) (
|
||||
std::shared_ptr<ElemBase> in,
|
||||
const FileDatabase&
|
||||
) const;
|
||||
|
||||
typedef std::shared_ptr<ElemBase> (
|
||||
Structure::*AllocProcPtr) () const;
|
||||
|
||||
typedef std::pair< AllocProcPtr, ConvertProcPtr > FactoryPair;
|
||||
|
||||
public:
|
||||
|
||||
std::map<std::string, FactoryPair > converters;
|
||||
vector<Structure > structures;
|
||||
std::map<std::string, size_t> indices;
|
||||
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Access a structure by its canonical name, the pointer version returns NULL on failure
|
||||
* while the reference version raises an error. */
|
||||
inline const Structure& operator [] (const std::string& ss) const;
|
||||
inline const Structure* Get (const std::string& ss) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Access a structure by its index */
|
||||
inline const Structure& operator [] (const size_t i) const;
|
||||
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Add structure definitions for all the primitive types,
|
||||
* i.e. integer, short, char, float */
|
||||
void AddPrimitiveStructures();
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Fill the @c converters member with converters for all
|
||||
* known data types. The implementation of this method is
|
||||
* in BlenderScene.cpp and is machine-generated.
|
||||
* Converters are used to quickly handle objects whose
|
||||
* exact data type is a runtime-property and not yet
|
||||
* known at compile time (consier Object::data).*/
|
||||
void RegisterConverters();
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Take an input blob from the stream, interpret it according to
|
||||
* a its structure name and convert it to the intermediate
|
||||
* representation.
|
||||
* @param structure Destination structure definition
|
||||
* @param db File database.
|
||||
* @return A null pointer if no appropriate converter is available.*/
|
||||
std::shared_ptr< ElemBase > ConvertBlobToStructure(
|
||||
const Structure& structure,
|
||||
const FileDatabase& db
|
||||
) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Find a suitable conversion function for a given Structure.
|
||||
* Such a converter function takes a blob from the input
|
||||
* stream, reads as much as it needs, and builds up a
|
||||
* complete object in intermediate representation.
|
||||
* @param structure Destination structure definition
|
||||
* @param db File database.
|
||||
* @return A null pointer in .first if no appropriate converter is available.*/
|
||||
FactoryPair GetBlobToStructureConverter(
|
||||
const Structure& structure,
|
||||
const FileDatabase& db
|
||||
) const;
|
||||
|
||||
|
||||
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
|
||||
// --------------------------------------------------------
|
||||
/** Dump the DNA to a text file. This is for debugging purposes.
|
||||
* The output file is `dna.txt` in the current working folder*/
|
||||
void DumpToFile();
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Extract array dimensions from a C array declaration, such
|
||||
* as `...[4][6]`. Returned string would be `...[][]`.
|
||||
* @param out
|
||||
* @param array_sizes Receive maximally two array dimensions,
|
||||
* the second element is set to 1 if the array is flat.
|
||||
* Both are set to 1 if the input is not an array.
|
||||
* @throw DeadlyImportError if more than 2 dimensions are
|
||||
* encountered. */
|
||||
static void ExtractArraySize(
|
||||
const std::string& out,
|
||||
size_t array_sizes[2]
|
||||
);
|
||||
};
|
||||
|
||||
// special converters for primitive types
|
||||
template <> inline void Structure :: Convert<int> (int& dest,const FileDatabase& db) const;
|
||||
template <> inline void Structure :: Convert<short> (short& dest,const FileDatabase& db) const;
|
||||
template <> inline void Structure :: Convert<char> (char& dest,const FileDatabase& db) const;
|
||||
template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const;
|
||||
template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const;
|
||||
template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const;
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Describes a master file block header. Each master file sections holds n
|
||||
* elements of a certain SDNA structure (or otherwise unspecified data). */
|
||||
// -------------------------------------------------------------------------------
|
||||
struct FileBlockHead
|
||||
{
|
||||
// points right after the header of the file block
|
||||
StreamReaderAny::pos start;
|
||||
|
||||
std::string id;
|
||||
size_t size;
|
||||
|
||||
// original memory address of the data
|
||||
Pointer address;
|
||||
|
||||
// index into DNA
|
||||
unsigned int dna_index;
|
||||
|
||||
// number of structure instances to follow
|
||||
size_t num;
|
||||
|
||||
|
||||
|
||||
// file blocks are sorted by address to quickly locate specific memory addresses
|
||||
bool operator < (const FileBlockHead& o) const {
|
||||
return address.val < o.address.val;
|
||||
}
|
||||
|
||||
// for std::upper_bound
|
||||
operator const Pointer& () const {
|
||||
return address;
|
||||
}
|
||||
};
|
||||
|
||||
// for std::upper_bound
|
||||
inline bool operator< (const Pointer& a, const Pointer& b) {
|
||||
return a.val < b.val;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Utility to read all master file blocks in turn. */
|
||||
// -------------------------------------------------------------------------------
|
||||
class SectionParser
|
||||
{
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** @param stream Inout stream, must point to the
|
||||
* first section in the file. Call Next() once
|
||||
* to have it read.
|
||||
* @param ptr64 Pointer size in file is 64 bits? */
|
||||
SectionParser(StreamReaderAny& stream,bool ptr64)
|
||||
: stream(stream)
|
||||
, ptr64(ptr64)
|
||||
{
|
||||
current.size = current.start = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------
|
||||
const FileBlockHead& GetCurrent() const {
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Advance to the next section.
|
||||
* @throw DeadlyImportError if the last chunk was passed. */
|
||||
void Next();
|
||||
|
||||
public:
|
||||
|
||||
FileBlockHead current;
|
||||
StreamReaderAny& stream;
|
||||
bool ptr64;
|
||||
};
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Import statistics, i.e. number of file blocks read*/
|
||||
// -------------------------------------------------------------------------------
|
||||
class Statistics {
|
||||
|
||||
public:
|
||||
|
||||
Statistics ()
|
||||
: fields_read ()
|
||||
, pointers_resolved ()
|
||||
, cache_hits ()
|
||||
// , blocks_read ()
|
||||
, cached_objects ()
|
||||
{}
|
||||
|
||||
public:
|
||||
|
||||
/** total number of fields we read */
|
||||
unsigned int fields_read;
|
||||
|
||||
/** total number of resolved pointers */
|
||||
unsigned int pointers_resolved;
|
||||
|
||||
/** number of pointers resolved from the cache */
|
||||
unsigned int cache_hits;
|
||||
|
||||
/** number of blocks (from FileDatabase::entries)
|
||||
we did actually read from. */
|
||||
// unsigned int blocks_read;
|
||||
|
||||
/** objects in FileData::cache */
|
||||
unsigned int cached_objects;
|
||||
};
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** The object cache - all objects addressed by pointers are added here. This
|
||||
* avoids circular references and avoids object duplication. */
|
||||
// -------------------------------------------------------------------------------
|
||||
template <template <typename> class TOUT>
|
||||
class ObjectCache
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::map< Pointer, TOUT<ElemBase> > StructureCache;
|
||||
|
||||
public:
|
||||
|
||||
ObjectCache(const FileDatabase& db)
|
||||
: db(db)
|
||||
{
|
||||
// currently there are only ~400 structure records per blend file.
|
||||
// we read only a small part of them and don't cache objects
|
||||
// which we don't need, so this should suffice.
|
||||
caches.reserve(64);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Check whether a specific item is in the cache.
|
||||
* @param s Data type of the item
|
||||
* @param out Output pointer. Unchanged if the
|
||||
* cache doesn't know the item yet.
|
||||
* @param ptr Item address to look for. */
|
||||
template <typename T> void get (
|
||||
const Structure& s,
|
||||
TOUT<T>& out,
|
||||
const Pointer& ptr) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Add an item to the cache after the item has
|
||||
* been fully read. Do not insert anything that
|
||||
* may be faulty or might cause the loading
|
||||
* to abort.
|
||||
* @param s Data type of the item
|
||||
* @param out Item to insert into the cache
|
||||
* @param ptr address (cache key) of the item. */
|
||||
template <typename T> void set
|
||||
(const Structure& s,
|
||||
const TOUT<T>& out,
|
||||
const Pointer& ptr);
|
||||
|
||||
private:
|
||||
|
||||
mutable vector<StructureCache> caches;
|
||||
const FileDatabase& db;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------
|
||||
template <> class ObjectCache<Blender::vector>
|
||||
{
|
||||
public:
|
||||
|
||||
ObjectCache(const FileDatabase&) {}
|
||||
|
||||
template <typename T> void get(const Structure&, vector<T>&, const Pointer&) {}
|
||||
template <typename T> void set(const Structure&, const vector<T>&, const Pointer&) {}
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Memory representation of a full BLEND file and all its dependencies. The
|
||||
* output aiScene is constructed from an instance of this data structure. */
|
||||
// -------------------------------------------------------------------------------
|
||||
class FileDatabase
|
||||
{
|
||||
template <template <typename> class TOUT> friend class ObjectCache;
|
||||
|
||||
public:
|
||||
FileDatabase()
|
||||
: _cacheArrays(*this)
|
||||
, _cache(*this)
|
||||
, next_cache_idx()
|
||||
{}
|
||||
|
||||
public:
|
||||
// publicly accessible fields
|
||||
bool i64bit;
|
||||
bool little;
|
||||
|
||||
DNA dna;
|
||||
std::shared_ptr< StreamReaderAny > reader;
|
||||
vector< FileBlockHead > entries;
|
||||
|
||||
public:
|
||||
|
||||
Statistics& stats() const {
|
||||
return _stats;
|
||||
}
|
||||
|
||||
// For all our templates to work on both shared_ptr's and vector's
|
||||
// using the same code, a dummy cache for arrays is provided. Actually,
|
||||
// arrays of objects are never cached because we can't easily
|
||||
// ensure their proper destruction.
|
||||
template <typename T>
|
||||
ObjectCache<std::shared_ptr>& cache(std::shared_ptr<T>& /*in*/) const {
|
||||
return _cache;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ObjectCache<vector>& cache(vector<T>& /*in*/) const {
|
||||
return _cacheArrays;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
mutable Statistics _stats;
|
||||
#endif
|
||||
|
||||
mutable ObjectCache<vector> _cacheArrays;
|
||||
mutable ObjectCache<std::shared_ptr> _cache;
|
||||
|
||||
mutable size_t next_cache_idx;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(default:4355)
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Factory to extract a #DNA from the DNA1 file block in a BLEND file. */
|
||||
// -------------------------------------------------------------------------------
|
||||
class DNAParser
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/** Bind the parser to a empty DNA and an input stream */
|
||||
DNAParser(FileDatabase& db)
|
||||
: db(db)
|
||||
{}
|
||||
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------
|
||||
/** Locate the DNA in the file and parse it. The input
|
||||
* stream is expected to point to the beginning of the DN1
|
||||
* chunk at the time this method is called and is
|
||||
* undefined afterwards.
|
||||
* @throw DeadlyImportError if the DNA cannot be read.
|
||||
* @note The position of the stream pointer is undefined
|
||||
* afterwards.*/
|
||||
void Parse ();
|
||||
|
||||
public:
|
||||
|
||||
/** Obtain a reference to the extracted DNA information */
|
||||
const Blender::DNA& GetDNA() const {
|
||||
return db.dna;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
FileDatabase& db;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief read CustomData's data to ptr to mem
|
||||
* @param[out] out memory ptr to set
|
||||
* @param[in] cdtype to read
|
||||
* @param[in] cnt cnt of elements to read
|
||||
* @param[in] db to read elements from
|
||||
* @return true when ok
|
||||
*/
|
||||
bool readCustomData(std::shared_ptr<ElemBase> &out, int cdtype, size_t cnt, const FileDatabase &db);
|
||||
|
||||
|
||||
} // end Blend
|
||||
} // end Assimp
|
||||
|
||||
#include "BlenderDNA.inl"
|
||||
|
||||
#endif
|
||||
856
thirdparty/assimp/code/Blender/BlenderDNA.inl
vendored
Normal file
856
thirdparty/assimp/code/Blender/BlenderDNA.inl
vendored
Normal file
@@ -0,0 +1,856 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderDNA.inl
|
||||
* @brief Blender `DNA` (file format specification embedded in
|
||||
* blend file itself) loader.
|
||||
*/
|
||||
#ifndef INCLUDED_AI_BLEND_DNA_INL
|
||||
#define INCLUDED_AI_BLEND_DNA_INL
|
||||
|
||||
#include <memory>
|
||||
#include <assimp/TinyFormatter.h>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Blender {
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
const Field& Structure :: operator [] (const std::string& ss) const
|
||||
{
|
||||
std::map<std::string, size_t>::const_iterator it = indices.find(ss);
|
||||
if (it == indices.end()) {
|
||||
throw Error((Formatter::format(),
|
||||
"BlendDNA: Did not find a field named `",ss,"` in structure `",name,"`"
|
||||
));
|
||||
}
|
||||
|
||||
return fields[(*it).second];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
const Field* Structure :: Get (const std::string& ss) const
|
||||
{
|
||||
std::map<std::string, size_t>::const_iterator it = indices.find(ss);
|
||||
return it == indices.end() ? NULL : &fields[(*it).second];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
const Field& Structure :: operator [] (const size_t i) const
|
||||
{
|
||||
if (i >= fields.size()) {
|
||||
throw Error((Formatter::format(),
|
||||
"BlendDNA: There is no field with index `",i,"` in structure `",name,"`"
|
||||
));
|
||||
}
|
||||
|
||||
return fields[i];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <typename T> std::shared_ptr<ElemBase> Structure :: Allocate() const
|
||||
{
|
||||
return std::shared_ptr<T>(new T());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <typename T> void Structure :: Convert(
|
||||
std::shared_ptr<ElemBase> in,
|
||||
const FileDatabase& db) const
|
||||
{
|
||||
Convert<T> (*static_cast<T*> ( in.get() ),db);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <int error_policy, typename T, size_t M>
|
||||
void Structure :: ReadFieldArray(T (& out)[M], const char* name, const FileDatabase& db) const
|
||||
{
|
||||
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
|
||||
try {
|
||||
const Field& f = (*this)[name];
|
||||
const Structure& s = db.dna[f.type];
|
||||
|
||||
// is the input actually an array?
|
||||
if (!(f.flags & FieldFlag_Array)) {
|
||||
throw Error((Formatter::format(),"Field `",name,"` of structure `",
|
||||
this->name,"` ought to be an array of size ",M
|
||||
));
|
||||
}
|
||||
|
||||
db.reader->IncPtr(f.offset);
|
||||
|
||||
// size conversions are always allowed, regardless of error_policy
|
||||
unsigned int i = 0;
|
||||
for(; i < std::min(f.array_sizes[0],M); ++i) {
|
||||
s.Convert(out[i],db);
|
||||
}
|
||||
for(; i < M; ++i) {
|
||||
_defaultInitializer<ErrorPolicy_Igno>()(out[i]);
|
||||
}
|
||||
}
|
||||
catch (const Error& e) {
|
||||
_defaultInitializer<error_policy>()(out,e.what());
|
||||
}
|
||||
|
||||
// and recover the previous stream position
|
||||
db.reader->SetCurrentPos(old);
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <int error_policy, typename T, size_t M, size_t N>
|
||||
void Structure :: ReadFieldArray2(T (& out)[M][N], const char* name, const FileDatabase& db) const
|
||||
{
|
||||
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
|
||||
try {
|
||||
const Field& f = (*this)[name];
|
||||
const Structure& s = db.dna[f.type];
|
||||
|
||||
// is the input actually an array?
|
||||
if (!(f.flags & FieldFlag_Array)) {
|
||||
throw Error((Formatter::format(),"Field `",name,"` of structure `",
|
||||
this->name,"` ought to be an array of size ",M,"*",N
|
||||
));
|
||||
}
|
||||
|
||||
db.reader->IncPtr(f.offset);
|
||||
|
||||
// size conversions are always allowed, regardless of error_policy
|
||||
unsigned int i = 0;
|
||||
for(; i < std::min(f.array_sizes[0],M); ++i) {
|
||||
unsigned int j = 0;
|
||||
for(; j < std::min(f.array_sizes[1],N); ++j) {
|
||||
s.Convert(out[i][j],db);
|
||||
}
|
||||
for(; j < N; ++j) {
|
||||
_defaultInitializer<ErrorPolicy_Igno>()(out[i][j]);
|
||||
}
|
||||
}
|
||||
for(; i < M; ++i) {
|
||||
_defaultInitializer<ErrorPolicy_Igno>()(out[i]);
|
||||
}
|
||||
}
|
||||
catch (const Error& e) {
|
||||
_defaultInitializer<error_policy>()(out,e.what());
|
||||
}
|
||||
|
||||
// and recover the previous stream position
|
||||
db.reader->SetCurrentPos(old);
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <int error_policy, template <typename> class TOUT, typename T>
|
||||
bool Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabase& db,
|
||||
bool non_recursive /*= false*/) const
|
||||
{
|
||||
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
|
||||
Pointer ptrval;
|
||||
const Field* f;
|
||||
try {
|
||||
f = &(*this)[name];
|
||||
|
||||
// sanity check, should never happen if the genblenddna script is right
|
||||
if (!(f->flags & FieldFlag_Pointer)) {
|
||||
throw Error((Formatter::format(),"Field `",name,"` of structure `",
|
||||
this->name,"` ought to be a pointer"));
|
||||
}
|
||||
|
||||
db.reader->IncPtr(f->offset);
|
||||
Convert(ptrval,db);
|
||||
// actually it is meaningless on which Structure the Convert is called
|
||||
// because the `Pointer` argument triggers a special implementation.
|
||||
}
|
||||
catch (const Error& e) {
|
||||
_defaultInitializer<error_policy>()(out,e.what());
|
||||
|
||||
out.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
// resolve the pointer and load the corresponding structure
|
||||
const bool res = ResolvePointer(out,ptrval,db,*f, non_recursive);
|
||||
|
||||
if(!non_recursive) {
|
||||
// and recover the previous stream position
|
||||
db.reader->SetCurrentPos(old);
|
||||
}
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <int error_policy, template <typename> class TOUT, typename T, size_t N>
|
||||
bool Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
|
||||
const FileDatabase& db) const
|
||||
{
|
||||
// XXX see if we can reduce this to call to the 'normal' ReadFieldPtr
|
||||
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
|
||||
Pointer ptrval[N];
|
||||
const Field* f;
|
||||
try {
|
||||
f = &(*this)[name];
|
||||
|
||||
// sanity check, should never happen if the genblenddna script is right
|
||||
if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) {
|
||||
throw Error((Formatter::format(),"Field `",name,"` of structure `",
|
||||
this->name,"` ought to be a pointer AND an array"));
|
||||
}
|
||||
|
||||
db.reader->IncPtr(f->offset);
|
||||
|
||||
size_t i = 0;
|
||||
for(; i < std::min(f->array_sizes[0],N); ++i) {
|
||||
Convert(ptrval[i],db);
|
||||
}
|
||||
for(; i < N; ++i) {
|
||||
_defaultInitializer<ErrorPolicy_Igno>()(ptrval[i]);
|
||||
}
|
||||
|
||||
// actually it is meaningless on which Structure the Convert is called
|
||||
// because the `Pointer` argument triggers a special implementation.
|
||||
}
|
||||
catch (const Error& e) {
|
||||
_defaultInitializer<error_policy>()(out,e.what());
|
||||
for(size_t i = 0; i < N; ++i) {
|
||||
out[i].reset();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool res = true;
|
||||
for(size_t i = 0; i < N; ++i) {
|
||||
// resolve the pointer and load the corresponding structure
|
||||
res = ResolvePointer(out[i],ptrval[i],db,*f) && res;
|
||||
}
|
||||
|
||||
// and recover the previous stream position
|
||||
db.reader->SetCurrentPos(old);
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <int error_policy, typename T>
|
||||
void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) const
|
||||
{
|
||||
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
|
||||
try {
|
||||
const Field& f = (*this)[name];
|
||||
// find the structure definition pertaining to this field
|
||||
const Structure& s = db.dna[f.type];
|
||||
|
||||
db.reader->IncPtr(f.offset);
|
||||
s.Convert(out,db);
|
||||
}
|
||||
catch (const Error& e) {
|
||||
_defaultInitializer<error_policy>()(out,e.what());
|
||||
}
|
||||
|
||||
// and recover the previous stream position
|
||||
db.reader->SetCurrentPos(old);
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// field parsing for raw untyped data (like CustomDataLayer.data)
|
||||
template <int error_policy>
|
||||
bool Structure::ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const {
|
||||
|
||||
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
|
||||
|
||||
Pointer ptrval;
|
||||
const Field* f;
|
||||
try {
|
||||
f = &(*this)[name];
|
||||
|
||||
// sanity check, should never happen if the genblenddna script is right
|
||||
if (!(f->flags & FieldFlag_Pointer)) {
|
||||
throw Error((Formatter::format(), "Field `", name, "` of structure `",
|
||||
this->name, "` ought to be a pointer"));
|
||||
}
|
||||
|
||||
db.reader->IncPtr(f->offset);
|
||||
Convert(ptrval, db);
|
||||
// actually it is meaningless on which Structure the Convert is called
|
||||
// because the `Pointer` argument triggers a special implementation.
|
||||
}
|
||||
catch (const Error& e) {
|
||||
_defaultInitializer<error_policy>()(out, e.what());
|
||||
out.reset();
|
||||
}
|
||||
|
||||
bool readOk = true;
|
||||
if (ptrval.val) {
|
||||
// get block for ptr
|
||||
const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
|
||||
db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
|
||||
// read block->num instances of given type to out
|
||||
readOk = readCustomData(out, cdtype, block->num, db);
|
||||
}
|
||||
|
||||
// and recover the previous stream position
|
||||
db.reader->SetCurrentPos(old);
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
|
||||
return readOk;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <int error_policy, template <typename> class TOUT, typename T>
|
||||
bool Structure::ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const {
|
||||
out.clear();
|
||||
|
||||
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
|
||||
|
||||
Pointer ptrval;
|
||||
const Field* f;
|
||||
try {
|
||||
f = &(*this)[name];
|
||||
|
||||
// sanity check, should never happen if the genblenddna script is right
|
||||
if (!(f->flags & FieldFlag_Pointer)) {
|
||||
throw Error((Formatter::format(), "Field `", name, "` of structure `",
|
||||
this->name, "` ought to be a pointer"));
|
||||
}
|
||||
|
||||
db.reader->IncPtr(f->offset);
|
||||
Convert(ptrval, db);
|
||||
// actually it is meaningless on which Structure the Convert is called
|
||||
// because the `Pointer` argument triggers a special implementation.
|
||||
}
|
||||
catch (const Error& e) {
|
||||
_defaultInitializer<error_policy>()(out, e.what());
|
||||
out.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (ptrval.val) {
|
||||
// find the file block the pointer is pointing to
|
||||
const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
|
||||
db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
|
||||
// FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
|
||||
// I really ought to improve StreamReader to work with 64 bit indices exclusively.
|
||||
|
||||
const Structure& s = db.dna[f->type];
|
||||
for (size_t i = 0; i < block->num; ++i) {
|
||||
TOUT<T> p(new T);
|
||||
s.Convert(*p, db);
|
||||
out.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
db.reader->SetCurrentPos(old);
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <template <typename> class TOUT, typename T>
|
||||
bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db,
|
||||
const Field& f,
|
||||
bool non_recursive /*= false*/) const
|
||||
{
|
||||
out.reset(); // ensure null pointers work
|
||||
if (!ptrval.val) {
|
||||
return false;
|
||||
}
|
||||
const Structure& s = db.dna[f.type];
|
||||
// find the file block the pointer is pointing to
|
||||
const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
|
||||
|
||||
// also determine the target type from the block header
|
||||
// and check if it matches the type which we expect.
|
||||
const Structure& ss = db.dna[block->dna_index];
|
||||
if (ss != s) {
|
||||
throw Error((Formatter::format(),"Expected target to be of type `",s.name,
|
||||
"` but seemingly it is a `",ss.name,"` instead"
|
||||
));
|
||||
}
|
||||
|
||||
// try to retrieve the object from the cache
|
||||
db.cache(out).get(s,out,ptrval);
|
||||
if (out) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// seek to this location, but save the previous stream pointer.
|
||||
const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
|
||||
db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
|
||||
// FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
|
||||
// I really ought to improve StreamReader to work with 64 bit indices exclusively.
|
||||
|
||||
// continue conversion after allocating the required storage
|
||||
size_t num = block->size / ss.size;
|
||||
T* o = _allocate(out,num);
|
||||
|
||||
// cache the object before we convert it to avoid cyclic recursion.
|
||||
db.cache(out).set(s,out,ptrval);
|
||||
|
||||
// if the non_recursive flag is set, we don't do anything but leave
|
||||
// the cursor at the correct position to resolve the object.
|
||||
if (!non_recursive) {
|
||||
for (size_t i = 0; i < num; ++i,++o) {
|
||||
s.Convert(*o,db);
|
||||
}
|
||||
|
||||
db.reader->SetCurrentPos(pold);
|
||||
}
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
if(out) {
|
||||
++db.stats().pointers_resolved;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
inline bool Structure :: ResolvePointer( std::shared_ptr< FileOffset >& out, const Pointer & ptrval,
|
||||
const FileDatabase& db,
|
||||
const Field&,
|
||||
bool) const
|
||||
{
|
||||
// Currently used exclusively by PackedFile::data to represent
|
||||
// a simple offset into the mapped BLEND file.
|
||||
out.reset();
|
||||
if (!ptrval.val) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the file block the pointer is pointing to
|
||||
const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
|
||||
|
||||
out = std::shared_ptr< FileOffset > (new FileOffset());
|
||||
out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) );
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <template <typename> class TOUT, typename T>
|
||||
bool Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
|
||||
const FileDatabase& db,
|
||||
const Field& f,
|
||||
bool) const
|
||||
{
|
||||
// This is a function overload, not a template specialization. According to
|
||||
// the partial ordering rules, it should be selected by the compiler
|
||||
// for array-of-pointer inputs, i.e. Object::mats.
|
||||
|
||||
out.reset();
|
||||
if (!ptrval.val) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the file block the pointer is pointing to
|
||||
const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
|
||||
const size_t num = block->size / (db.i64bit?8:4);
|
||||
|
||||
// keep the old stream position
|
||||
const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
|
||||
db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
|
||||
|
||||
bool res = false;
|
||||
// allocate raw storage for the array
|
||||
out.resize(num);
|
||||
for (size_t i = 0; i< num; ++i) {
|
||||
Pointer val;
|
||||
Convert(val,db);
|
||||
|
||||
// and resolve the pointees
|
||||
res = ResolvePointer(out[i],val,db,f) && res;
|
||||
}
|
||||
|
||||
db.reader->SetCurrentPos(pold);
|
||||
return res;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(std::shared_ptr<ElemBase>& out,
|
||||
const Pointer & ptrval,
|
||||
const FileDatabase& db,
|
||||
const Field&,
|
||||
bool
|
||||
) const
|
||||
{
|
||||
// Special case when the data type needs to be determined at runtime.
|
||||
// Less secure than in the `strongly-typed` case.
|
||||
|
||||
out.reset();
|
||||
if (!ptrval.val) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the file block the pointer is pointing to
|
||||
const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
|
||||
|
||||
// determine the target type from the block header
|
||||
const Structure& s = db.dna[block->dna_index];
|
||||
|
||||
// try to retrieve the object from the cache
|
||||
db.cache(out).get(s,out,ptrval);
|
||||
if (out) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// seek to this location, but save the previous stream pointer.
|
||||
const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
|
||||
db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
|
||||
// FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
|
||||
// I really ought to improve StreamReader to work with 64 bit indices exclusively.
|
||||
|
||||
// continue conversion after allocating the required storage
|
||||
DNA::FactoryPair builders = db.dna.GetBlobToStructureConverter(s,db);
|
||||
if (!builders.first) {
|
||||
// this might happen if DNA::RegisterConverters hasn't been called so far
|
||||
// or if the target type is not contained in `our` DNA.
|
||||
out.reset();
|
||||
ASSIMP_LOG_WARN_F( "Failed to find a converter for the `",s.name,"` structure" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// allocate the object hull
|
||||
out = (s.*builders.first)();
|
||||
|
||||
// cache the object immediately to prevent infinite recursion in a
|
||||
// circular list with a single element (i.e. a self-referencing element).
|
||||
db.cache(out).set(s,out,ptrval);
|
||||
|
||||
// and do the actual conversion
|
||||
(s.*builders.second)(out,db);
|
||||
db.reader->SetCurrentPos(pold);
|
||||
|
||||
// store a pointer to the name string of the actual type
|
||||
// in the object itself. This allows the conversion code
|
||||
// to perform additional type checking.
|
||||
out->dna_type = s.name.c_str();
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().pointers_resolved;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
const FileBlockHead* Structure :: LocateFileBlockForAddress(const Pointer & ptrval, const FileDatabase& db) const
|
||||
{
|
||||
// the file blocks appear in list sorted by
|
||||
// with ascending base addresses so we can run a
|
||||
// binary search to locate the pointer quickly.
|
||||
|
||||
// NOTE: Blender seems to distinguish between side-by-side
|
||||
// data (stored in the same data block) and far pointers,
|
||||
// which are only used for structures starting with an ID.
|
||||
// We don't need to make this distinction, our algorithm
|
||||
// works regardless where the data is stored.
|
||||
vector<FileBlockHead>::const_iterator it = std::lower_bound(db.entries.begin(),db.entries.end(),ptrval);
|
||||
if (it == db.entries.end()) {
|
||||
// this is crucial, pointers may not be invalid.
|
||||
// this is either a corrupted file or an attempted attack.
|
||||
throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x",
|
||||
std::hex,ptrval.val,", no file block falls into this address range"
|
||||
));
|
||||
}
|
||||
if (ptrval.val >= (*it).address.val + (*it).size) {
|
||||
throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x",
|
||||
std::hex,ptrval.val,", nearest file block starting at 0x",
|
||||
(*it).address.val," ends at 0x",
|
||||
(*it).address.val + (*it).size
|
||||
));
|
||||
}
|
||||
return &*it;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// NOTE: The MSVC debugger keeps showing up this annoying `a cast to a smaller data type has
|
||||
// caused a loss of data`-warning. Avoid this warning by a masking with an appropriate bitmask.
|
||||
|
||||
template <typename T> struct signless;
|
||||
template <> struct signless<char> {typedef unsigned char type;};
|
||||
template <> struct signless<short> {typedef unsigned short type;};
|
||||
template <> struct signless<int> {typedef unsigned int type;};
|
||||
template <> struct signless<unsigned char> { typedef unsigned char type; };
|
||||
template <typename T>
|
||||
struct static_cast_silent {
|
||||
template <typename V>
|
||||
T operator()(V in) {
|
||||
return static_cast<T>(in & static_cast<typename signless<T>::type>(-1));
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct static_cast_silent<float> {
|
||||
template <typename V> float operator()(V in) {
|
||||
return static_cast<float> (in);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct static_cast_silent<double> {
|
||||
template <typename V> double operator()(V in) {
|
||||
return static_cast<double>(in);
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <typename T> inline void ConvertDispatcher(T& out, const Structure& in,const FileDatabase& db)
|
||||
{
|
||||
if (in.name == "int") {
|
||||
out = static_cast_silent<T>()(db.reader->GetU4());
|
||||
}
|
||||
else if (in.name == "short") {
|
||||
out = static_cast_silent<T>()(db.reader->GetU2());
|
||||
}
|
||||
else if (in.name == "char") {
|
||||
out = static_cast_silent<T>()(db.reader->GetU1());
|
||||
}
|
||||
else if (in.name == "float") {
|
||||
out = static_cast<T>(db.reader->GetF4());
|
||||
}
|
||||
else if (in.name == "double") {
|
||||
out = static_cast<T>(db.reader->GetF8());
|
||||
}
|
||||
else {
|
||||
throw DeadlyImportError("Unknown source for conversion to primitive data type: "+in.name);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <> inline void Structure :: Convert<int> (int& dest,const FileDatabase& db) const
|
||||
{
|
||||
ConvertDispatcher(dest,*this,db);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template<> inline void Structure :: Convert<short> (short& dest,const FileDatabase& db) const
|
||||
{
|
||||
// automatic rescaling from short to float and vice versa (seems to be used by normals)
|
||||
if (name == "float") {
|
||||
float f = db.reader->GetF4();
|
||||
if ( f > 1.0f )
|
||||
f = 1.0f;
|
||||
dest = static_cast<short>( f * 32767.f);
|
||||
//db.reader->IncPtr(-4);
|
||||
return;
|
||||
}
|
||||
else if (name == "double") {
|
||||
dest = static_cast<short>(db.reader->GetF8() * 32767.);
|
||||
//db.reader->IncPtr(-8);
|
||||
return;
|
||||
}
|
||||
ConvertDispatcher(dest,*this,db);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <> inline void Structure :: Convert<char> (char& dest,const FileDatabase& db) const
|
||||
{
|
||||
// automatic rescaling from char to float and vice versa (seems useful for RGB colors)
|
||||
if (name == "float") {
|
||||
dest = static_cast<char>(db.reader->GetF4() * 255.f);
|
||||
return;
|
||||
}
|
||||
else if (name == "double") {
|
||||
dest = static_cast<char>(db.reader->GetF8() * 255.f);
|
||||
return;
|
||||
}
|
||||
ConvertDispatcher(dest,*this,db);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <> inline void Structure::Convert<unsigned char>(unsigned char& dest, const FileDatabase& db) const
|
||||
{
|
||||
// automatic rescaling from char to float and vice versa (seems useful for RGB colors)
|
||||
if (name == "float") {
|
||||
dest = static_cast<unsigned char>(db.reader->GetF4() * 255.f);
|
||||
return;
|
||||
}
|
||||
else if (name == "double") {
|
||||
dest = static_cast<unsigned char>(db.reader->GetF8() * 255.f);
|
||||
return;
|
||||
}
|
||||
ConvertDispatcher(dest, *this, db);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const
|
||||
{
|
||||
// automatic rescaling from char to float and vice versa (seems useful for RGB colors)
|
||||
if (name == "char") {
|
||||
dest = db.reader->GetI1() / 255.f;
|
||||
return;
|
||||
}
|
||||
// automatic rescaling from short to float and vice versa (used by normals)
|
||||
else if (name == "short") {
|
||||
dest = db.reader->GetI2() / 32767.f;
|
||||
return;
|
||||
}
|
||||
ConvertDispatcher(dest,*this,db);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const
|
||||
{
|
||||
if (name == "char") {
|
||||
dest = db.reader->GetI1() / 255.;
|
||||
return;
|
||||
}
|
||||
else if (name == "short") {
|
||||
dest = db.reader->GetI2() / 32767.;
|
||||
return;
|
||||
}
|
||||
ConvertDispatcher(dest,*this,db);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const
|
||||
{
|
||||
if (db.i64bit) {
|
||||
dest.val = db.reader->GetU8();
|
||||
//db.reader->IncPtr(-8);
|
||||
return;
|
||||
}
|
||||
dest.val = db.reader->GetU4();
|
||||
//db.reader->IncPtr(-4);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
const Structure& DNA :: operator [] (const std::string& ss) const
|
||||
{
|
||||
std::map<std::string, size_t>::const_iterator it = indices.find(ss);
|
||||
if (it == indices.end()) {
|
||||
throw Error((Formatter::format(),
|
||||
"BlendDNA: Did not find a structure named `",ss,"`"
|
||||
));
|
||||
}
|
||||
|
||||
return structures[(*it).second];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
const Structure* DNA :: Get (const std::string& ss) const
|
||||
{
|
||||
std::map<std::string, size_t>::const_iterator it = indices.find(ss);
|
||||
return it == indices.end() ? NULL : &structures[(*it).second];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
const Structure& DNA :: operator [] (const size_t i) const
|
||||
{
|
||||
if (i >= structures.size()) {
|
||||
throw Error((Formatter::format(),
|
||||
"BlendDNA: There is no structure with index `",i,"`"
|
||||
));
|
||||
}
|
||||
|
||||
return structures[i];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <template <typename> class TOUT> template <typename T> void ObjectCache<TOUT> :: get (
|
||||
const Structure& s,
|
||||
TOUT<T>& out,
|
||||
const Pointer& ptr
|
||||
) const {
|
||||
|
||||
if(s.cache_idx == static_cast<size_t>(-1)) {
|
||||
s.cache_idx = db.next_cache_idx++;
|
||||
caches.resize(db.next_cache_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
typename StructureCache::const_iterator it = caches[s.cache_idx].find(ptr);
|
||||
if (it != caches[s.cache_idx].end()) {
|
||||
out = std::static_pointer_cast<T>( (*it).second );
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().cache_hits;
|
||||
#endif
|
||||
}
|
||||
// otherwise, out remains untouched
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <template <typename> class TOUT> template <typename T> void ObjectCache<TOUT> :: set (
|
||||
const Structure& s,
|
||||
const TOUT<T>& out,
|
||||
const Pointer& ptr
|
||||
) {
|
||||
if(s.cache_idx == static_cast<size_t>(-1)) {
|
||||
s.cache_idx = db.next_cache_idx++;
|
||||
caches.resize(db.next_cache_idx);
|
||||
}
|
||||
caches[s.cache_idx][ptr] = std::static_pointer_cast<ElemBase>( out );
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().cached_objects;
|
||||
#endif
|
||||
}
|
||||
|
||||
}}
|
||||
#endif
|
||||
206
thirdparty/assimp/code/Blender/BlenderIntermediate.h
vendored
Normal file
206
thirdparty/assimp/code/Blender/BlenderIntermediate.h
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderIntermediate.h
|
||||
* @brief Internal utility structures for the BlenderLoader. It also serves
|
||||
* as master include file for the whole (internal) Blender subsystem.
|
||||
*/
|
||||
#ifndef INCLUDED_AI_BLEND_INTERMEDIATE_H
|
||||
#define INCLUDED_AI_BLEND_INTERMEDIATE_H
|
||||
|
||||
#include "BlenderLoader.h"
|
||||
#include "BlenderDNA.h"
|
||||
#include "BlenderScene.h"
|
||||
#include <deque>
|
||||
#include <assimp/material.h>
|
||||
|
||||
struct aiTexture;
|
||||
|
||||
namespace Assimp {
|
||||
namespace Blender {
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/** Mini smart-array to avoid pulling in even more boost stuff. usable with vector and deque */
|
||||
// --------------------------------------------------------------------
|
||||
template <template <typename,typename> class TCLASS, typename T>
|
||||
struct TempArray {
|
||||
typedef TCLASS< T*,std::allocator<T*> > mywrap;
|
||||
|
||||
TempArray() {
|
||||
}
|
||||
|
||||
~TempArray () {
|
||||
for(T* elem : arr) {
|
||||
delete elem;
|
||||
}
|
||||
}
|
||||
|
||||
void dismiss() {
|
||||
arr.clear();
|
||||
}
|
||||
|
||||
mywrap* operator -> () {
|
||||
return &arr;
|
||||
}
|
||||
|
||||
operator mywrap& () {
|
||||
return arr;
|
||||
}
|
||||
|
||||
operator const mywrap& () const {
|
||||
return arr;
|
||||
}
|
||||
|
||||
mywrap& get () {
|
||||
return arr;
|
||||
}
|
||||
|
||||
const mywrap& get () const {
|
||||
return arr;
|
||||
}
|
||||
|
||||
T* operator[] (size_t idx) const {
|
||||
return arr[idx];
|
||||
}
|
||||
|
||||
T*& operator[] (size_t idx) {
|
||||
return arr[idx];
|
||||
}
|
||||
|
||||
private:
|
||||
// no copy semantics
|
||||
void operator= (const TempArray&) {
|
||||
}
|
||||
|
||||
TempArray(const TempArray& /*arr*/) {
|
||||
}
|
||||
|
||||
private:
|
||||
mywrap arr;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(disable:4351)
|
||||
#endif
|
||||
|
||||
// As counter-intuitive as it may seem, a comparator must return false for equal values.
|
||||
// The C++ standard defines and expects this behavior: true if lhs < rhs, false otherwise.
|
||||
struct ObjectCompare {
|
||||
bool operator() (const Object* left, const Object* right) const {
|
||||
return ::strncmp(left->id.name, right->id.name, strlen( left->id.name ) ) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
// When keeping objects in sets, sort them by their name.
|
||||
typedef std::set<const Object*, ObjectCompare> ObjectSet;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/** ConversionData acts as intermediate storage location for
|
||||
* the various ConvertXXX routines in BlenderImporter.*/
|
||||
// --------------------------------------------------------------------
|
||||
struct ConversionData
|
||||
{
|
||||
ConversionData(const FileDatabase& db)
|
||||
: sentinel_cnt()
|
||||
, next_texture()
|
||||
, db(db)
|
||||
{}
|
||||
|
||||
// As counter-intuitive as it may seem, a comparator must return false for equal values.
|
||||
// The C++ standard defines and expects this behavior: true if lhs < rhs, false otherwise.
|
||||
struct ObjectCompare {
|
||||
bool operator() (const Object* left, const Object* right) const {
|
||||
return ::strncmp( left->id.name, right->id.name, strlen( left->id.name ) ) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
ObjectSet objects;
|
||||
|
||||
TempArray <std::vector, aiMesh> meshes;
|
||||
TempArray <std::vector, aiCamera> cameras;
|
||||
TempArray <std::vector, aiLight> lights;
|
||||
TempArray <std::vector, aiMaterial> materials;
|
||||
TempArray <std::vector, aiTexture> textures;
|
||||
|
||||
// set of all materials referenced by at least one mesh in the scene
|
||||
std::deque< std::shared_ptr< Material > > materials_raw;
|
||||
|
||||
// counter to name sentinel textures inserted as substitutes for procedural textures.
|
||||
unsigned int sentinel_cnt;
|
||||
|
||||
// next texture ID for each texture type, respectively
|
||||
unsigned int next_texture[aiTextureType_UNKNOWN+1];
|
||||
|
||||
// original file data
|
||||
const FileDatabase& db;
|
||||
};
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(default:4351)
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline const char* GetTextureTypeDisplayString(Tex::Type t)
|
||||
{
|
||||
switch (t) {
|
||||
case Tex::Type_CLOUDS : return "Clouds";
|
||||
case Tex::Type_WOOD : return "Wood";
|
||||
case Tex::Type_MARBLE : return "Marble";
|
||||
case Tex::Type_MAGIC : return "Magic";
|
||||
case Tex::Type_BLEND : return "Blend";
|
||||
case Tex::Type_STUCCI : return "Stucci";
|
||||
case Tex::Type_NOISE : return "Noise";
|
||||
case Tex::Type_PLUGIN : return "Plugin";
|
||||
case Tex::Type_MUSGRAVE : return "Musgrave";
|
||||
case Tex::Type_VORONOI : return "Voronoi";
|
||||
case Tex::Type_DISTNOISE : return "DistortedNoise";
|
||||
case Tex::Type_ENVMAP : return "EnvMap";
|
||||
case Tex::Type_IMAGE : return "Image";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "<Unknown>";
|
||||
}
|
||||
|
||||
} // ! Blender
|
||||
} // ! Assimp
|
||||
|
||||
#endif // ! INCLUDED_AI_BLEND_INTERMEDIATE_H
|
||||
1397
thirdparty/assimp/code/Blender/BlenderLoader.cpp
vendored
Normal file
1397
thirdparty/assimp/code/Blender/BlenderLoader.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
240
thirdparty/assimp/code/Blender/BlenderLoader.h
vendored
Normal file
240
thirdparty/assimp/code/Blender/BlenderLoader.h
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderLoader.h
|
||||
* @brief Declaration of the Blender 3D (*.blend) importer class.
|
||||
*/
|
||||
#ifndef INCLUDED_AI_BLEND_LOADER_H
|
||||
#define INCLUDED_AI_BLEND_LOADER_H
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/LogAux.h>
|
||||
#include <memory>
|
||||
|
||||
struct aiNode;
|
||||
struct aiMesh;
|
||||
struct aiLight;
|
||||
struct aiCamera;
|
||||
struct aiMaterial;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// BlenderDNA.h
|
||||
namespace Blender {
|
||||
class FileDatabase;
|
||||
struct ElemBase;
|
||||
}
|
||||
|
||||
// BlenderScene.h
|
||||
namespace Blender {
|
||||
struct Scene;
|
||||
struct Object;
|
||||
struct Mesh;
|
||||
struct Camera;
|
||||
struct Lamp;
|
||||
struct MTex;
|
||||
struct Image;
|
||||
struct Material;
|
||||
}
|
||||
|
||||
// BlenderIntermediate.h
|
||||
namespace Blender {
|
||||
struct ConversionData;
|
||||
template <template <typename,typename> class TCLASS, typename T> struct TempArray;
|
||||
}
|
||||
|
||||
// BlenderModifier.h
|
||||
namespace Blender {
|
||||
class BlenderModifierShowcase;
|
||||
class BlenderModifier;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
/** Load blenders official binary format. The actual file structure (the `DNA` how they
|
||||
* call it is outsourced to BlenderDNA.cpp/BlenderDNA.h. This class only performs the
|
||||
* conversion from intermediate format to aiScene. */
|
||||
// -------------------------------------------------------------------------------------------
|
||||
class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter>
|
||||
{
|
||||
public:
|
||||
BlenderImporter();
|
||||
~BlenderImporter();
|
||||
|
||||
public:
|
||||
|
||||
// --------------------
|
||||
bool CanRead( const std::string& pFile,
|
||||
IOSystem* pIOHandler,
|
||||
bool checkSig
|
||||
) const;
|
||||
|
||||
protected:
|
||||
|
||||
// --------------------
|
||||
const aiImporterDesc* GetInfo () const;
|
||||
|
||||
// --------------------
|
||||
void GetExtensionList(std::set<std::string>& app);
|
||||
|
||||
// --------------------
|
||||
void SetupProperties(const Importer* pImp);
|
||||
|
||||
// --------------------
|
||||
void InternReadFile( const std::string& pFile,
|
||||
aiScene* pScene,
|
||||
IOSystem* pIOHandler
|
||||
);
|
||||
|
||||
// --------------------
|
||||
void ParseBlendFile(Blender::FileDatabase& out,
|
||||
std::shared_ptr<IOStream> stream
|
||||
);
|
||||
|
||||
// --------------------
|
||||
void ExtractScene(Blender::Scene& out,
|
||||
const Blender::FileDatabase& file
|
||||
);
|
||||
|
||||
// --------------------
|
||||
void ConvertBlendFile(aiScene* out,
|
||||
const Blender::Scene& in,
|
||||
const Blender::FileDatabase& file
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
// --------------------
|
||||
aiNode* ConvertNode(const Blender::Scene& in,
|
||||
const Blender::Object* obj,
|
||||
Blender::ConversionData& conv_info,
|
||||
const aiMatrix4x4& parentTransform
|
||||
);
|
||||
|
||||
// --------------------
|
||||
void ConvertMesh(const Blender::Scene& in,
|
||||
const Blender::Object* obj,
|
||||
const Blender::Mesh* mesh,
|
||||
Blender::ConversionData& conv_data,
|
||||
Blender::TempArray<std::vector,aiMesh>& temp
|
||||
);
|
||||
|
||||
// --------------------
|
||||
aiLight* ConvertLight(const Blender::Scene& in,
|
||||
const Blender::Object* obj,
|
||||
const Blender::Lamp* mesh,
|
||||
Blender::ConversionData& conv_data
|
||||
);
|
||||
|
||||
// --------------------
|
||||
aiCamera* ConvertCamera(const Blender::Scene& in,
|
||||
const Blender::Object* obj,
|
||||
const Blender::Camera* mesh,
|
||||
Blender::ConversionData& conv_data
|
||||
);
|
||||
|
||||
// --------------------
|
||||
void BuildDefaultMaterial(
|
||||
Blender::ConversionData& conv_data
|
||||
);
|
||||
|
||||
void AddBlendParams(
|
||||
aiMaterial* result,
|
||||
const Blender::Material* source
|
||||
);
|
||||
|
||||
void BuildMaterials(
|
||||
Blender::ConversionData& conv_data
|
||||
);
|
||||
|
||||
// --------------------
|
||||
void ResolveTexture(
|
||||
aiMaterial* out,
|
||||
const Blender::Material* mat,
|
||||
const Blender::MTex* tex,
|
||||
Blender::ConversionData& conv_data
|
||||
);
|
||||
|
||||
// --------------------
|
||||
void ResolveImage(
|
||||
aiMaterial* out,
|
||||
const Blender::Material* mat,
|
||||
const Blender::MTex* tex,
|
||||
const Blender::Image* img,
|
||||
Blender::ConversionData& conv_data
|
||||
);
|
||||
|
||||
void AddSentinelTexture(
|
||||
aiMaterial* out,
|
||||
const Blender::Material* mat,
|
||||
const Blender::MTex* tex,
|
||||
Blender::ConversionData& conv_data
|
||||
);
|
||||
|
||||
private: // static stuff, mostly logging and error reporting.
|
||||
|
||||
// --------------------
|
||||
static void CheckActualType(const Blender::ElemBase* dt,
|
||||
const char* check
|
||||
);
|
||||
|
||||
// --------------------
|
||||
static void NotSupportedObjectType(const Blender::Object* obj,
|
||||
const char* type
|
||||
);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Blender::BlenderModifierShowcase* modifier_cache;
|
||||
|
||||
}; // !class BlenderImporter
|
||||
|
||||
} // end of namespace Assimp
|
||||
#endif // AI_UNREALIMPORTER_H_INC
|
||||
299
thirdparty/assimp/code/Blender/BlenderModifier.cpp
vendored
Normal file
299
thirdparty/assimp/code/Blender/BlenderModifier.cpp
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderModifier.cpp
|
||||
* @brief Implementation of some blender modifiers (i.e subdivision, mirror).
|
||||
*/
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
|
||||
#include "BlenderModifier.h"
|
||||
#include <assimp/SceneCombiner.h>
|
||||
#include <assimp/Subdivision.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <memory>
|
||||
|
||||
#include <functional>
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Blender;
|
||||
|
||||
template <typename T> BlenderModifier* god() {
|
||||
return new T();
|
||||
}
|
||||
|
||||
// add all available modifiers here
|
||||
typedef BlenderModifier* (*fpCreateModifier)();
|
||||
static const fpCreateModifier creators[] = {
|
||||
&god<BlenderModifier_Mirror>,
|
||||
&god<BlenderModifier_Subdivision>,
|
||||
|
||||
NULL // sentinel
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
struct SharedModifierData : ElemBase
|
||||
{
|
||||
ModifierData modifier;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object )
|
||||
{
|
||||
size_t cnt = 0u, ful = 0u;
|
||||
|
||||
// NOTE: this cast is potentially unsafe by design, so we need to perform type checks before
|
||||
// we're allowed to dereference the pointers without risking to crash. We might still be
|
||||
// invoking UB btw - we're assuming that the ModifierData member of the respective modifier
|
||||
// structures is at offset sizeof(vftable) with no padding.
|
||||
const SharedModifierData* cur = static_cast<const SharedModifierData *> ( orig_object.modifiers.first.get() );
|
||||
for (; cur; cur = static_cast<const SharedModifierData *> ( cur->modifier.next.get() ), ++ful) {
|
||||
ai_assert(cur->dna_type);
|
||||
|
||||
const Structure* s = conv_data.db.dna.Get( cur->dna_type );
|
||||
if (!s) {
|
||||
ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
// this is a common trait of all XXXMirrorData structures in BlenderDNA
|
||||
const Field* f = s->Get("modifier");
|
||||
if (!f || f->offset != 0) {
|
||||
ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0");
|
||||
continue;
|
||||
}
|
||||
|
||||
s = conv_data.db.dna.Get( f->type );
|
||||
if (!s || s->name != "ModifierData") {
|
||||
ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member");
|
||||
continue;
|
||||
}
|
||||
|
||||
// now, we can be sure that we should be fine to dereference *cur* as
|
||||
// ModifierData (with the above note).
|
||||
const ModifierData& dat = cur->modifier;
|
||||
|
||||
const fpCreateModifier* curgod = creators;
|
||||
std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end();
|
||||
|
||||
for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly
|
||||
if (curmod == endmod) {
|
||||
cached_modifiers->push_back((*curgod)());
|
||||
|
||||
endmod = cached_modifiers->end();
|
||||
curmod = endmod-1;
|
||||
}
|
||||
|
||||
BlenderModifier* const modifier = *curmod;
|
||||
if(modifier->IsActive(dat)) {
|
||||
modifier->DoIt(out,conv_data,*static_cast<const ElemBase *>(cur),in,orig_object);
|
||||
cnt++;
|
||||
|
||||
curgod = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (curgod) {
|
||||
ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name);
|
||||
}
|
||||
}
|
||||
|
||||
// Even though we managed to resolve some or all of the modifiers on this
|
||||
// object, we still can't say whether our modifier implementations were
|
||||
// able to fully do their job.
|
||||
if (ful) {
|
||||
ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name,
|
||||
"`, check log messages above for errors");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool BlenderModifier_Mirror :: IsActive (const ModifierData& modin)
|
||||
{
|
||||
return modin.type == ModifierData::eModifierType_Mirror;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
|
||||
const Scene& /*in*/,
|
||||
const Object& orig_object )
|
||||
{
|
||||
// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
|
||||
const MirrorModifierData& mir = static_cast<const MirrorModifierData&>(orig_modifier);
|
||||
ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
|
||||
|
||||
conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes);
|
||||
|
||||
// XXX not entirely correct, mirroring on two axes results in 4 distinct objects in blender ...
|
||||
|
||||
// take all input meshes and clone them
|
||||
for (unsigned int i = 0; i < out.mNumMeshes; ++i) {
|
||||
aiMesh* mesh;
|
||||
SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]);
|
||||
|
||||
const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f;
|
||||
const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
|
||||
const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f;
|
||||
|
||||
if (mir.mirror_ob) {
|
||||
const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] );
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D& v = mesh->mVertices[i];
|
||||
|
||||
v.x = center.x + xs*(center.x - v.x);
|
||||
v.y = center.y + ys*(center.y - v.y);
|
||||
v.z = center.z + zs*(center.z - v.z);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D& v = mesh->mVertices[i];
|
||||
v.x *= xs;v.y *= ys;v.z *= zs;
|
||||
}
|
||||
}
|
||||
|
||||
if (mesh->mNormals) {
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D& v = mesh->mNormals[i];
|
||||
v.x *= xs;v.y *= ys;v.z *= zs;
|
||||
}
|
||||
}
|
||||
|
||||
if (mesh->mTangents) {
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D& v = mesh->mTangents[i];
|
||||
v.x *= xs;v.y *= ys;v.z *= zs;
|
||||
}
|
||||
}
|
||||
|
||||
if (mesh->mBitangents) {
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D& v = mesh->mBitangents[i];
|
||||
v.x *= xs;v.y *= ys;v.z *= zs;
|
||||
}
|
||||
}
|
||||
|
||||
const float us = mir.flag & MirrorModifierData::Flags_MIRROR_U ? -1.f : 1.f;
|
||||
const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f;
|
||||
|
||||
for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) {
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D& v = mesh->mTextureCoords[n][i];
|
||||
v.x *= us;v.y *= vs;
|
||||
}
|
||||
}
|
||||
|
||||
// Only reverse the winding order if an odd number of axes were mirrored.
|
||||
if (xs * ys * zs < 0) {
|
||||
for( unsigned int i = 0; i < mesh->mNumFaces; i++) {
|
||||
aiFace& face = mesh->mFaces[i];
|
||||
for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
|
||||
std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
|
||||
}
|
||||
}
|
||||
|
||||
conv_data.meshes->push_back(mesh);
|
||||
}
|
||||
unsigned int* nind = new unsigned int[out.mNumMeshes*2];
|
||||
|
||||
std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind);
|
||||
std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes,
|
||||
[&out](unsigned int n) { return out.mNumMeshes + n; });
|
||||
|
||||
delete[] out.mMeshes;
|
||||
out.mMeshes = nind;
|
||||
out.mNumMeshes *= 2;
|
||||
|
||||
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `",
|
||||
orig_object.id.name,"`");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin)
|
||||
{
|
||||
return modin.type == ModifierData::eModifierType_Subsurf;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
|
||||
const Scene& /*in*/,
|
||||
const Object& orig_object )
|
||||
{
|
||||
// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
|
||||
const SubsurfModifierData& mir = static_cast<const SubsurfModifierData&>(orig_modifier);
|
||||
ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf);
|
||||
|
||||
Subdivider::Algorithm algo;
|
||||
switch (mir.subdivType)
|
||||
{
|
||||
case SubsurfModifierData::TYPE_CatmullClarke:
|
||||
algo = Subdivider::CATMULL_CLARKE;
|
||||
break;
|
||||
|
||||
case SubsurfModifierData::TYPE_Simple:
|
||||
ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke");
|
||||
algo = Subdivider::CATMULL_CLARKE;
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType);
|
||||
return;
|
||||
};
|
||||
|
||||
std::unique_ptr<Subdivider> subd(Subdivider::Create(algo));
|
||||
ai_assert(subd);
|
||||
if ( conv_data.meshes->empty() ) {
|
||||
return;
|
||||
}
|
||||
aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
|
||||
std::unique_ptr<aiMesh*[]> tempmeshes(new aiMesh*[out.mNumMeshes]());
|
||||
|
||||
subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true);
|
||||
std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes);
|
||||
|
||||
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `",
|
||||
orig_object.id.name,"`");
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
155
thirdparty/assimp/code/Blender/BlenderModifier.h
vendored
Normal file
155
thirdparty/assimp/code/Blender/BlenderModifier.h
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderModifier.h
|
||||
* @brief Declare dedicated helper classes to simulate some blender modifiers (i.e. mirror)
|
||||
*/
|
||||
#ifndef INCLUDED_AI_BLEND_MODIFIER_H
|
||||
#define INCLUDED_AI_BLEND_MODIFIER_H
|
||||
|
||||
#include "BlenderIntermediate.h"
|
||||
|
||||
namespace Assimp {
|
||||
namespace Blender {
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Dummy base class for all blender modifiers. Modifiers are reused between imports, so
|
||||
* they should be stateless and not try to cache model data.
|
||||
*/
|
||||
// -------------------------------------------------------------------------------------------
|
||||
class BlenderModifier {
|
||||
public:
|
||||
/**
|
||||
* The class destructor, virtual.
|
||||
*/
|
||||
virtual ~BlenderModifier() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// --------------------
|
||||
/**
|
||||
* Check if *this* modifier is active, given a ModifierData& block.
|
||||
*/
|
||||
virtual bool IsActive( const ModifierData& /*modin*/) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// --------------------
|
||||
/**
|
||||
* Apply the modifier to a given output node. The original data used
|
||||
* to construct the node is given as well. Not called unless IsActive()
|
||||
* was called and gave positive response.
|
||||
*/
|
||||
virtual void DoIt(aiNode& /*out*/,
|
||||
ConversionData& /*conv_data*/,
|
||||
const ElemBase& orig_modifier,
|
||||
const Scene& /*in*/,
|
||||
const Object& /*orig_object*/
|
||||
) {
|
||||
ASSIMP_LOG_INFO_F("This modifier is not supported, skipping: ",orig_modifier.dna_type );
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Manage all known modifiers and instance and apply them if necessary
|
||||
*/
|
||||
// -------------------------------------------------------------------------------------------
|
||||
class BlenderModifierShowcase {
|
||||
public:
|
||||
// --------------------
|
||||
/** Apply all requested modifiers provided we support them. */
|
||||
void ApplyModifiers(aiNode& out,
|
||||
ConversionData& conv_data,
|
||||
const Scene& in,
|
||||
const Object& orig_object
|
||||
);
|
||||
|
||||
private:
|
||||
TempArray< std::vector,BlenderModifier > cached_modifiers;
|
||||
};
|
||||
|
||||
// MODIFIERS /////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Mirror modifier. Status: implemented.
|
||||
*/
|
||||
// -------------------------------------------------------------------------------------------
|
||||
class BlenderModifier_Mirror : public BlenderModifier {
|
||||
public:
|
||||
// --------------------
|
||||
virtual bool IsActive( const ModifierData& modin);
|
||||
|
||||
// --------------------
|
||||
virtual void DoIt(aiNode& out,
|
||||
ConversionData& conv_data,
|
||||
const ElemBase& orig_modifier,
|
||||
const Scene& in,
|
||||
const Object& orig_object
|
||||
) ;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
/** Subdivision modifier. Status: dummy. */
|
||||
// -------------------------------------------------------------------------------------------
|
||||
class BlenderModifier_Subdivision : public BlenderModifier {
|
||||
public:
|
||||
|
||||
// --------------------
|
||||
virtual bool IsActive( const ModifierData& modin);
|
||||
|
||||
// --------------------
|
||||
virtual void DoIt(aiNode& out,
|
||||
ConversionData& conv_data,
|
||||
const ElemBase& orig_modifier,
|
||||
const Scene& in,
|
||||
const Object& orig_object
|
||||
) ;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !INCLUDED_AI_BLEND_MODIFIER_H
|
||||
875
thirdparty/assimp/code/Blender/BlenderScene.cpp
vendored
Normal file
875
thirdparty/assimp/code/Blender/BlenderScene.cpp
vendored
Normal file
@@ -0,0 +1,875 @@
|
||||
/*
|
||||
Open Asset Import Library (ASSIMP)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2016, ASSIMP Development Team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the ASSIMP team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the ASSIMP Development Team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderScene.cpp
|
||||
* @brief MACHINE GENERATED BY ./scripts/BlenderImporter/genblenddna.py
|
||||
*/
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
|
||||
#include "BlenderScene.h"
|
||||
#include "BlenderSceneGen.h"
|
||||
#include "BlenderDNA.h"
|
||||
#include "BlenderCustomData.h"
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Blender;
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<Object> (
|
||||
Object& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
int temp = 0;
|
||||
ReadField<ErrorPolicy_Fail>(temp,"type",db);
|
||||
dest.type = static_cast<Assimp::Blender::Object::Type>(temp);
|
||||
ReadFieldArray2<ErrorPolicy_Warn>(dest.obmat,"obmat",db);
|
||||
ReadFieldArray2<ErrorPolicy_Warn>(dest.parentinv,"parentinv",db);
|
||||
ReadFieldArray<ErrorPolicy_Warn>(dest.parsubstr,"parsubstr",db);
|
||||
{
|
||||
std::shared_ptr<Object> parent;
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(parent,"*parent",db);
|
||||
dest.parent = parent.get();
|
||||
}
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.track,"*track",db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.proxy,"*proxy",db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.proxy_from,"*proxy_from",db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.proxy_group,"*proxy_group",db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.dup_group,"*dup_group",db);
|
||||
ReadFieldPtr<ErrorPolicy_Fail>(dest.data,"*data",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.modifiers,"modifiers",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<Group> (
|
||||
Group& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.layer,"layer",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.gobject,"*gobject",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MTex> (
|
||||
MTex& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
int temp_short = 0;
|
||||
ReadField<ErrorPolicy_Igno>(temp_short,"mapto",db);
|
||||
dest.mapto = static_cast<Assimp::Blender::MTex::MapType>(temp_short);
|
||||
int temp = 0;
|
||||
ReadField<ErrorPolicy_Igno>(temp,"blendtype",db);
|
||||
dest.blendtype = static_cast<Assimp::Blender::MTex::BlendType>(temp);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.object,"*object",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.tex,"*tex",db);
|
||||
ReadFieldArray<ErrorPolicy_Igno>(dest.uvname,"uvname",db);
|
||||
ReadField<ErrorPolicy_Igno>(temp,"projx",db);
|
||||
dest.projx = static_cast<Assimp::Blender::MTex::Projection>(temp);
|
||||
ReadField<ErrorPolicy_Igno>(temp,"projy",db);
|
||||
dest.projy = static_cast<Assimp::Blender::MTex::Projection>(temp);
|
||||
ReadField<ErrorPolicy_Igno>(temp,"projz",db);
|
||||
dest.projz = static_cast<Assimp::Blender::MTex::Projection>(temp);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mapping,"mapping",db);
|
||||
ReadFieldArray<ErrorPolicy_Igno>(dest.ofs,"ofs",db);
|
||||
ReadFieldArray<ErrorPolicy_Igno>(dest.size,"size",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.rot,"rot",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.texflag,"texflag",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.colormodel,"colormodel",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pmapto,"pmapto",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pmaptoneg,"pmaptoneg",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.r,"r",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.g,"g",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.b,"b",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.k,"k",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.colspecfac,"colspecfac",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mirrfac,"mirrfac",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.alphafac,"alphafac",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.difffac,"difffac",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.specfac,"specfac",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.emitfac,"emitfac",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.hardfac,"hardfac",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.norfac,"norfac",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<TFace> (
|
||||
TFace& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadFieldArray2<ErrorPolicy_Fail>(dest.uv,"uv",db);
|
||||
ReadFieldArray<ErrorPolicy_Fail>(dest.col,"col",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<SubsurfModifierData> (
|
||||
SubsurfModifierData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.modifier,"modifier",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.subdivType,"subdivType",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.levels,"levels",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.renderLevels,"renderLevels",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MFace> (
|
||||
MFace& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.v1,"v1",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.v2,"v2",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.v3,"v3",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.v4,"v4",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.mat_nr,"mat_nr",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<Lamp> (
|
||||
Lamp& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
int temp = 0;
|
||||
ReadField<ErrorPolicy_Fail>(temp,"type",db);
|
||||
dest.type = static_cast<Assimp::Blender::Lamp::Type>(temp);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flags,"flag",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.colormodel,"colormodel",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.totex,"totex",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.r,"r",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.g,"g",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.b,"b",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.k,"k",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.energy,"energy",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.dist,"dist",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.spotsize,"spotsize",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.spotblend,"spotblend",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.constant_coefficient, "coeff_const", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.linear_coefficient, "coeff_lin", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.quadratic_coefficient, "coeff_quad", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.att1,"att1",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db);
|
||||
ReadField<ErrorPolicy_Igno>(temp,"falloff_type",db);
|
||||
dest.falloff_type = static_cast<Assimp::Blender::Lamp::FalloffType>(temp);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sun_brightness,"sun_brightness",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.area_size,"area_size",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.area_sizey,"area_sizey",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.area_sizez,"area_sizez",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.area_shape,"area_shape",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MDeformWeight> (
|
||||
MDeformWeight& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.def_nr,"def_nr",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.weight,"weight",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<PackedFile> (
|
||||
PackedFile& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Warn>(dest.size,"size",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.seek,"seek",db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.data,"*data",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<Base> (
|
||||
Base& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
// note: as per https://github.com/assimp/assimp/issues/128,
|
||||
// reading the Object linked list recursively is prone to stack overflow.
|
||||
// This structure converter is therefore an hand-written exception that
|
||||
// does it iteratively.
|
||||
|
||||
const int initial_pos = db.reader->GetCurrentPos();
|
||||
|
||||
std::pair<Base*, int> todo = std::make_pair(&dest, initial_pos);
|
||||
for ( ;; ) {
|
||||
|
||||
Base& cur_dest = *todo.first;
|
||||
db.reader->SetCurrentPos(todo.second);
|
||||
|
||||
// we know that this is a double-linked, circular list which we never
|
||||
// traverse backwards, so don't bother resolving the back links.
|
||||
cur_dest.prev = NULL;
|
||||
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.object,"*object",db);
|
||||
|
||||
// the return value of ReadFieldPtr indicates whether the object
|
||||
// was already cached. In this case, we don't need to resolve
|
||||
// it again.
|
||||
if(!ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.next,"*next",db, true) && cur_dest.next) {
|
||||
todo = std::make_pair(&*cur_dest.next, db.reader->GetCurrentPos());
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
db.reader->SetCurrentPos(initial_pos + size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MTFace> (
|
||||
MTFace& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadFieldArray2<ErrorPolicy_Fail>(dest.uv,"uv",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<Material> (
|
||||
Material& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.r,"r",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.g,"g",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.b,"b",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.specr,"specr",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.specg,"specg",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.specb,"specb",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.har,"har",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.ambr,"ambr",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.ambg,"ambg",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.ambb,"ambb",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mirr,"mirr",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mirg,"mirg",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mirb,"mirb",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.emit,"emit",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.ray_mirror,"ray_mirror",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.alpha,"alpha",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.ref,"ref",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.translucency,"translucency",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.roughness,"roughness",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.darkness,"darkness",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.refrac,"refrac",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.group,"*group",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.diff_shader,"diff_shader",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.spec_shader,"spec_shader",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.mtex,"*mtex",db);
|
||||
|
||||
|
||||
ReadField<ErrorPolicy_Igno>(dest.amb, "amb", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.ang, "ang", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.spectra, "spectra", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.spec, "spec", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.zoffs, "zoffs", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.add, "add", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.fresnel_mir, "fresnel_mir", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.fresnel_mir_i, "fresnel_mir_i", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.fresnel_tra, "fresnel_tra", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.fresnel_tra_i, "fresnel_tra_i", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.filter, "filter", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.tx_limit, "tx_limit", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.tx_falloff, "tx_falloff", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.gloss_mir, "gloss_mir", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.gloss_tra, "gloss_tra", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.adapt_thresh_mir, "adapt_thresh_mir", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.adapt_thresh_tra, "adapt_thresh_tra", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.aniso_gloss_mir, "aniso_gloss_mir", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.dist_mir, "dist_mir", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.hasize, "hasize", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flaresize, "flaresize", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.subsize, "subsize", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flareboost, "flareboost", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.strand_sta, "strand_sta", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.strand_end, "strand_end", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.strand_ease, "strand_ease", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.strand_surfnor, "strand_surfnor", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.strand_min, "strand_min", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.strand_widthfade, "strand_widthfade", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sbias, "sbias", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.lbias, "lbias", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.shad_alpha, "shad_alpha", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.param, "param", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.rms, "rms", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.rampfac_col, "rampfac_col", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.rampfac_spec, "rampfac_spec", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.friction, "friction", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.fh, "fh", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.reflect, "reflect", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.fhdist, "fhdist", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.xyfrict, "xyfrict", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sss_radius, "sss_radius", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sss_col, "sss_col", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sss_error, "sss_error", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sss_scale, "sss_scale", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sss_ior, "sss_ior", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sss_colfac, "sss_colfac", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sss_texfac, "sss_texfac", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sss_front, "sss_front", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sss_back, "sss_back", db);
|
||||
|
||||
ReadField<ErrorPolicy_Igno>(dest.material_type, "material_type", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flag, "flag", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.ray_depth, "ray_depth", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.ray_depth_tra, "ray_depth_tra", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.samp_gloss_mir, "samp_gloss_mir", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.samp_gloss_tra, "samp_gloss_tra", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.fadeto_mir, "fadeto_mir", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.shade_flag, "shade_flag", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flarec, "flarec", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.starc, "starc", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.linec, "linec", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.ringc, "ringc", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pr_lamp, "pr_lamp", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pr_texture, "pr_texture", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.ml_flag, "ml_flag", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.diff_shader, "diff_shader", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.spec_shader, "spec_shader", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.texco, "texco", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mapto, "mapto", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.ramp_show, "ramp_show", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pad3, "pad3", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.dynamode, "dynamode", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pad2, "pad2", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sss_flag, "sss_flag", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sss_preset, "sss_preset", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.shadowonly_flag, "shadowonly_flag", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.index, "index", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.vcol_alpha, "vcol_alpha", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pad4, "pad4", db);
|
||||
|
||||
ReadField<ErrorPolicy_Igno>(dest.seed1, "seed1", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.seed2, "seed2", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MTexPoly> (
|
||||
MTexPoly& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
{
|
||||
std::shared_ptr<Image> tpage;
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(tpage,"*tpage",db);
|
||||
dest.tpage = tpage.get();
|
||||
}
|
||||
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.transp,"transp",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<Mesh> (
|
||||
Mesh& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.totface,"totface",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.totedge,"totedge",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.totvert,"totvert",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.totloop,"totloop",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.totpoly,"totpoly",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.subdiv,"subdiv",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.subdivr,"subdivr",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.subsurftype,"subsurftype",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.smoothresh,"smoothresh",db);
|
||||
ReadFieldPtr<ErrorPolicy_Fail>(dest.mface,"*mface",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.mtface,"*mtface",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.tface,"*tface",db);
|
||||
ReadFieldPtr<ErrorPolicy_Fail>(dest.mvert,"*mvert",db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.medge,"*medge",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.mloop,"*mloop",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.mloopuv,"*mloopuv",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.mloopcol,"*mloopcol",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.mpoly,"*mpoly",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.mtpoly,"*mtpoly",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.dvert,"*dvert",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
|
||||
ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
|
||||
|
||||
ReadField<ErrorPolicy_Igno>(dest.vdata, "vdata", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.edata, "edata", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.fdata, "fdata", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pdata, "pdata", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.ldata, "ldata", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MDeformVert> (
|
||||
MDeformVert& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.dw,"*dw",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.totweight,"totweight",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<World> (
|
||||
World& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MLoopCol> (
|
||||
MLoopCol& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Igno>(dest.r,"r",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.g,"g",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.b,"b",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.a,"a",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MVert> (
|
||||
MVert& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadFieldArray<ErrorPolicy_Fail>(dest.co,"co",db);
|
||||
ReadFieldArray<ErrorPolicy_Fail>(dest.no,"no",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
|
||||
//ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MEdge> (
|
||||
MEdge& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.v1,"v1",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.v2,"v2",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.crease,"crease",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MLoopUV> (
|
||||
MLoopUV& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadFieldArray<ErrorPolicy_Igno>(dest.uv,"uv",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<GroupObject> (
|
||||
GroupObject& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadFieldPtr<ErrorPolicy_Fail>(dest.prev,"*prev",db);
|
||||
ReadFieldPtr<ErrorPolicy_Fail>(dest.next,"*next",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.ob,"*ob",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<ListBase> (
|
||||
ListBase& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.first,"*first",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.last,"*last",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MLoop> (
|
||||
MLoop& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Igno>(dest.v,"v",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.e,"e",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<ModifierData> (
|
||||
ModifierData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.next,"*next",db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.prev,"*prev",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.type,"type",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
|
||||
ReadFieldArray<ErrorPolicy_Igno>(dest.name,"name",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<ID> (
|
||||
ID& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MCol> (
|
||||
MCol& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.r,"r",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.g,"g",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.b,"b",db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.a,"a",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MPoly> (
|
||||
MPoly& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Igno>(dest.loopstart,"loopstart",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.totloop,"totloop",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mat_nr,"mat_nr",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<Scene> (
|
||||
Scene& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.camera,"*camera",db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.world,"*world",db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.basact,"*basact",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.base,"base",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<Library> (
|
||||
Library& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
|
||||
ReadFieldArray<ErrorPolicy_Fail>(dest.filename,"filename",db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.parent,"*parent",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<Tex> (
|
||||
Tex& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
short temp_short = 0;
|
||||
ReadField<ErrorPolicy_Igno>(temp_short,"imaflag",db);
|
||||
dest.imaflag = static_cast<Assimp::Blender::Tex::ImageFlags>(temp_short);
|
||||
int temp = 0;
|
||||
ReadField<ErrorPolicy_Fail>(temp,"type",db);
|
||||
dest.type = static_cast<Assimp::Blender::Tex::Type>(temp);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.ima,"*ima",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<Camera> (
|
||||
Camera& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
int temp = 0;
|
||||
ReadField<ErrorPolicy_Warn>(temp,"type",db);
|
||||
dest.type = static_cast<Assimp::Blender::Camera::Type>(temp);
|
||||
ReadField<ErrorPolicy_Warn>(temp,"flag",db);
|
||||
dest.flag = static_cast<Assimp::Blender::Camera::Type>(temp);
|
||||
ReadField<ErrorPolicy_Warn>(dest.lens,"lens",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.sensor_x,"sensor_x",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.clipsta,"clipsta",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.clipend,"clipend",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<MirrorModifierData> (
|
||||
MirrorModifierData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.modifier,"modifier",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.axis,"axis",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.tolerance,"tolerance",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.mirror_ob,"*mirror_ob",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: Convert<Image> (
|
||||
Image& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.ok,"ok",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.source,"source",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.type,"type",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pad1,"pad1",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.lastframe,"lastframe",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.tpageflag,"tpageflag",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.totbind,"totbind",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.xrep,"xrep",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.yrep,"yrep",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.twsta,"twsta",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.twend,"twend",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.packedfile,"*packedfile",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.lastupdate,"lastupdate",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.lastused,"lastused",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.animspeed,"animspeed",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.gen_x,"gen_x",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.gen_y,"gen_y",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.gen_type,"gen_type",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure::Convert<CustomData>(
|
||||
CustomData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
ReadFieldArray<ErrorPolicy_Warn>(dest.typemap, "typemap", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.totlayer, "totlayer", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.maxlayer, "maxlayer", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.totsize, "totsize", db);
|
||||
ReadFieldPtrVector<ErrorPolicy_Warn>(dest.layers, "*layers", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure::Convert<CustomDataLayer>(
|
||||
CustomDataLayer& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
ReadField<ErrorPolicy_Fail>(dest.type, "type", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.offset, "offset", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.flag, "flag", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.active, "active", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.active_rnd, "active_rnd", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.active_clone, "active_clone", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.active_mask, "active_mask", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.uid, "uid", db);
|
||||
ReadFieldArray<ErrorPolicy_Warn>(dest.name, "name", db);
|
||||
ReadCustomDataPtr<ErrorPolicy_Fail>(dest.data, dest.type, "*data", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
void DNA::RegisterConverters() {
|
||||
|
||||
converters["Object"] = DNA::FactoryPair( &Structure::Allocate<Object>, &Structure::Convert<Object> );
|
||||
converters["Group"] = DNA::FactoryPair( &Structure::Allocate<Group>, &Structure::Convert<Group> );
|
||||
converters["MTex"] = DNA::FactoryPair( &Structure::Allocate<MTex>, &Structure::Convert<MTex> );
|
||||
converters["TFace"] = DNA::FactoryPair( &Structure::Allocate<TFace>, &Structure::Convert<TFace> );
|
||||
converters["SubsurfModifierData"] = DNA::FactoryPair( &Structure::Allocate<SubsurfModifierData>, &Structure::Convert<SubsurfModifierData> );
|
||||
converters["MFace"] = DNA::FactoryPair( &Structure::Allocate<MFace>, &Structure::Convert<MFace> );
|
||||
converters["Lamp"] = DNA::FactoryPair( &Structure::Allocate<Lamp>, &Structure::Convert<Lamp> );
|
||||
converters["MDeformWeight"] = DNA::FactoryPair( &Structure::Allocate<MDeformWeight>, &Structure::Convert<MDeformWeight> );
|
||||
converters["PackedFile"] = DNA::FactoryPair( &Structure::Allocate<PackedFile>, &Structure::Convert<PackedFile> );
|
||||
converters["Base"] = DNA::FactoryPair( &Structure::Allocate<Base>, &Structure::Convert<Base> );
|
||||
converters["MTFace"] = DNA::FactoryPair( &Structure::Allocate<MTFace>, &Structure::Convert<MTFace> );
|
||||
converters["Material"] = DNA::FactoryPair( &Structure::Allocate<Material>, &Structure::Convert<Material> );
|
||||
converters["MTexPoly"] = DNA::FactoryPair( &Structure::Allocate<MTexPoly>, &Structure::Convert<MTexPoly> );
|
||||
converters["Mesh"] = DNA::FactoryPair( &Structure::Allocate<Mesh>, &Structure::Convert<Mesh> );
|
||||
converters["MDeformVert"] = DNA::FactoryPair( &Structure::Allocate<MDeformVert>, &Structure::Convert<MDeformVert> );
|
||||
converters["World"] = DNA::FactoryPair( &Structure::Allocate<World>, &Structure::Convert<World> );
|
||||
converters["MLoopCol"] = DNA::FactoryPair( &Structure::Allocate<MLoopCol>, &Structure::Convert<MLoopCol> );
|
||||
converters["MVert"] = DNA::FactoryPair( &Structure::Allocate<MVert>, &Structure::Convert<MVert> );
|
||||
converters["MEdge"] = DNA::FactoryPair( &Structure::Allocate<MEdge>, &Structure::Convert<MEdge> );
|
||||
converters["MLoopUV"] = DNA::FactoryPair( &Structure::Allocate<MLoopUV>, &Structure::Convert<MLoopUV> );
|
||||
converters["GroupObject"] = DNA::FactoryPair( &Structure::Allocate<GroupObject>, &Structure::Convert<GroupObject> );
|
||||
converters["ListBase"] = DNA::FactoryPair( &Structure::Allocate<ListBase>, &Structure::Convert<ListBase> );
|
||||
converters["MLoop"] = DNA::FactoryPair( &Structure::Allocate<MLoop>, &Structure::Convert<MLoop> );
|
||||
converters["ModifierData"] = DNA::FactoryPair( &Structure::Allocate<ModifierData>, &Structure::Convert<ModifierData> );
|
||||
converters["ID"] = DNA::FactoryPair( &Structure::Allocate<ID>, &Structure::Convert<ID> );
|
||||
converters["MCol"] = DNA::FactoryPair( &Structure::Allocate<MCol>, &Structure::Convert<MCol> );
|
||||
converters["MPoly"] = DNA::FactoryPair( &Structure::Allocate<MPoly>, &Structure::Convert<MPoly> );
|
||||
converters["Scene"] = DNA::FactoryPair( &Structure::Allocate<Scene>, &Structure::Convert<Scene> );
|
||||
converters["Library"] = DNA::FactoryPair( &Structure::Allocate<Library>, &Structure::Convert<Library> );
|
||||
converters["Tex"] = DNA::FactoryPair( &Structure::Allocate<Tex>, &Structure::Convert<Tex> );
|
||||
converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> );
|
||||
converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> );
|
||||
converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
|
||||
converters["CustomData"] = DNA::FactoryPair(&Structure::Allocate<CustomData>, &Structure::Convert<CustomData>);
|
||||
converters["CustomDataLayer"] = DNA::FactoryPair(&Structure::Allocate<CustomDataLayer>, &Structure::Convert<CustomDataLayer>);
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
|
||||
983
thirdparty/assimp/code/Blender/BlenderScene.h
vendored
Normal file
983
thirdparty/assimp/code/Blender/BlenderScene.h
vendored
Normal file
@@ -0,0 +1,983 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderScene.h
|
||||
* @brief Intermediate representation of a BLEND scene.
|
||||
*/
|
||||
#ifndef INCLUDED_AI_BLEND_SCENE_H
|
||||
#define INCLUDED_AI_BLEND_SCENE_H
|
||||
|
||||
#include "BlenderDNA.h"
|
||||
|
||||
namespace Assimp {
|
||||
namespace Blender {
|
||||
|
||||
// Minor parts of this file are extracts from blender data structures,
|
||||
// declared in the ./source/blender/makesdna directory.
|
||||
// Stuff that is not used by Assimp is commented.
|
||||
|
||||
|
||||
// NOTE
|
||||
// this file serves as input data to the `./scripts/genblenddna.py`
|
||||
// script. This script generates the actual binding code to read a
|
||||
// blender file with a possibly different DNA into our structures.
|
||||
// Only `struct` declarations are considered and the following
|
||||
// rules must be obeyed in order for the script to work properly:
|
||||
//
|
||||
// * C++ style comments only
|
||||
//
|
||||
// * Structures may include the primitive types char, int, short,
|
||||
// float, double. Signed specifiers are not allowed on
|
||||
// integers. Enum types are allowed, but they must have been
|
||||
// defined in this header.
|
||||
//
|
||||
// * Structures may aggregate other structures, unless not defined
|
||||
// in this header.
|
||||
//
|
||||
// * Pointers to other structures or primitive types are allowed.
|
||||
// No references or double pointers or arrays of pointers.
|
||||
// A pointer to a T is normally written as std::shared_ptr, while a
|
||||
// pointer to an array of elements is written as boost::
|
||||
// shared_array. To avoid cyclic pointers, use raw pointers in
|
||||
// one direction.
|
||||
//
|
||||
// * Arrays can have maximally two-dimensions. Any non-pointer
|
||||
// type can form them.
|
||||
//
|
||||
// * Multiple fields can be declare in a single line (i.e `int a,b;`)
|
||||
// provided they are neither pointers nor arrays.
|
||||
//
|
||||
// * One of WARN, FAIL can be appended to the declaration (
|
||||
// prior to the semicolon to specify the error handling policy if
|
||||
// this field is missing in the input DNA). If none of those
|
||||
// is specified the default policy is to substitute a default
|
||||
// value for the field.
|
||||
//
|
||||
|
||||
// warn if field is missing, substitute default value
|
||||
#ifdef WARN
|
||||
# undef WARN
|
||||
#endif
|
||||
#define WARN
|
||||
|
||||
// fail the import if the field does not exist
|
||||
#ifdef FAIL
|
||||
# undef FAIL
|
||||
#endif
|
||||
#define FAIL
|
||||
|
||||
struct Object;
|
||||
struct MTex;
|
||||
struct Image;
|
||||
|
||||
#include <memory>
|
||||
|
||||
#define AI_BLEND_MESH_MAX_VERTS 2000000000L
|
||||
|
||||
static const size_t MaxNameLen = 1024;
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct ID : ElemBase {
|
||||
char name[ MaxNameLen ] WARN;
|
||||
short flag;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct ListBase : ElemBase {
|
||||
std::shared_ptr<ElemBase> first;
|
||||
std::shared_ptr<ElemBase> last;
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct PackedFile : ElemBase {
|
||||
int size WARN;
|
||||
int seek WARN;
|
||||
std::shared_ptr< FileOffset > data WARN;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct GroupObject : ElemBase {
|
||||
std::shared_ptr<GroupObject> prev,next FAIL;
|
||||
std::shared_ptr<Object> ob;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Group : ElemBase {
|
||||
ID id FAIL;
|
||||
int layer;
|
||||
|
||||
std::shared_ptr<GroupObject> gobject;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct World : ElemBase {
|
||||
ID id FAIL;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MVert : ElemBase {
|
||||
float co[3] FAIL;
|
||||
float no[3] FAIL; // readed as short and divided through / 32767.f
|
||||
char flag;
|
||||
int mat_nr WARN;
|
||||
int bweight;
|
||||
|
||||
MVert() : ElemBase()
|
||||
, flag(0)
|
||||
, mat_nr(0)
|
||||
, bweight(0)
|
||||
{}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MEdge : ElemBase {
|
||||
int v1, v2 FAIL;
|
||||
char crease, bweight;
|
||||
short flag;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MLoop : ElemBase {
|
||||
int v, e;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MLoopUV : ElemBase {
|
||||
float uv[2];
|
||||
int flag;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Note that red and blue are not swapped, as with MCol
|
||||
struct MLoopCol : ElemBase {
|
||||
unsigned char r, g, b, a;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MPoly : ElemBase {
|
||||
int loopstart;
|
||||
int totloop;
|
||||
short mat_nr;
|
||||
char flag;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MTexPoly : ElemBase {
|
||||
Image* tpage;
|
||||
char flag, transp;
|
||||
short mode, tile, pad;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MCol : ElemBase {
|
||||
char r,g,b,a FAIL;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MFace : ElemBase {
|
||||
int v1,v2,v3,v4 FAIL;
|
||||
int mat_nr FAIL;
|
||||
char flag;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct TFace : ElemBase {
|
||||
float uv[4][2] FAIL;
|
||||
int col[4] FAIL;
|
||||
char flag;
|
||||
short mode;
|
||||
short tile;
|
||||
short unwrap;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MTFace : ElemBase {
|
||||
MTFace()
|
||||
: flag(0)
|
||||
, mode(0)
|
||||
, tile(0)
|
||||
, unwrap(0)
|
||||
{
|
||||
}
|
||||
|
||||
float uv[4][2] FAIL;
|
||||
char flag;
|
||||
short mode;
|
||||
short tile;
|
||||
short unwrap;
|
||||
|
||||
// std::shared_ptr<Image> tpage;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MDeformWeight : ElemBase {
|
||||
int def_nr FAIL;
|
||||
float weight FAIL;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MDeformVert : ElemBase {
|
||||
vector<MDeformWeight> dw WARN;
|
||||
int totweight;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
#define MA_RAYMIRROR 0x40000
|
||||
#define MA_TRANSPARENCY 0x10000
|
||||
#define MA_RAYTRANSP 0x20000
|
||||
#define MA_ZTRANSP 0x00040
|
||||
|
||||
struct Material : ElemBase {
|
||||
ID id FAIL;
|
||||
|
||||
float r,g,b WARN;
|
||||
float specr,specg,specb WARN;
|
||||
short har;
|
||||
float ambr,ambg,ambb WARN;
|
||||
float mirr,mirg,mirb;
|
||||
float emit WARN;
|
||||
float ray_mirror;
|
||||
float alpha WARN;
|
||||
float ref;
|
||||
float translucency;
|
||||
int mode;
|
||||
float roughness;
|
||||
float darkness;
|
||||
float refrac;
|
||||
|
||||
float amb;
|
||||
float ang;
|
||||
float spectra;
|
||||
float spec;
|
||||
float zoffs;
|
||||
float add;
|
||||
float fresnel_mir;
|
||||
float fresnel_mir_i;
|
||||
float fresnel_tra;
|
||||
float fresnel_tra_i;
|
||||
float filter;
|
||||
float tx_limit;
|
||||
float tx_falloff;
|
||||
float gloss_mir;
|
||||
float gloss_tra;
|
||||
float adapt_thresh_mir;
|
||||
float adapt_thresh_tra;
|
||||
float aniso_gloss_mir;
|
||||
float dist_mir;
|
||||
float hasize;
|
||||
float flaresize;
|
||||
float subsize;
|
||||
float flareboost;
|
||||
float strand_sta;
|
||||
float strand_end;
|
||||
float strand_ease;
|
||||
float strand_surfnor;
|
||||
float strand_min;
|
||||
float strand_widthfade;
|
||||
float sbias;
|
||||
float lbias;
|
||||
float shad_alpha;
|
||||
float param;
|
||||
float rms;
|
||||
float rampfac_col;
|
||||
float rampfac_spec;
|
||||
float friction;
|
||||
float fh;
|
||||
float reflect;
|
||||
float fhdist;
|
||||
float xyfrict;
|
||||
float sss_radius;
|
||||
float sss_col;
|
||||
float sss_error;
|
||||
float sss_scale;
|
||||
float sss_ior;
|
||||
float sss_colfac;
|
||||
float sss_texfac;
|
||||
float sss_front;
|
||||
float sss_back;
|
||||
|
||||
short material_type;
|
||||
short flag;
|
||||
short ray_depth;
|
||||
short ray_depth_tra;
|
||||
short samp_gloss_mir;
|
||||
short samp_gloss_tra;
|
||||
short fadeto_mir;
|
||||
short shade_flag;
|
||||
short flarec;
|
||||
short starc;
|
||||
short linec;
|
||||
short ringc;
|
||||
short pr_lamp;
|
||||
short pr_texture;
|
||||
short ml_flag;
|
||||
short texco;
|
||||
short mapto;
|
||||
short ramp_show;
|
||||
short pad3;
|
||||
short dynamode;
|
||||
short pad2;
|
||||
short sss_flag;
|
||||
short sss_preset;
|
||||
short shadowonly_flag;
|
||||
short index;
|
||||
short vcol_alpha;
|
||||
short pad4;
|
||||
|
||||
char seed1;
|
||||
char seed2;
|
||||
|
||||
std::shared_ptr<Group> group;
|
||||
|
||||
short diff_shader WARN;
|
||||
short spec_shader WARN;
|
||||
|
||||
std::shared_ptr<MTex> mtex[18];
|
||||
};
|
||||
|
||||
/*
|
||||
CustomDataLayer 104
|
||||
|
||||
int type 0 4
|
||||
int offset 4 4
|
||||
int flag 8 4
|
||||
int active 12 4
|
||||
int active_rnd 16 4
|
||||
int active_clone 20 4
|
||||
int active_mask 24 4
|
||||
int uid 28 4
|
||||
char name 32 64
|
||||
void *data 96 8
|
||||
*/
|
||||
struct CustomDataLayer : ElemBase {
|
||||
int type;
|
||||
int offset;
|
||||
int flag;
|
||||
int active;
|
||||
int active_rnd;
|
||||
int active_clone;
|
||||
int active_mask;
|
||||
int uid;
|
||||
char name[64];
|
||||
std::shared_ptr<ElemBase> data; // must be converted to real type according type member
|
||||
|
||||
CustomDataLayer()
|
||||
: ElemBase()
|
||||
, type(0)
|
||||
, offset(0)
|
||||
, flag(0)
|
||||
, active(0)
|
||||
, active_rnd(0)
|
||||
, active_clone(0)
|
||||
, active_mask(0)
|
||||
, uid(0)
|
||||
, data(nullptr)
|
||||
{
|
||||
memset(name, 0, sizeof name);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
CustomData 208
|
||||
|
||||
CustomDataLayer *layers 0 8
|
||||
int typemap 8 168
|
||||
int pad_i1 176 4
|
||||
int totlayer 180 4
|
||||
int maxlayer 184 4
|
||||
int totsize 188 4
|
||||
BLI_mempool *pool 192 8
|
||||
CustomDataExternal *external 200 8
|
||||
*/
|
||||
struct CustomData : ElemBase {
|
||||
vector<std::shared_ptr<struct CustomDataLayer> > layers;
|
||||
int typemap[42]; // CD_NUMTYPES
|
||||
int totlayer;
|
||||
int maxlayer;
|
||||
int totsize;
|
||||
/*
|
||||
std::shared_ptr<BLI_mempool> pool;
|
||||
std::shared_ptr<CustomDataExternal> external;
|
||||
*/
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Mesh : ElemBase {
|
||||
ID id FAIL;
|
||||
|
||||
int totface FAIL;
|
||||
int totedge FAIL;
|
||||
int totvert FAIL;
|
||||
int totloop;
|
||||
int totpoly;
|
||||
|
||||
short subdiv;
|
||||
short subdivr;
|
||||
short subsurftype;
|
||||
short smoothresh;
|
||||
|
||||
vector<MFace> mface FAIL;
|
||||
vector<MTFace> mtface;
|
||||
vector<TFace> tface;
|
||||
vector<MVert> mvert FAIL;
|
||||
vector<MEdge> medge WARN;
|
||||
vector<MLoop> mloop;
|
||||
vector<MLoopUV> mloopuv;
|
||||
vector<MLoopCol> mloopcol;
|
||||
vector<MPoly> mpoly;
|
||||
vector<MTexPoly> mtpoly;
|
||||
vector<MDeformVert> dvert;
|
||||
vector<MCol> mcol;
|
||||
|
||||
vector< std::shared_ptr<Material> > mat FAIL;
|
||||
|
||||
struct CustomData vdata;
|
||||
struct CustomData edata;
|
||||
struct CustomData fdata;
|
||||
struct CustomData pdata;
|
||||
struct CustomData ldata;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Library : ElemBase {
|
||||
ID id FAIL;
|
||||
|
||||
char name[240] WARN;
|
||||
char filename[240] FAIL;
|
||||
std::shared_ptr<Library> parent WARN;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Camera : ElemBase {
|
||||
enum Type {
|
||||
Type_PERSP = 0
|
||||
,Type_ORTHO = 1
|
||||
};
|
||||
|
||||
ID id FAIL;
|
||||
|
||||
Type type,flag WARN;
|
||||
float lens WARN;
|
||||
float sensor_x WARN;
|
||||
float clipsta, clipend;
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Lamp : ElemBase {
|
||||
|
||||
enum FalloffType {
|
||||
FalloffType_Constant = 0x0
|
||||
,FalloffType_InvLinear = 0x1
|
||||
,FalloffType_InvSquare = 0x2
|
||||
//,FalloffType_Curve = 0x3
|
||||
//,FalloffType_Sliders = 0x4
|
||||
};
|
||||
|
||||
enum Type {
|
||||
Type_Local = 0x0
|
||||
,Type_Sun = 0x1
|
||||
,Type_Spot = 0x2
|
||||
,Type_Hemi = 0x3
|
||||
,Type_Area = 0x4
|
||||
//,Type_YFPhoton = 0x5
|
||||
};
|
||||
|
||||
ID id FAIL;
|
||||
//AnimData *adt;
|
||||
|
||||
Type type FAIL;
|
||||
short flags;
|
||||
|
||||
//int mode;
|
||||
|
||||
short colormodel, totex;
|
||||
float r,g,b,k WARN;
|
||||
//float shdwr, shdwg, shdwb;
|
||||
|
||||
float energy, dist, spotsize, spotblend;
|
||||
//float haint;
|
||||
|
||||
float constant_coefficient;
|
||||
float linear_coefficient;
|
||||
float quadratic_coefficient;
|
||||
|
||||
float att1, att2;
|
||||
//struct CurveMapping *curfalloff;
|
||||
FalloffType falloff_type;
|
||||
|
||||
//float clipsta, clipend, shadspotsize;
|
||||
//float bias, soft, compressthresh;
|
||||
//short bufsize, samp, buffers, filtertype;
|
||||
//char bufflag, buftype;
|
||||
|
||||
//short ray_samp, ray_sampy, ray_sampz;
|
||||
//short ray_samp_type;
|
||||
short area_shape;
|
||||
float area_size, area_sizey, area_sizez;
|
||||
//float adapt_thresh;
|
||||
//short ray_samp_method;
|
||||
|
||||
//short texact, shadhalostep;
|
||||
|
||||
//short sun_effect_type;
|
||||
//short skyblendtype;
|
||||
//float horizon_brightness;
|
||||
//float spread;
|
||||
float sun_brightness;
|
||||
//float sun_size;
|
||||
//float backscattered_light;
|
||||
//float sun_intensity;
|
||||
//float atm_turbidity;
|
||||
//float atm_inscattering_factor;
|
||||
//float atm_extinction_factor;
|
||||
//float atm_distance_factor;
|
||||
//float skyblendfac;
|
||||
//float sky_exposure;
|
||||
//short sky_colorspace;
|
||||
|
||||
// int YF_numphotons, YF_numsearch;
|
||||
// short YF_phdepth, YF_useqmc, YF_bufsize, YF_pad;
|
||||
// float YF_causticblur, YF_ltradius;
|
||||
|
||||
// float YF_glowint, YF_glowofs;
|
||||
// short YF_glowtype, YF_pad2;
|
||||
|
||||
//struct Ipo *ipo;
|
||||
//struct MTex *mtex[18];
|
||||
// short pr_texture;
|
||||
|
||||
//struct PreviewImage *preview;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct ModifierData : ElemBase {
|
||||
enum ModifierType {
|
||||
eModifierType_None = 0,
|
||||
eModifierType_Subsurf,
|
||||
eModifierType_Lattice,
|
||||
eModifierType_Curve,
|
||||
eModifierType_Build,
|
||||
eModifierType_Mirror,
|
||||
eModifierType_Decimate,
|
||||
eModifierType_Wave,
|
||||
eModifierType_Armature,
|
||||
eModifierType_Hook,
|
||||
eModifierType_Softbody,
|
||||
eModifierType_Boolean,
|
||||
eModifierType_Array,
|
||||
eModifierType_EdgeSplit,
|
||||
eModifierType_Displace,
|
||||
eModifierType_UVProject,
|
||||
eModifierType_Smooth,
|
||||
eModifierType_Cast,
|
||||
eModifierType_MeshDeform,
|
||||
eModifierType_ParticleSystem,
|
||||
eModifierType_ParticleInstance,
|
||||
eModifierType_Explode,
|
||||
eModifierType_Cloth,
|
||||
eModifierType_Collision,
|
||||
eModifierType_Bevel,
|
||||
eModifierType_Shrinkwrap,
|
||||
eModifierType_Fluidsim,
|
||||
eModifierType_Mask,
|
||||
eModifierType_SimpleDeform,
|
||||
eModifierType_Multires,
|
||||
eModifierType_Surface,
|
||||
eModifierType_Smoke,
|
||||
eModifierType_ShapeKey
|
||||
};
|
||||
|
||||
std::shared_ptr<ElemBase> next WARN;
|
||||
std::shared_ptr<ElemBase> prev WARN;
|
||||
|
||||
int type, mode;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct SubsurfModifierData : ElemBase {
|
||||
|
||||
enum Type {
|
||||
|
||||
TYPE_CatmullClarke = 0x0,
|
||||
TYPE_Simple = 0x1
|
||||
};
|
||||
|
||||
enum Flags {
|
||||
// some omitted
|
||||
FLAGS_SubsurfUV =1<<3
|
||||
};
|
||||
|
||||
ModifierData modifier FAIL;
|
||||
short subdivType WARN;
|
||||
short levels FAIL;
|
||||
short renderLevels ;
|
||||
short flags;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MirrorModifierData : ElemBase {
|
||||
|
||||
enum Flags {
|
||||
Flags_CLIPPING =1<<0,
|
||||
Flags_MIRROR_U =1<<1,
|
||||
Flags_MIRROR_V =1<<2,
|
||||
Flags_AXIS_X =1<<3,
|
||||
Flags_AXIS_Y =1<<4,
|
||||
Flags_AXIS_Z =1<<5,
|
||||
Flags_VGROUP =1<<6
|
||||
};
|
||||
|
||||
ModifierData modifier FAIL;
|
||||
|
||||
short axis, flag;
|
||||
float tolerance;
|
||||
std::shared_ptr<Object> mirror_ob;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Object : ElemBase {
|
||||
ID id FAIL;
|
||||
|
||||
enum Type {
|
||||
Type_EMPTY = 0
|
||||
,Type_MESH = 1
|
||||
,Type_CURVE = 2
|
||||
,Type_SURF = 3
|
||||
,Type_FONT = 4
|
||||
,Type_MBALL = 5
|
||||
|
||||
,Type_LAMP = 10
|
||||
,Type_CAMERA = 11
|
||||
|
||||
,Type_WAVE = 21
|
||||
,Type_LATTICE = 22
|
||||
};
|
||||
|
||||
Type type FAIL;
|
||||
float obmat[4][4] WARN;
|
||||
float parentinv[4][4] WARN;
|
||||
char parsubstr[32] WARN;
|
||||
|
||||
Object* parent WARN;
|
||||
std::shared_ptr<Object> track WARN;
|
||||
|
||||
std::shared_ptr<Object> proxy,proxy_from,proxy_group WARN;
|
||||
std::shared_ptr<Group> dup_group WARN;
|
||||
std::shared_ptr<ElemBase> data FAIL;
|
||||
|
||||
ListBase modifiers;
|
||||
|
||||
Object()
|
||||
: ElemBase()
|
||||
, type( Type_EMPTY )
|
||||
, parent( nullptr )
|
||||
, track()
|
||||
, proxy()
|
||||
, proxy_from()
|
||||
, data() {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Base : ElemBase {
|
||||
Base* prev WARN;
|
||||
std::shared_ptr<Base> next WARN;
|
||||
std::shared_ptr<Object> object WARN;
|
||||
|
||||
Base()
|
||||
: ElemBase()
|
||||
, prev( nullptr )
|
||||
, next()
|
||||
, object() {
|
||||
// empty
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Scene : ElemBase {
|
||||
ID id FAIL;
|
||||
|
||||
std::shared_ptr<Object> camera WARN;
|
||||
std::shared_ptr<World> world WARN;
|
||||
std::shared_ptr<Base> basact WARN;
|
||||
|
||||
ListBase base;
|
||||
|
||||
Scene()
|
||||
: ElemBase()
|
||||
, camera()
|
||||
, world()
|
||||
, basact() {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Image : ElemBase {
|
||||
ID id FAIL;
|
||||
|
||||
char name[240] WARN;
|
||||
|
||||
//struct anim *anim;
|
||||
|
||||
short ok, flag;
|
||||
short source, type, pad, pad1;
|
||||
int lastframe;
|
||||
|
||||
short tpageflag, totbind;
|
||||
short xrep, yrep;
|
||||
short twsta, twend;
|
||||
//unsigned int bindcode;
|
||||
//unsigned int *repbind;
|
||||
|
||||
std::shared_ptr<PackedFile> packedfile;
|
||||
//struct PreviewImage * preview;
|
||||
|
||||
float lastupdate;
|
||||
int lastused;
|
||||
short animspeed;
|
||||
|
||||
short gen_x, gen_y, gen_type;
|
||||
|
||||
Image()
|
||||
: ElemBase() {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Tex : ElemBase {
|
||||
|
||||
// actually, the only texture type we support is Type_IMAGE
|
||||
enum Type {
|
||||
Type_CLOUDS = 1
|
||||
,Type_WOOD = 2
|
||||
,Type_MARBLE = 3
|
||||
,Type_MAGIC = 4
|
||||
,Type_BLEND = 5
|
||||
,Type_STUCCI = 6
|
||||
,Type_NOISE = 7
|
||||
,Type_IMAGE = 8
|
||||
,Type_PLUGIN = 9
|
||||
,Type_ENVMAP = 10
|
||||
,Type_MUSGRAVE = 11
|
||||
,Type_VORONOI = 12
|
||||
,Type_DISTNOISE = 13
|
||||
,Type_POINTDENSITY = 14
|
||||
,Type_VOXELDATA = 15
|
||||
};
|
||||
|
||||
enum ImageFlags {
|
||||
ImageFlags_INTERPOL = 1
|
||||
,ImageFlags_USEALPHA = 2
|
||||
,ImageFlags_MIPMAP = 4
|
||||
,ImageFlags_IMAROT = 16
|
||||
,ImageFlags_CALCALPHA = 32
|
||||
,ImageFlags_NORMALMAP = 2048
|
||||
,ImageFlags_GAUSS_MIP = 4096
|
||||
,ImageFlags_FILTER_MIN = 8192
|
||||
,ImageFlags_DERIVATIVEMAP = 16384
|
||||
};
|
||||
|
||||
ID id FAIL;
|
||||
// AnimData *adt;
|
||||
|
||||
//float noisesize, turbul;
|
||||
//float bright, contrast, rfac, gfac, bfac;
|
||||
//float filtersize;
|
||||
|
||||
//float mg_H, mg_lacunarity, mg_octaves, mg_offset, mg_gain;
|
||||
//float dist_amount, ns_outscale;
|
||||
|
||||
//float vn_w1;
|
||||
//float vn_w2;
|
||||
//float vn_w3;
|
||||
//float vn_w4;
|
||||
//float vn_mexp;
|
||||
//short vn_distm, vn_coltype;
|
||||
|
||||
//short noisedepth, noisetype;
|
||||
//short noisebasis, noisebasis2;
|
||||
|
||||
//short flag;
|
||||
ImageFlags imaflag;
|
||||
Type type FAIL;
|
||||
//short stype;
|
||||
|
||||
//float cropxmin, cropymin, cropxmax, cropymax;
|
||||
//int texfilter;
|
||||
//int afmax;
|
||||
//short xrepeat, yrepeat;
|
||||
//short extend;
|
||||
|
||||
//short fie_ima;
|
||||
//int len;
|
||||
//int frames, offset, sfra;
|
||||
|
||||
//float checkerdist, nabla;
|
||||
//float norfac;
|
||||
|
||||
//ImageUser iuser;
|
||||
|
||||
//bNodeTree *nodetree;
|
||||
//Ipo *ipo;
|
||||
std::shared_ptr<Image> ima WARN;
|
||||
//PluginTex *plugin;
|
||||
//ColorBand *coba;
|
||||
//EnvMap *env;
|
||||
//PreviewImage * preview;
|
||||
//PointDensity *pd;
|
||||
//VoxelData *vd;
|
||||
|
||||
//char use_nodes;
|
||||
|
||||
Tex()
|
||||
: ElemBase()
|
||||
, imaflag( ImageFlags_INTERPOL )
|
||||
, type( Type_CLOUDS )
|
||||
, ima() {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MTex : ElemBase {
|
||||
|
||||
enum Projection {
|
||||
Proj_N = 0
|
||||
,Proj_X = 1
|
||||
,Proj_Y = 2
|
||||
,Proj_Z = 3
|
||||
};
|
||||
|
||||
enum Flag {
|
||||
Flag_RGBTOINT = 0x1
|
||||
,Flag_STENCIL = 0x2
|
||||
,Flag_NEGATIVE = 0x4
|
||||
,Flag_ALPHAMIX = 0x8
|
||||
,Flag_VIEWSPACE = 0x10
|
||||
};
|
||||
|
||||
enum BlendType {
|
||||
BlendType_BLEND = 0
|
||||
,BlendType_MUL = 1
|
||||
,BlendType_ADD = 2
|
||||
,BlendType_SUB = 3
|
||||
,BlendType_DIV = 4
|
||||
,BlendType_DARK = 5
|
||||
,BlendType_DIFF = 6
|
||||
,BlendType_LIGHT = 7
|
||||
,BlendType_SCREEN = 8
|
||||
,BlendType_OVERLAY = 9
|
||||
,BlendType_BLEND_HUE = 10
|
||||
,BlendType_BLEND_SAT = 11
|
||||
,BlendType_BLEND_VAL = 12
|
||||
,BlendType_BLEND_COLOR = 13
|
||||
};
|
||||
|
||||
enum MapType {
|
||||
MapType_COL = 1
|
||||
,MapType_NORM = 2
|
||||
,MapType_COLSPEC = 4
|
||||
,MapType_COLMIR = 8
|
||||
,MapType_REF = 16
|
||||
,MapType_SPEC = 32
|
||||
,MapType_EMIT = 64
|
||||
,MapType_ALPHA = 128
|
||||
,MapType_HAR = 256
|
||||
,MapType_RAYMIRR = 512
|
||||
,MapType_TRANSLU = 1024
|
||||
,MapType_AMB = 2048
|
||||
,MapType_DISPLACE = 4096
|
||||
,MapType_WARP = 8192
|
||||
};
|
||||
|
||||
// short texco, maptoneg;
|
||||
MapType mapto;
|
||||
|
||||
BlendType blendtype;
|
||||
std::shared_ptr<Object> object;
|
||||
std::shared_ptr<Tex> tex;
|
||||
char uvname[32];
|
||||
|
||||
Projection projx,projy,projz;
|
||||
char mapping;
|
||||
float ofs[3], size[3], rot;
|
||||
|
||||
int texflag;
|
||||
short colormodel, pmapto, pmaptoneg;
|
||||
//short normapspace, which_output;
|
||||
//char brush_map_mode;
|
||||
float r,g,b,k WARN;
|
||||
//float def_var, rt;
|
||||
|
||||
//float colfac, varfac;
|
||||
|
||||
float norfac;
|
||||
//float dispfac, warpfac;
|
||||
float colspecfac, mirrfac, alphafac;
|
||||
float difffac, specfac, emitfac, hardfac;
|
||||
//float raymirrfac, translfac, ambfac;
|
||||
//float colemitfac, colreflfac, coltransfac;
|
||||
//float densfac, scatterfac, reflfac;
|
||||
|
||||
//float timefac, lengthfac, clumpfac;
|
||||
//float kinkfac, roughfac, padensfac;
|
||||
//float lifefac, sizefac, ivelfac, pvelfac;
|
||||
//float shadowfac;
|
||||
//float zenupfac, zendownfac, blendfac;
|
||||
|
||||
MTex()
|
||||
: ElemBase() {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
266
thirdparty/assimp/code/Blender/BlenderSceneGen.h
vendored
Normal file
266
thirdparty/assimp/code/Blender/BlenderSceneGen.h
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
Open Asset Import Library (ASSIMP)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2016, ASSIMP Development Team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the ASSIMP team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the ASSIMP Development Team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderSceneGen.h
|
||||
* @brief MACHINE GENERATED BY ./scripts/BlenderImporter/genblenddna.py
|
||||
*/
|
||||
#ifndef INCLUDED_AI_BLEND_SCENEGEN_H
|
||||
#define INCLUDED_AI_BLEND_SCENEGEN_H
|
||||
|
||||
#include "BlenderDNA.h"
|
||||
#include "BlenderScene.h"
|
||||
|
||||
namespace Assimp {
|
||||
namespace Blender {
|
||||
|
||||
template <> void Structure :: Convert<Object> (
|
||||
Object& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Group> (
|
||||
Group& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MTex> (
|
||||
MTex& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<TFace> (
|
||||
TFace& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<SubsurfModifierData> (
|
||||
SubsurfModifierData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MFace> (
|
||||
MFace& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Lamp> (
|
||||
Lamp& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MDeformWeight> (
|
||||
MDeformWeight& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<PackedFile> (
|
||||
PackedFile& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Base> (
|
||||
Base& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MTFace> (
|
||||
MTFace& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Material> (
|
||||
Material& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MTexPoly> (
|
||||
MTexPoly& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Mesh> (
|
||||
Mesh& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MDeformVert> (
|
||||
MDeformVert& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<World> (
|
||||
World& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MLoopCol> (
|
||||
MLoopCol& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MVert> (
|
||||
MVert& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MEdge> (
|
||||
MEdge& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MLoopUV> (
|
||||
MLoopUV& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<GroupObject> (
|
||||
GroupObject& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<ListBase> (
|
||||
ListBase& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MLoop> (
|
||||
MLoop& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<ModifierData> (
|
||||
ModifierData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<ID> (
|
||||
ID& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MCol> (
|
||||
MCol& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MPoly> (
|
||||
MPoly& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Scene> (
|
||||
Scene& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Library> (
|
||||
Library& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Tex> (
|
||||
Tex& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Camera> (
|
||||
Camera& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MirrorModifierData> (
|
||||
MirrorModifierData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Image> (
|
||||
Image& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure::Convert<CustomData>(
|
||||
CustomData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure::Convert<CustomDataLayer>(
|
||||
CustomDataLayer& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
526
thirdparty/assimp/code/Blender/BlenderTessellator.cpp
vendored
Normal file
526
thirdparty/assimp/code/Blender/BlenderTessellator.cpp
vendored
Normal file
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderTessellator.cpp
|
||||
* @brief A simple tessellation wrapper
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
|
||||
#include "BlenderDNA.h"
|
||||
#include "BlenderScene.h"
|
||||
#include "BlenderBMesh.h"
|
||||
#include "BlenderTessellator.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
static const unsigned int BLEND_TESS_MAGIC = 0x83ed9ac3;
|
||||
|
||||
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
||||
|
||||
namspace Assimp
|
||||
{
|
||||
template< > const char* LogFunctions< BlenderTessellatorGL >::Prefix()
|
||||
{
|
||||
static auto prefix = "BLEND_TESS_GL: ";
|
||||
return prefix;
|
||||
}
|
||||
}
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Blender;
|
||||
|
||||
#ifndef CALLBACK
|
||||
#define CALLBACK
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BlenderTessellatorGL::BlenderTessellatorGL( BlenderBMeshConverter& converter ):
|
||||
converter( &converter )
|
||||
{
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BlenderTessellatorGL::~BlenderTessellatorGL( )
|
||||
{
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
|
||||
{
|
||||
AssertVertexCount( vertexCount );
|
||||
|
||||
std::vector< VertexGL > polyLoopGL;
|
||||
GenerateLoopVerts( polyLoopGL, polyLoop, vertexCount, vertices );
|
||||
|
||||
TessDataGL tessData;
|
||||
Tesssellate( polyLoopGL, tessData );
|
||||
|
||||
TriangulateDrawCalls( tessData );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::AssertVertexCount( int vertexCount )
|
||||
{
|
||||
if ( vertexCount <= 4 )
|
||||
{
|
||||
ThrowException( "Expected more than 4 vertices for tessellation" );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::GenerateLoopVerts( std::vector< VertexGL >& polyLoopGL, const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
|
||||
{
|
||||
for ( int i = 0; i < vertexCount; ++i )
|
||||
{
|
||||
const MLoop& loopItem = polyLoop[ i ];
|
||||
const MVert& vertex = vertices[ loopItem.v ];
|
||||
polyLoopGL.push_back( VertexGL( vertex.co[ 0 ], vertex.co[ 1 ], vertex.co[ 2 ], loopItem.v, BLEND_TESS_MAGIC ) );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::Tesssellate( std::vector< VertexGL >& polyLoopGL, TessDataGL& tessData )
|
||||
{
|
||||
GLUtesselator* tessellator = gluNewTess( );
|
||||
gluTessCallback( tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateBegin ) );
|
||||
gluTessCallback( tessellator, GLU_TESS_END_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEnd ) );
|
||||
gluTessCallback( tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateVertex ) );
|
||||
gluTessCallback( tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateCombine ) );
|
||||
gluTessCallback( tessellator, GLU_TESS_EDGE_FLAG_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEdgeFlag ) );
|
||||
gluTessCallback( tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateError ) );
|
||||
gluTessProperty( tessellator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO );
|
||||
|
||||
gluTessBeginPolygon( tessellator, &tessData );
|
||||
gluTessBeginContour( tessellator );
|
||||
|
||||
for ( unsigned int i = 0; i < polyLoopGL.size( ); ++i )
|
||||
{
|
||||
gluTessVertex( tessellator, reinterpret_cast< GLdouble* >( &polyLoopGL[ i ] ), &polyLoopGL[ i ] );
|
||||
}
|
||||
|
||||
gluTessEndContour( tessellator );
|
||||
gluTessEndPolygon( tessellator );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TriangulateDrawCalls( const TessDataGL& tessData )
|
||||
{
|
||||
// NOTE - Because we are supplying a callback to GLU_TESS_EDGE_FLAG_DATA we don't technically
|
||||
// need support for GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN but we'll keep it here in case
|
||||
// GLU tessellate changes or tri-strips and fans are wanted.
|
||||
// See: http://www.opengl.org/sdk/docs/man2/xhtml/gluTessCallback.xml
|
||||
for ( unsigned int i = 0; i < tessData.drawCalls.size( ); ++i )
|
||||
{
|
||||
const DrawCallGL& drawCallGL = tessData.drawCalls[ i ];
|
||||
const VertexGL* vertices = &tessData.vertices[ drawCallGL.baseVertex ];
|
||||
if ( drawCallGL.drawMode == GL_TRIANGLES )
|
||||
{
|
||||
MakeFacesFromTris( vertices, drawCallGL.vertexCount );
|
||||
}
|
||||
else if ( drawCallGL.drawMode == GL_TRIANGLE_STRIP )
|
||||
{
|
||||
MakeFacesFromTriStrip( vertices, drawCallGL.vertexCount );
|
||||
}
|
||||
else if ( drawCallGL.drawMode == GL_TRIANGLE_FAN )
|
||||
{
|
||||
MakeFacesFromTriFan( vertices, drawCallGL.vertexCount );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::MakeFacesFromTris( const VertexGL* vertices, int vertexCount )
|
||||
{
|
||||
const int triangleCount = vertexCount / 3;
|
||||
for ( int i = 0; i < triangleCount; ++i )
|
||||
{
|
||||
int vertexBase = i * 3;
|
||||
converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::MakeFacesFromTriStrip( const VertexGL* vertices, int vertexCount )
|
||||
{
|
||||
const int triangleCount = vertexCount - 2;
|
||||
for ( int i = 0; i < triangleCount; ++i )
|
||||
{
|
||||
int vertexBase = i;
|
||||
converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::MakeFacesFromTriFan( const VertexGL* vertices, int vertexCount )
|
||||
{
|
||||
const int triangleCount = vertexCount - 2;
|
||||
for ( int i = 0; i < triangleCount; ++i )
|
||||
{
|
||||
int vertexBase = i;
|
||||
converter->AddFace( vertices[ 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TessellateBegin( GLenum drawModeGL, void* userData )
|
||||
{
|
||||
TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
|
||||
tessData.drawCalls.push_back( DrawCallGL( drawModeGL, tessData.vertices.size( ) ) );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TessellateEnd( void* )
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TessellateVertex( const void* vtxData, void* userData )
|
||||
{
|
||||
TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
|
||||
|
||||
const VertexGL& vertex = *reinterpret_cast< const VertexGL* >( vtxData );
|
||||
if ( vertex.magic != BLEND_TESS_MAGIC )
|
||||
{
|
||||
ThrowException( "Point returned by GLU Tessellate was probably not one of ours. This indicates we need a new way to store vertex information" );
|
||||
}
|
||||
tessData.vertices.push_back( vertex );
|
||||
if ( tessData.drawCalls.size( ) == 0 )
|
||||
{
|
||||
ThrowException( "\"Vertex\" callback received before \"Begin\"" );
|
||||
}
|
||||
++( tessData.drawCalls.back( ).vertexCount );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData )
|
||||
{
|
||||
ThrowException( "Intersected polygon loops are not yet supported" );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TessellateEdgeFlag( GLboolean, void* )
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
|
||||
{
|
||||
ThrowException( reinterpret_cast< const char* >( gluErrorString( errorCode ) ) );
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
||||
|
||||
#if ASSIMP_BLEND_WITH_POLY_2_TRI
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
template< > const char* LogFunctions< BlenderTessellatorP2T >::Prefix()
|
||||
{
|
||||
static auto prefix = "BLEND_TESS_P2T: ";
|
||||
return prefix;
|
||||
}
|
||||
}
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Blender;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BlenderTessellatorP2T::BlenderTessellatorP2T( BlenderBMeshConverter& converter ):
|
||||
converter( &converter )
|
||||
{
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BlenderTessellatorP2T::~BlenderTessellatorP2T( )
|
||||
{
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorP2T::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
|
||||
{
|
||||
AssertVertexCount( vertexCount );
|
||||
|
||||
// NOTE - We have to hope that points in a Blender polygon are roughly on the same plane.
|
||||
// There may be some triangulation artifacts if they are wildly different.
|
||||
|
||||
std::vector< PointP2T > points;
|
||||
Copy3DVertices( polyLoop, vertexCount, vertices, points );
|
||||
|
||||
PlaneP2T plane = FindLLSQPlane( points );
|
||||
|
||||
aiMatrix4x4 transform = GeneratePointTransformMatrix( plane );
|
||||
|
||||
TransformAndFlattenVectices( transform, points );
|
||||
|
||||
std::vector< p2t::Point* > pointRefs;
|
||||
ReferencePoints( points, pointRefs );
|
||||
|
||||
p2t::CDT cdt( pointRefs );
|
||||
|
||||
cdt.Triangulate( );
|
||||
std::vector< p2t::Triangle* > triangles = cdt.GetTriangles( );
|
||||
|
||||
MakeFacesFromTriangles( triangles );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorP2T::AssertVertexCount( int vertexCount )
|
||||
{
|
||||
if ( vertexCount <= 4 )
|
||||
{
|
||||
ThrowException( "Expected more than 4 vertices for tessellation" );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices, std::vector< PointP2T >& points ) const
|
||||
{
|
||||
points.resize( vertexCount );
|
||||
for ( int i = 0; i < vertexCount; ++i )
|
||||
{
|
||||
const MLoop& loop = polyLoop[ i ];
|
||||
const MVert& vert = vertices[ loop.v ];
|
||||
|
||||
PointP2T& point = points[ i ];
|
||||
point.point3D.Set( vert.co[ 0 ], vert.co[ 1 ], vert.co[ 2 ] );
|
||||
point.index = loop.v;
|
||||
point.magic = BLEND_TESS_MAGIC;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const
|
||||
{
|
||||
aiVector3D sideA( 1.0f, 0.0f, 0.0f );
|
||||
if ( std::fabs( plane.normal * sideA ) > 0.999f )
|
||||
{
|
||||
sideA = aiVector3D( 0.0f, 1.0f, 0.0f );
|
||||
}
|
||||
|
||||
aiVector3D sideB( plane.normal ^ sideA );
|
||||
sideB.Normalize( );
|
||||
sideA = sideB ^ plane.normal;
|
||||
|
||||
aiMatrix4x4 result;
|
||||
result.a1 = sideA.x;
|
||||
result.a2 = sideA.y;
|
||||
result.a3 = sideA.z;
|
||||
result.b1 = sideB.x;
|
||||
result.b2 = sideB.y;
|
||||
result.b3 = sideB.z;
|
||||
result.c1 = plane.normal.x;
|
||||
result.c2 = plane.normal.y;
|
||||
result.c3 = plane.normal.z;
|
||||
result.a4 = plane.centre.x;
|
||||
result.b4 = plane.centre.y;
|
||||
result.c4 = plane.centre.z;
|
||||
result.Inverse( );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorP2T::TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const
|
||||
{
|
||||
for ( size_t i = 0; i < vertices.size( ); ++i )
|
||||
{
|
||||
PointP2T& point = vertices[ i ];
|
||||
point.point3D = transform * point.point3D;
|
||||
point.point2D.set( point.point3D.y, point.point3D.z );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorP2T::ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const
|
||||
{
|
||||
pointRefs.resize( points.size( ) );
|
||||
for ( size_t i = 0; i < points.size( ); ++i )
|
||||
{
|
||||
pointRefs[ i ] = &points[ i ].point2D;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline PointP2T& BlenderTessellatorP2T::GetActualPointStructure( p2t::Point& point ) const
|
||||
{
|
||||
unsigned int pointOffset = offsetof( PointP2T, point2D );
|
||||
PointP2T& pointStruct = *reinterpret_cast< PointP2T* >( reinterpret_cast< char* >( &point ) - pointOffset );
|
||||
if ( pointStruct.magic != static_cast<int>( BLEND_TESS_MAGIC ) )
|
||||
{
|
||||
ThrowException( "Point returned by poly2tri was probably not one of ours. This indicates we need a new way to store vertex information" );
|
||||
}
|
||||
return pointStruct;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorP2T::MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const
|
||||
{
|
||||
for ( size_t i = 0; i < triangles.size( ); ++i )
|
||||
{
|
||||
p2t::Triangle& Triangle = *triangles[ i ];
|
||||
|
||||
PointP2T& pointA = GetActualPointStructure( *Triangle.GetPoint( 0 ) );
|
||||
PointP2T& pointB = GetActualPointStructure( *Triangle.GetPoint( 1 ) );
|
||||
PointP2T& pointC = GetActualPointStructure( *Triangle.GetPoint( 2 ) );
|
||||
|
||||
converter->AddFace( pointA.index, pointB.index, pointC.index );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline float p2tMax( float a, float b )
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
|
||||
float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) const
|
||||
{
|
||||
float result = 0.0f;
|
||||
|
||||
for ( unsigned int x = 0; x < 3; ++x )
|
||||
{
|
||||
for ( unsigned int y = 0; y < 3; ++y )
|
||||
{
|
||||
result = p2tMax( std::fabs( mtx[ x ][ y ] ), result );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Apparently Assimp doesn't have matrix scaling
|
||||
aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const
|
||||
{
|
||||
aiMatrix3x3 result;
|
||||
|
||||
for ( unsigned int x = 0; x < 3; ++x )
|
||||
{
|
||||
for ( unsigned int y = 0; y < 3; ++y )
|
||||
{
|
||||
result[ x ][ y ] = mtx[ x ][ y ] * scale;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
|
||||
aiVector3D BlenderTessellatorP2T::GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const
|
||||
{
|
||||
const float scale = FindLargestMatrixElem( mtx );
|
||||
aiMatrix3x3 mc = ScaleMatrix( mtx, 1.0f / scale );
|
||||
mc = mc * mc * mc;
|
||||
|
||||
aiVector3D v( 1.0f );
|
||||
aiVector3D lastV = v;
|
||||
for ( int i = 0; i < 100; ++i )
|
||||
{
|
||||
v = mc * v;
|
||||
v.Normalize( );
|
||||
if ( ( v - lastV ).SquareLength( ) < 1e-16f )
|
||||
{
|
||||
break;
|
||||
}
|
||||
lastV = v;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
|
||||
PlaneP2T BlenderTessellatorP2T::FindLLSQPlane( const std::vector< PointP2T >& points ) const
|
||||
{
|
||||
PlaneP2T result;
|
||||
|
||||
aiVector3D sum( 0.0 );
|
||||
for ( size_t i = 0; i < points.size( ); ++i )
|
||||
{
|
||||
sum += points[ i ].point3D;
|
||||
}
|
||||
result.centre = sum * (ai_real)( 1.0 / points.size( ) );
|
||||
|
||||
ai_real sumXX = 0.0;
|
||||
ai_real sumXY = 0.0;
|
||||
ai_real sumXZ = 0.0;
|
||||
ai_real sumYY = 0.0;
|
||||
ai_real sumYZ = 0.0;
|
||||
ai_real sumZZ = 0.0;
|
||||
for ( size_t i = 0; i < points.size( ); ++i )
|
||||
{
|
||||
aiVector3D offset = points[ i ].point3D - result.centre;
|
||||
sumXX += offset.x * offset.x;
|
||||
sumXY += offset.x * offset.y;
|
||||
sumXZ += offset.x * offset.z;
|
||||
sumYY += offset.y * offset.y;
|
||||
sumYZ += offset.y * offset.z;
|
||||
sumZZ += offset.z * offset.z;
|
||||
}
|
||||
|
||||
aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ );
|
||||
|
||||
const ai_real det = mtx.Determinant( );
|
||||
if ( det == 0.0f )
|
||||
{
|
||||
result.normal = aiVector3D( 0.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
aiMatrix3x3 invMtx = mtx;
|
||||
invMtx.Inverse( );
|
||||
result.normal = GetEigenVectorFromLargestEigenValue( invMtx );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BLEND_WITH_POLY_2_TRI
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
214
thirdparty/assimp/code/Blender/BlenderTessellator.h
vendored
Normal file
214
thirdparty/assimp/code/Blender/BlenderTessellator.h
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderTessellator.h
|
||||
* @brief A simple tessellation wrapper
|
||||
*/
|
||||
#ifndef INCLUDED_AI_BLEND_TESSELLATOR_H
|
||||
#define INCLUDED_AI_BLEND_TESSELLATOR_H
|
||||
|
||||
// Use these to toggle between GLU Tessellate or poly2tri
|
||||
// Note (acg) keep GLU Tessellate disabled by default - if it is turned on,
|
||||
// assimp needs to be linked against GLU, which is currently not yet
|
||||
// made configurable in CMake and potentially not wanted by most users
|
||||
// as it requires a Gl environment.
|
||||
#ifndef ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
||||
# define ASSIMP_BLEND_WITH_GLU_TESSELLATE 0
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BLEND_WITH_POLY_2_TRI
|
||||
# define ASSIMP_BLEND_WITH_POLY_2_TRI 1
|
||||
#endif
|
||||
|
||||
#include <assimp/LogAux.h>
|
||||
|
||||
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
||||
|
||||
#if defined( WIN32 ) || defined( _WIN32 ) || defined( _MSC_VER )
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <GL/glu.h>
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
class BlenderBMeshConverter;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// BlenderScene.h
|
||||
namespace Blender
|
||||
{
|
||||
struct MLoop;
|
||||
struct MVert;
|
||||
|
||||
struct VertexGL
|
||||
{
|
||||
GLdouble X;
|
||||
GLdouble Y;
|
||||
GLdouble Z;
|
||||
int index;
|
||||
int magic;
|
||||
|
||||
VertexGL( GLdouble X, GLdouble Y, GLdouble Z, int index, int magic ): X( X ), Y( Y ), Z( Z ), index( index ), magic( magic ) { }
|
||||
};
|
||||
|
||||
struct DrawCallGL
|
||||
{
|
||||
GLenum drawMode;
|
||||
int baseVertex;
|
||||
int vertexCount;
|
||||
|
||||
DrawCallGL( GLenum drawMode, int baseVertex ): drawMode( drawMode ), baseVertex( baseVertex ), vertexCount( 0 ) { }
|
||||
};
|
||||
|
||||
struct TessDataGL
|
||||
{
|
||||
std::vector< DrawCallGL > drawCalls;
|
||||
std::vector< VertexGL > vertices;
|
||||
};
|
||||
}
|
||||
|
||||
class BlenderTessellatorGL: public LogFunctions< BlenderTessellatorGL >
|
||||
{
|
||||
public:
|
||||
BlenderTessellatorGL( BlenderBMeshConverter& converter );
|
||||
~BlenderTessellatorGL( );
|
||||
|
||||
void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
|
||||
|
||||
private:
|
||||
void AssertVertexCount( int vertexCount );
|
||||
void GenerateLoopVerts( std::vector< Blender::VertexGL >& polyLoopGL, const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
|
||||
void Tesssellate( std::vector< Blender::VertexGL >& polyLoopGL, Blender::TessDataGL& tessData );
|
||||
void TriangulateDrawCalls( const Blender::TessDataGL& tessData );
|
||||
void MakeFacesFromTris( const Blender::VertexGL* vertices, int vertexCount );
|
||||
void MakeFacesFromTriStrip( const Blender::VertexGL* vertices, int vertexCount );
|
||||
void MakeFacesFromTriFan( const Blender::VertexGL* vertices, int vertexCount );
|
||||
|
||||
static void TessellateBegin( GLenum drawModeGL, void* userData );
|
||||
static void TessellateEnd( void* userData );
|
||||
static void TessellateVertex( const void* vtxData, void* userData );
|
||||
static void TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData );
|
||||
static void TessellateEdgeFlag( GLboolean edgeFlag, void* userData );
|
||||
static void TessellateError( GLenum errorCode, void* userData );
|
||||
|
||||
BlenderBMeshConverter* converter;
|
||||
};
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
||||
|
||||
#if ASSIMP_BLEND_WITH_POLY_2_TRI
|
||||
|
||||
#ifdef ASSIMP_USE_HUNTER
|
||||
# include <poly2tri/poly2tri.h>
|
||||
#else
|
||||
# include "../contrib/poly2tri/poly2tri/poly2tri.h"
|
||||
#endif
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
class BlenderBMeshConverter;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// BlenderScene.h
|
||||
namespace Blender
|
||||
{
|
||||
struct MLoop;
|
||||
struct MVert;
|
||||
|
||||
struct PointP2T
|
||||
{
|
||||
aiVector3D point3D;
|
||||
p2t::Point point2D;
|
||||
int magic;
|
||||
int index;
|
||||
};
|
||||
|
||||
struct PlaneP2T
|
||||
{
|
||||
aiVector3D centre;
|
||||
aiVector3D normal;
|
||||
};
|
||||
}
|
||||
|
||||
class BlenderTessellatorP2T: public LogFunctions< BlenderTessellatorP2T >
|
||||
{
|
||||
public:
|
||||
BlenderTessellatorP2T( BlenderBMeshConverter& converter );
|
||||
~BlenderTessellatorP2T( );
|
||||
|
||||
void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
|
||||
|
||||
private:
|
||||
void AssertVertexCount( int vertexCount );
|
||||
void Copy3DVertices( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices, std::vector< Blender::PointP2T >& targetVertices ) const;
|
||||
aiMatrix4x4 GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const;
|
||||
void TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const;
|
||||
void ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const;
|
||||
inline Blender::PointP2T& GetActualPointStructure( p2t::Point& point ) const;
|
||||
void MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const;
|
||||
|
||||
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
|
||||
float FindLargestMatrixElem( const aiMatrix3x3& mtx ) const;
|
||||
aiMatrix3x3 ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const;
|
||||
aiVector3D GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const;
|
||||
Blender::PlaneP2T FindLLSQPlane( const std::vector< Blender::PointP2T >& points ) const;
|
||||
|
||||
BlenderBMeshConverter* converter;
|
||||
};
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // ASSIMP_BLEND_WITH_POLY_2_TRI
|
||||
|
||||
#endif // INCLUDED_AI_BLEND_TESSELLATOR_H
|
||||
Reference in New Issue
Block a user