Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Courses
Scotty3D
Commits
c6fcf2f0
Commit
c6fcf2f0
authored
Sep 08, 2020
by
TheNumbat
Browse files
initial codebase
parent
f746c7c1
Changes
138
Show whitespace changes
Inline
Side-by-side
Too many changes to show.
To preserve performance only
138 of 138+
files are displayed.
Plain diff
Email patch
deps/assimp/code/AssetLib/Assbin/AssbinFileWriter.h
0 → 100644
View file @
c6fcf2f0
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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 AssbinFileWriter.h
* @brief Declaration of Assbin file writer.
*/
#ifndef AI_ASSBINFILEWRITER_H_INC
#define AI_ASSBINFILEWRITER_H_INC
#include <assimp/defs.h>
#include <assimp/scene.h>
#include <assimp/IOSystem.hpp>
namespace
Assimp
{
void
ASSIMP_API
DumpSceneToAssbin
(
const
char
*
pFile
,
const
char
*
cmd
,
IOSystem
*
pIOSystem
,
const
aiScene
*
pScene
,
bool
shortened
,
bool
compressed
);
}
#endif // AI_ASSBINFILEWRITER_H_INC
deps/assimp/code/AssetLib/Assbin/AssbinLoader.cpp
0 → 100644
View file @
c6fcf2f0
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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 AssbinLoader.cpp
* @brief Implementation of the .assbin importer class
*
* see assbin_chunks.h
*/
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
// internal headers
#include "AssetLib/Assbin/AssbinLoader.h"
#include "Common/assbin_chunks.h"
#include <assimp/MemoryIOWrapper.h>
#include <assimp/anim.h>
#include <assimp/importerdesc.h>
#include <assimp/mesh.h>
#include <assimp/scene.h>
#include <memory>
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
#include <zlib.h>
#else
#include <contrib/zlib/zlib.h>
#endif
using
namespace
Assimp
;
static
const
aiImporterDesc
desc
=
{
"Assimp Binary Importer"
,
"Gargaj / Conspiracy"
,
""
,
""
,
aiImporterFlags_SupportBinaryFlavour
|
aiImporterFlags_SupportCompressedFlavour
,
0
,
0
,
0
,
0
,
"assbin"
};
// -----------------------------------------------------------------------------------
const
aiImporterDesc
*
AssbinImporter
::
GetInfo
()
const
{
return
&
desc
;
}
// -----------------------------------------------------------------------------------
bool
AssbinImporter
::
CanRead
(
const
std
::
string
&
pFile
,
IOSystem
*
pIOHandler
,
bool
/*checkSig*/
)
const
{
IOStream
*
in
=
pIOHandler
->
Open
(
pFile
);
if
(
nullptr
==
in
)
{
return
false
;
}
char
s
[
32
];
in
->
Read
(
s
,
sizeof
(
char
),
32
);
pIOHandler
->
Close
(
in
);
return
strncmp
(
s
,
"ASSIMP.binary-dump."
,
19
)
==
0
;
}
// -----------------------------------------------------------------------------------
template
<
typename
T
>
T
Read
(
IOStream
*
stream
)
{
T
t
;
size_t
res
=
stream
->
Read
(
&
t
,
sizeof
(
T
),
1
);
if
(
res
!=
1
)
{
throw
DeadlyImportError
(
"Unexpected EOF"
);
}
return
t
;
}
// -----------------------------------------------------------------------------------
template
<
>
aiVector3D
Read
<
aiVector3D
>
(
IOStream
*
stream
)
{
aiVector3D
v
;
v
.
x
=
Read
<
ai_real
>
(
stream
);
v
.
y
=
Read
<
ai_real
>
(
stream
);
v
.
z
=
Read
<
ai_real
>
(
stream
);
return
v
;
}
// -----------------------------------------------------------------------------------
template
<
>
aiColor4D
Read
<
aiColor4D
>
(
IOStream
*
stream
)
{
aiColor4D
c
;
c
.
r
=
Read
<
ai_real
>
(
stream
);
c
.
g
=
Read
<
ai_real
>
(
stream
);
c
.
b
=
Read
<
ai_real
>
(
stream
);
c
.
a
=
Read
<
ai_real
>
(
stream
);
return
c
;
}
// -----------------------------------------------------------------------------------
template
<
>
aiQuaternion
Read
<
aiQuaternion
>
(
IOStream
*
stream
)
{
aiQuaternion
v
;
v
.
w
=
Read
<
ai_real
>
(
stream
);
v
.
x
=
Read
<
ai_real
>
(
stream
);
v
.
y
=
Read
<
ai_real
>
(
stream
);
v
.
z
=
Read
<
ai_real
>
(
stream
);
return
v
;
}
// -----------------------------------------------------------------------------------
template
<
>
aiString
Read
<
aiString
>
(
IOStream
*
stream
)
{
aiString
s
;
stream
->
Read
(
&
s
.
length
,
4
,
1
);
if
(
s
.
length
)
{
stream
->
Read
(
s
.
data
,
s
.
length
,
1
);
}
s
.
data
[
s
.
length
]
=
0
;
return
s
;
}
// -----------------------------------------------------------------------------------
template
<
>
aiVertexWeight
Read
<
aiVertexWeight
>
(
IOStream
*
stream
)
{
aiVertexWeight
w
;
w
.
mVertexId
=
Read
<
unsigned
int
>
(
stream
);
w
.
mWeight
=
Read
<
ai_real
>
(
stream
);
return
w
;
}
// -----------------------------------------------------------------------------------
template
<
>
aiMatrix4x4
Read
<
aiMatrix4x4
>
(
IOStream
*
stream
)
{
aiMatrix4x4
m
;
for
(
unsigned
int
i
=
0
;
i
<
4
;
++
i
)
{
for
(
unsigned
int
i2
=
0
;
i2
<
4
;
++
i2
)
{
m
[
i
][
i2
]
=
Read
<
ai_real
>
(
stream
);
}
}
return
m
;
}
// -----------------------------------------------------------------------------------
template
<
>
aiVectorKey
Read
<
aiVectorKey
>
(
IOStream
*
stream
)
{
aiVectorKey
v
;
v
.
mTime
=
Read
<
double
>
(
stream
);
v
.
mValue
=
Read
<
aiVector3D
>
(
stream
);
return
v
;
}
// -----------------------------------------------------------------------------------
template
<
>
aiQuatKey
Read
<
aiQuatKey
>
(
IOStream
*
stream
)
{
aiQuatKey
v
;
v
.
mTime
=
Read
<
double
>
(
stream
);
v
.
mValue
=
Read
<
aiQuaternion
>
(
stream
);
return
v
;
}
// -----------------------------------------------------------------------------------
template
<
typename
T
>
void
ReadArray
(
IOStream
*
stream
,
T
*
out
,
unsigned
int
size
)
{
ai_assert
(
nullptr
!=
stream
);
ai_assert
(
nullptr
!=
out
);
for
(
unsigned
int
i
=
0
;
i
<
size
;
i
++
)
{
out
[
i
]
=
Read
<
T
>
(
stream
);
}
}
// -----------------------------------------------------------------------------------
template
<
typename
T
>
void
ReadBounds
(
IOStream
*
stream
,
T
*
/*p*/
,
unsigned
int
n
)
{
// not sure what to do here, the data isn't really useful.
stream
->
Seek
(
sizeof
(
T
)
*
n
,
aiOrigin_CUR
);
}
// -----------------------------------------------------------------------------------
void
AssbinImporter
::
ReadBinaryNode
(
IOStream
*
stream
,
aiNode
**
onode
,
aiNode
*
parent
)
{
if
(
Read
<
uint32_t
>
(
stream
)
!=
ASSBIN_CHUNK_AINODE
)
throw
DeadlyImportError
(
"Magic chunk identifiers are wrong!"
);
/*uint32_t size =*/
Read
<
uint32_t
>
(
stream
);
std
::
unique_ptr
<
aiNode
>
node
(
new
aiNode
());
node
->
mName
=
Read
<
aiString
>
(
stream
);
node
->
mTransformation
=
Read
<
aiMatrix4x4
>
(
stream
);
unsigned
numChildren
=
Read
<
unsigned
int
>
(
stream
);
unsigned
numMeshes
=
Read
<
unsigned
int
>
(
stream
);
unsigned
int
nb_metadata
=
Read
<
unsigned
int
>
(
stream
);
if
(
parent
)
{
node
->
mParent
=
parent
;
}
if
(
numMeshes
)
{
node
->
mMeshes
=
new
unsigned
int
[
numMeshes
];
for
(
unsigned
int
i
=
0
;
i
<
numMeshes
;
++
i
)
{
node
->
mMeshes
[
i
]
=
Read
<
unsigned
int
>
(
stream
);
node
->
mNumMeshes
++
;
}
}
if
(
numChildren
)
{
node
->
mChildren
=
new
aiNode
*
[
numChildren
];
for
(
unsigned
int
i
=
0
;
i
<
numChildren
;
++
i
)
{
ReadBinaryNode
(
stream
,
&
node
->
mChildren
[
i
],
node
.
get
());
node
->
mNumChildren
++
;
}
}
if
(
nb_metadata
>
0
)
{
node
->
mMetaData
=
aiMetadata
::
Alloc
(
nb_metadata
);
for
(
unsigned
int
i
=
0
;
i
<
nb_metadata
;
++
i
)
{
node
->
mMetaData
->
mKeys
[
i
]
=
Read
<
aiString
>
(
stream
);
node
->
mMetaData
->
mValues
[
i
].
mType
=
(
aiMetadataType
)
Read
<
uint16_t
>
(
stream
);
void
*
data
=
nullptr
;
switch
(
node
->
mMetaData
->
mValues
[
i
].
mType
)
{
case
AI_BOOL
:
data
=
new
bool
(
Read
<
bool
>
(
stream
));
break
;
case
AI_INT32
:
data
=
new
int32_t
(
Read
<
int32_t
>
(
stream
));
break
;
case
AI_UINT64
:
data
=
new
uint64_t
(
Read
<
uint64_t
>
(
stream
));
break
;
case
AI_FLOAT
:
data
=
new
ai_real
(
Read
<
ai_real
>
(
stream
));
break
;
case
AI_DOUBLE
:
data
=
new
double
(
Read
<
double
>
(
stream
));
break
;
case
AI_AISTRING
:
data
=
new
aiString
(
Read
<
aiString
>
(
stream
));
break
;
case
AI_AIVECTOR3D
:
data
=
new
aiVector3D
(
Read
<
aiVector3D
>
(
stream
));
break
;
#ifndef SWIG
case
FORCE_32BIT
:
#endif // SWIG
default:
break
;
}
node
->
mMetaData
->
mValues
[
i
].
mData
=
data
;
}
}
*
onode
=
node
.
release
();
}
// -----------------------------------------------------------------------------------
void
AssbinImporter
::
ReadBinaryBone
(
IOStream
*
stream
,
aiBone
*
b
)
{
if
(
Read
<
uint32_t
>
(
stream
)
!=
ASSBIN_CHUNK_AIBONE
)
throw
DeadlyImportError
(
"Magic chunk identifiers are wrong!"
);
/*uint32_t size =*/
Read
<
uint32_t
>
(
stream
);
b
->
mName
=
Read
<
aiString
>
(
stream
);
b
->
mNumWeights
=
Read
<
unsigned
int
>
(
stream
);
b
->
mOffsetMatrix
=
Read
<
aiMatrix4x4
>
(
stream
);
// for the moment we write dumb min/max values for the bones, too.
// maybe I'll add a better, hash-like solution later
if
(
shortened
)
{
ReadBounds
(
stream
,
b
->
mWeights
,
b
->
mNumWeights
);
}
else
{
// else write as usual
b
->
mWeights
=
new
aiVertexWeight
[
b
->
mNumWeights
];
ReadArray
<
aiVertexWeight
>
(
stream
,
b
->
mWeights
,
b
->
mNumWeights
);
}
}
// -----------------------------------------------------------------------------------
static
bool
fitsIntoUI16
(
unsigned
int
mNumVertices
)
{
return
(
mNumVertices
<
(
1u
<<
16
));
}
// -----------------------------------------------------------------------------------
void
AssbinImporter
::
ReadBinaryMesh
(
IOStream
*
stream
,
aiMesh
*
mesh
)
{
if
(
Read
<
uint32_t
>
(
stream
)
!=
ASSBIN_CHUNK_AIMESH
)
throw
DeadlyImportError
(
"Magic chunk identifiers are wrong!"
);
/*uint32_t size =*/
Read
<
uint32_t
>
(
stream
);
mesh
->
mPrimitiveTypes
=
Read
<
unsigned
int
>
(
stream
);
mesh
->
mNumVertices
=
Read
<
unsigned
int
>
(
stream
);
mesh
->
mNumFaces
=
Read
<
unsigned
int
>
(
stream
);
mesh
->
mNumBones
=
Read
<
unsigned
int
>
(
stream
);
mesh
->
mMaterialIndex
=
Read
<
unsigned
int
>
(
stream
);
// first of all, write bits for all existent vertex components
unsigned
int
c
=
Read
<
unsigned
int
>
(
stream
);
if
(
c
&
ASSBIN_MESH_HAS_POSITIONS
)
{
if
(
shortened
)
{
ReadBounds
(
stream
,
mesh
->
mVertices
,
mesh
->
mNumVertices
);
}
else
{
// else write as usual
mesh
->
mVertices
=
new
aiVector3D
[
mesh
->
mNumVertices
];
ReadArray
<
aiVector3D
>
(
stream
,
mesh
->
mVertices
,
mesh
->
mNumVertices
);
}
}
if
(
c
&
ASSBIN_MESH_HAS_NORMALS
)
{
if
(
shortened
)
{
ReadBounds
(
stream
,
mesh
->
mNormals
,
mesh
->
mNumVertices
);
}
else
{
// else write as usual
mesh
->
mNormals
=
new
aiVector3D
[
mesh
->
mNumVertices
];
ReadArray
<
aiVector3D
>
(
stream
,
mesh
->
mNormals
,
mesh
->
mNumVertices
);
}
}
if
(
c
&
ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS
)
{
if
(
shortened
)
{
ReadBounds
(
stream
,
mesh
->
mTangents
,
mesh
->
mNumVertices
);
ReadBounds
(
stream
,
mesh
->
mBitangents
,
mesh
->
mNumVertices
);
}
else
{
// else write as usual
mesh
->
mTangents
=
new
aiVector3D
[
mesh
->
mNumVertices
];
ReadArray
<
aiVector3D
>
(
stream
,
mesh
->
mTangents
,
mesh
->
mNumVertices
);
mesh
->
mBitangents
=
new
aiVector3D
[
mesh
->
mNumVertices
];
ReadArray
<
aiVector3D
>
(
stream
,
mesh
->
mBitangents
,
mesh
->
mNumVertices
);
}
}
for
(
unsigned
int
n
=
0
;
n
<
AI_MAX_NUMBER_OF_COLOR_SETS
;
++
n
)
{
if
(
!
(
c
&
ASSBIN_MESH_HAS_COLOR
(
n
)))
{
break
;
}
if
(
shortened
)
{
ReadBounds
(
stream
,
mesh
->
mColors
[
n
],
mesh
->
mNumVertices
);
}
else
{
// else write as usual
mesh
->
mColors
[
n
]
=
new
aiColor4D
[
mesh
->
mNumVertices
];
ReadArray
<
aiColor4D
>
(
stream
,
mesh
->
mColors
[
n
],
mesh
->
mNumVertices
);
}
}
for
(
unsigned
int
n
=
0
;
n
<
AI_MAX_NUMBER_OF_TEXTURECOORDS
;
++
n
)
{
if
(
!
(
c
&
ASSBIN_MESH_HAS_TEXCOORD
(
n
)))
{
break
;
}
// write number of UV components
mesh
->
mNumUVComponents
[
n
]
=
Read
<
unsigned
int
>
(
stream
);
if
(
shortened
)
{
ReadBounds
(
stream
,
mesh
->
mTextureCoords
[
n
],
mesh
->
mNumVertices
);
}
else
{
// else write as usual
mesh
->
mTextureCoords
[
n
]
=
new
aiVector3D
[
mesh
->
mNumVertices
];
ReadArray
<
aiVector3D
>
(
stream
,
mesh
->
mTextureCoords
[
n
],
mesh
->
mNumVertices
);
}
}
// write faces. There are no floating-point calculations involved
// in these, so we can write a simple hash over the face data
// to the dump file. We generate a single 32 Bit hash for 512 faces
// using Assimp's standard hashing function.
if
(
shortened
)
{
Read
<
unsigned
int
>
(
stream
);
}
else
{
// else write as usual
// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
mesh
->
mFaces
=
new
aiFace
[
mesh
->
mNumFaces
];
for
(
unsigned
int
i
=
0
;
i
<
mesh
->
mNumFaces
;
++
i
)
{
aiFace
&
f
=
mesh
->
mFaces
[
i
];
static_assert
(
AI_MAX_FACE_INDICES
<=
0xffff
,
"AI_MAX_FACE_INDICES <= 0xffff"
);
f
.
mNumIndices
=
Read
<
uint16_t
>
(
stream
);
f
.
mIndices
=
new
unsigned
int
[
f
.
mNumIndices
];
for
(
unsigned
int
a
=
0
;
a
<
f
.
mNumIndices
;
++
a
)
{
// Check if unsigned short ( 16 bit ) are big enought for the indices
if
(
fitsIntoUI16
(
mesh
->
mNumVertices
))
{
f
.
mIndices
[
a
]
=
Read
<
uint16_t
>
(
stream
);
}
else
{
f
.
mIndices
[
a
]
=
Read
<
unsigned
int
>
(
stream
);
}
}
}
}
// write bones
if
(
mesh
->
mNumBones
)
{
mesh
->
mBones
=
new
C_STRUCT
aiBone
*
[
mesh
->
mNumBones
];
for
(
unsigned
int
a
=
0
;
a
<
mesh
->
mNumBones
;
++
a
)
{
mesh
->
mBones
[
a
]
=
new
aiBone
();
ReadBinaryBone
(
stream
,
mesh
->
mBones
[
a
]);
}
}
}
// -----------------------------------------------------------------------------------
void
AssbinImporter
::
ReadBinaryMaterialProperty
(
IOStream
*
stream
,
aiMaterialProperty
*
prop
)
{
if
(
Read
<
uint32_t
>
(
stream
)
!=
ASSBIN_CHUNK_AIMATERIALPROPERTY
)
throw
DeadlyImportError
(
"Magic chunk identifiers are wrong!"
);
/*uint32_t size =*/
Read
<
uint32_t
>
(
stream
);
prop
->
mKey
=
Read
<
aiString
>
(
stream
);
prop
->
mSemantic
=
Read
<
unsigned
int
>
(
stream
);
prop
->
mIndex
=
Read
<
unsigned
int
>
(
stream
);
prop
->
mDataLength
=
Read
<
unsigned
int
>
(
stream
);
prop
->
mType
=
(
aiPropertyTypeInfo
)
Read
<
unsigned
int
>
(
stream
);
prop
->
mData
=
new
char
[
prop
->
mDataLength
];
stream
->
Read
(
prop
->
mData
,
1
,
prop
->
mDataLength
);
}
// -----------------------------------------------------------------------------------
void
AssbinImporter
::
ReadBinaryMaterial
(
IOStream
*
stream
,
aiMaterial
*
mat
)
{
if
(
Read
<
uint32_t
>
(
stream
)
!=
ASSBIN_CHUNK_AIMATERIAL
)
throw
DeadlyImportError
(
"Magic chunk identifiers are wrong!"
);
/*uint32_t size =*/
Read
<
uint32_t
>
(
stream
);
mat
->
mNumAllocated
=
mat
->
mNumProperties
=
Read
<
unsigned
int
>
(
stream
);
if
(
mat
->
mNumProperties
)
{
if
(
mat
->
mProperties
)
{
delete
[]
mat
->
mProperties
;
}
mat
->
mProperties
=
new
aiMaterialProperty
*
[
mat
->
mNumProperties
];
for
(
unsigned
int
i
=
0
;
i
<
mat
->
mNumProperties
;
++
i
)
{
mat
->
mProperties
[
i
]
=
new
aiMaterialProperty
();
ReadBinaryMaterialProperty
(
stream
,
mat
->
mProperties
[
i
]);
}
}
}
// -----------------------------------------------------------------------------------
void
AssbinImporter
::
ReadBinaryNodeAnim
(
IOStream
*
stream
,
aiNodeAnim
*
nd
)
{
if
(
Read
<
uint32_t
>
(
stream
)
!=
ASSBIN_CHUNK_AINODEANIM
)
throw
DeadlyImportError
(
"Magic chunk identifiers are wrong!"
);
/*uint32_t size =*/
Read
<
uint32_t
>
(
stream
);
nd
->
mNodeName
=
Read
<
aiString
>
(
stream
);
nd
->
mNumPositionKeys
=
Read
<
unsigned
int
>
(
stream
);
nd
->
mNumRotationKeys
=
Read
<
unsigned
int
>
(
stream
);
nd
->
mNumScalingKeys
=
Read
<
unsigned
int
>
(
stream
);
nd
->
mPreState
=
(
aiAnimBehaviour
)
Read
<
unsigned
int
>
(
stream
);
nd
->
mPostState
=
(
aiAnimBehaviour
)
Read
<
unsigned
int
>
(
stream
);
if
(
nd
->
mNumPositionKeys
)
{
if
(
shortened
)
{
ReadBounds
(
stream
,
nd
->
mPositionKeys
,
nd
->
mNumPositionKeys
);
}
// else write as usual
else
{
nd
->
mPositionKeys
=
new
aiVectorKey
[
nd
->
mNumPositionKeys
];
ReadArray
<
aiVectorKey
>
(
stream
,
nd
->
mPositionKeys
,
nd
->
mNumPositionKeys
);
}
}
if
(
nd
->
mNumRotationKeys
)
{
if
(
shortened
)
{
ReadBounds
(
stream
,
nd
->
mRotationKeys
,
nd
->
mNumRotationKeys
);
}
else
{
// else write as usual
nd
->
mRotationKeys
=
new
aiQuatKey
[
nd
->
mNumRotationKeys
];
ReadArray
<
aiQuatKey
>
(
stream
,
nd
->
mRotationKeys
,
nd
->
mNumRotationKeys
);
}
}
if
(
nd
->
mNumScalingKeys
)
{
if
(
shortened
)
{
ReadBounds
(
stream
,
nd
->
mScalingKeys
,
nd
->
mNumScalingKeys
);
}
else
{
// else write as usual
nd
->
mScalingKeys
=
new
aiVectorKey
[
nd
->
mNumScalingKeys
];
ReadArray
<
aiVectorKey
>
(
stream
,
nd
->
mScalingKeys
,
nd
->
mNumScalingKeys
);
}
}
}
// -----------------------------------------------------------------------------------
void
AssbinImporter
::
ReadBinaryAnim
(
IOStream
*
stream
,
aiAnimation
*
anim
)
{
if
(
Read
<
uint32_t
>
(
stream
)
!=
ASSBIN_CHUNK_AIANIMATION
)
throw
DeadlyImportError
(
"Magic chunk identifiers are wrong!"
);
/*uint32_t size =*/
Read
<
uint32_t
>
(
stream
);
anim
->
mName
=
Read
<
aiString
>
(
stream
);
anim
->
mDuration
=
Read
<
double
>
(
stream
);
anim
->
mTicksPerSecond
=
Read
<
double
>
(
stream
);
anim
->
mNumChannels
=
Read
<
unsigned
int
>
(
stream
);
if
(
anim
->
mNumChannels
)
{
anim
->
mChannels
=
new
aiNodeAnim
*
[
anim
->
mNumChannels
];
for
(
unsigned
int
a
=
0
;
a
<
anim
->
mNumChannels
;
++
a
)
{
anim
->
mChannels
[
a
]
=
new
aiNodeAnim
();
ReadBinaryNodeAnim
(
stream
,
anim
->
mChannels
[
a
]);
}
}
}
// -----------------------------------------------------------------------------------
void
AssbinImporter
::
ReadBinaryTexture
(
IOStream
*
stream
,
aiTexture
*
tex
)
{
if
(
Read
<
uint32_t
>
(
stream
)
!=
ASSBIN_CHUNK_AITEXTURE
)
throw
DeadlyImportError
(
"Magic chunk identifiers are wrong!"
);
/*uint32_t size =*/
Read
<
uint32_t
>
(
stream
);
tex
->
mWidth
=
Read
<
unsigned
int
>
(
stream
);
tex
->
mHeight
=
Read
<
unsigned
int
>
(
stream
);
stream
->
Read
(
tex
->
achFormatHint
,
sizeof
(
char
),
HINTMAXTEXTURELEN
-
1
);
if
(
!
shortened
)
{
if
(
!
tex
->
mHeight
)
{
tex
->
pcData
=
new
aiTexel
[
tex
->
mWidth
];
stream
->
Read
(
tex
->
pcData
,
1
,
tex
->
mWidth
);
}
else
{
tex
->
pcData
=
new
aiTexel
[
tex
->
mWidth
*
tex
->
mHeight
];
stream
->
Read
(
tex
->
pcData
,
1
,
tex
->
mWidth
*
tex
->
mHeight
*
4
);
}
}
}
// -----------------------------------------------------------------------------------
void
AssbinImporter
::
ReadBinaryLight
(
IOStream
*
stream
,
aiLight
*
l
)
{
if
(
Read
<
uint32_t
>
(
stream
)
!=
ASSBIN_CHUNK_AILIGHT
)
throw
DeadlyImportError
(
"Magic chunk identifiers are wrong!"
);
/*uint32_t size =*/
Read
<
uint32_t
>
(
stream
);
l
->
mName
=
Read
<
aiString
>
(
stream
);
l
->
mType
=
(
aiLightSourceType
)
Read
<
unsigned
int
>
(
stream
);
if
(
l
->
mType
!=
aiLightSource_DIRECTIONAL
)
{
l
->
mAttenuationConstant
=
Read
<
float
>
(
stream
);
l
->
mAttenuationLinear
=
Read
<
float
>
(
stream
);
l
->
mAttenuationQuadratic
=
Read
<
float
>
(
stream
);
}
l
->
mColorDiffuse
=
Read
<
aiColor3D
>
(
stream
);
l
->
mColorSpecular
=
Read
<
aiColor3D
>
(
stream
);
l
->
mColorAmbient
=
Read
<
aiColor3D
>
(
stream
);
if
(
l
->
mType
==
aiLightSource_SPOT
)
{
l
->
mAngleInnerCone
=
Read
<
float
>
(
stream
);
l
->
mAngleOuterCone
=
Read
<
float
>
(
stream
);
}
}
// -----------------------------------------------------------------------------------
void
AssbinImporter
::
ReadBinaryCamera
(
IOStream
*
stream
,
aiCamera
*
cam
)
{
if
(
Read
<
uint32_t
>
(
stream
)
!=
ASSBIN_CHUNK_AICAMERA
)
throw
DeadlyImportError
(
"Magic chunk identifiers are wrong!"
);
/*uint32_t size =*/
Read
<
uint32_t
>
(
stream
);
cam
->
mName
=
Read
<
aiString
>
(
stream
);
cam
->
mPosition
=
Read
<
aiVector3D
>
(
stream
);
cam
->
mLookAt
=
Read
<
aiVector3D
>
(
stream
);
cam
->
mUp
=
Read
<
aiVector3D
>
(
stream
);
cam
->
mHorizontalFOV
=
Read
<
float
>
(
stream
);
cam
->
mClipPlaneNear
=
Read
<
float
>
(
stream
);
cam
->
mClipPlaneFar
=
Read
<
float
>
(
stream
);
cam
->
mAspect
=
Read
<
float
>
(
stream
);
}
// -----------------------------------------------------------------------------------
void
AssbinImporter
::
ReadBinaryScene
(
IOStream
*
stream
,
aiScene
*
scene
)
{
if
(
Read
<
uint32_t
>
(
stream
)
!=
ASSBIN_CHUNK_AISCENE
)
throw
DeadlyImportError
(
"Magic chunk identifiers are wrong!"
);
/*uint32_t size =*/
Read
<
uint32_t
>
(
stream
);
scene
->
mFlags
=
Read
<
unsigned
int
>
(
stream
);
scene
->
mNumMeshes
=
Read
<
unsigned
int
>
(
stream
);
scene
->
mNumMaterials
=
Read
<
unsigned
int
>
(
stream
);
scene
->
mNumAnimations
=
Read
<
unsigned
int
>
(
stream
);
scene
->
mNumTextures
=
Read
<
unsigned
int
>
(
stream
);
scene
->
mNumLights
=
Read
<
unsigned
int
>
(
stream
);
scene
->
mNumCameras
=
Read
<
unsigned
int
>
(
stream
);
// Read node graph
//scene->mRootNode = new aiNode[1];
ReadBinaryNode
(
stream
,
&
scene
->
mRootNode
,
(
aiNode
*
)
NULL
);
// Read all meshes
if
(
scene
->
mNumMeshes
)
{
scene
->
mMeshes
=
new
aiMesh
*
[
scene
->
mNumMeshes
];
memset
(
scene
->
mMeshes
,
0
,
scene
->
mNumMeshes
*
sizeof
(
aiMesh
*
));
for
(
unsigned
int
i
=
0
;
i
<
scene
->
mNumMeshes
;
++
i
)
{
scene
->
mMeshes
[
i
]
=
new
aiMesh
();
ReadBinaryMesh
(
stream
,
scene
->
mMeshes
[
i
]);
}
}
// Read materials
if
(
scene
->
mNumMaterials
)
{
scene
->
mMaterials
=
new
aiMaterial
*
[
scene
->
mNumMaterials
];
memset
(
scene
->
mMaterials
,
0
,
scene
->
mNumMaterials
*
sizeof
(
aiMaterial
*
));
for
(
unsigned
int
i
=
0
;
i
<
scene
->
mNumMaterials
;
++
i
)
{
scene
->
mMaterials
[
i
]
=
new
aiMaterial
();
ReadBinaryMaterial
(
stream
,
scene
->
mMaterials
[
i
]);
}
}
// Read all animations
if
(
scene
->
mNumAnimations
)
{
scene
->
mAnimations
=
new
aiAnimation
*
[
scene
->
mNumAnimations
];
memset
(
scene
->
mAnimations
,
0
,
scene
->
mNumAnimations
*
sizeof
(
aiAnimation
*
));
for
(
unsigned
int
i
=
0
;
i
<
scene
->
mNumAnimations
;
++
i
)
{
scene
->
mAnimations
[
i
]
=
new
aiAnimation
();
ReadBinaryAnim
(
stream
,
scene
->
mAnimations
[
i
]);
}
}
// Read all textures
if
(
scene
->
mNumTextures
)
{
scene
->
mTextures
=
new
aiTexture
*
[
scene
->
mNumTextures
];
memset
(
scene
->
mTextures
,
0
,
scene
->
mNumTextures
*
sizeof
(
aiTexture
*
));
for
(
unsigned
int
i
=
0
;
i
<
scene
->
mNumTextures
;
++
i
)
{
scene
->
mTextures
[
i
]
=
new
aiTexture
();
ReadBinaryTexture
(
stream
,
scene
->
mTextures
[
i
]);
}
}
// Read lights
if
(
scene
->
mNumLights
)
{
scene
->
mLights
=
new
aiLight
*
[
scene
->
mNumLights
];
memset
(
scene
->
mLights
,
0
,
scene
->
mNumLights
*
sizeof
(
aiLight
*
));
for
(
unsigned
int
i
=
0
;
i
<
scene
->
mNumLights
;
++
i
)
{
scene
->
mLights
[
i
]
=
new
aiLight
();
ReadBinaryLight
(
stream
,
scene
->
mLights
[
i
]);
}
}
// Read cameras
if
(
scene
->
mNumCameras
)
{
scene
->
mCameras
=
new
aiCamera
*
[
scene
->
mNumCameras
];
memset
(
scene
->
mCameras
,
0
,
scene
->
mNumCameras
*
sizeof
(
aiCamera
*
));
for
(
unsigned
int
i
=
0
;
i
<
scene
->
mNumCameras
;
++
i
)
{
scene
->
mCameras
[
i
]
=
new
aiCamera
();
ReadBinaryCamera
(
stream
,
scene
->
mCameras
[
i
]);
}
}
}
// -----------------------------------------------------------------------------------
void
AssbinImporter
::
InternReadFile
(
const
std
::
string
&
pFile
,
aiScene
*
pScene
,
IOSystem
*
pIOHandler
)
{
IOStream
*
stream
=
pIOHandler
->
Open
(
pFile
,
"rb"
);
if
(
nullptr
==
stream
)
{
return
;
}
// signature
stream
->
Seek
(
44
,
aiOrigin_CUR
);
unsigned
int
versionMajor
=
Read
<
unsigned
int
>
(
stream
);
unsigned
int
versionMinor
=
Read
<
unsigned
int
>
(
stream
);
if
(
versionMinor
!=
ASSBIN_VERSION_MINOR
||
versionMajor
!=
ASSBIN_VERSION_MAJOR
)
{
throw
DeadlyImportError
(
"Invalid version, data format not compatible!"
);
}
/*unsigned int versionRevision =*/
Read
<
unsigned
int
>
(
stream
);
/*unsigned int compileFlags =*/
Read
<
unsigned
int
>
(
stream
);
shortened
=
Read
<
uint16_t
>
(
stream
)
>
0
;
compressed
=
Read
<
uint16_t
>
(
stream
)
>
0
;
if
(
shortened
)
throw
DeadlyImportError
(
"Shortened binaries are not supported!"
);
stream
->
Seek
(
256
,
aiOrigin_CUR
);
// original filename
stream
->
Seek
(
128
,
aiOrigin_CUR
);
// options
stream
->
Seek
(
64
,
aiOrigin_CUR
);
// padding
if
(
compressed
)
{
uLongf
uncompressedSize
=
Read
<
uint32_t
>
(
stream
);
uLongf
compressedSize
=
static_cast
<
uLongf
>
(
stream
->
FileSize
()
-
stream
->
Tell
());
unsigned
char
*
compressedData
=
new
unsigned
char
[
compressedSize
];
size_t
len
=
stream
->
Read
(
compressedData
,
1
,
compressedSize
);
ai_assert
(
len
==
compressedSize
);
unsigned
char
*
uncompressedData
=
new
unsigned
char
[
uncompressedSize
];
int
res
=
uncompress
(
uncompressedData
,
&
uncompressedSize
,
compressedData
,
(
uLong
)
len
);
if
(
res
!=
Z_OK
)
{
delete
[]
uncompressedData
;
delete
[]
compressedData
;
pIOHandler
->
Close
(
stream
);
throw
DeadlyImportError
(
"Zlib decompression failed."
);
}
MemoryIOStream
io
(
uncompressedData
,
uncompressedSize
);
ReadBinaryScene
(
&
io
,
pScene
);
delete
[]
uncompressedData
;
delete
[]
compressedData
;
}
else
{
ReadBinaryScene
(
stream
,
pScene
);
}
pIOHandler
->
Close
(
stream
);
}
#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER
deps/assimp/code/AssetLib/Assbin/AssbinLoader.h
0 → 100644
View file @
c6fcf2f0
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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 AssbinLoader.h
* @brief .assbin File format loader
*/
#ifndef AI_ASSBINIMPORTER_H_INC
#define AI_ASSBINIMPORTER_H_INC
#include <assimp/BaseImporter.h>
struct
aiMesh
;
struct
aiNode
;
struct
aiBone
;
struct
aiMaterial
;
struct
aiMaterialProperty
;
struct
aiNodeAnim
;
struct
aiAnimation
;
struct
aiTexture
;
struct
aiLight
;
struct
aiCamera
;
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
namespace
Assimp
{
// ---------------------------------------------------------------------------------
/** Importer class for 3D Studio r3 and r4 3DS files
*/
class
AssbinImporter
:
public
BaseImporter
{
private:
bool
shortened
;
bool
compressed
;
public:
virtual
bool
CanRead
(
const
std
::
string
&
pFile
,
IOSystem
*
pIOHandler
,
bool
checkSig
)
const
;
virtual
const
aiImporterDesc
*
GetInfo
()
const
;
virtual
void
InternReadFile
(
const
std
::
string
&
pFile
,
aiScene
*
pScene
,
IOSystem
*
pIOHandler
);
void
ReadHeader
();
void
ReadBinaryScene
(
IOStream
*
stream
,
aiScene
*
pScene
);
void
ReadBinaryNode
(
IOStream
*
stream
,
aiNode
**
mRootNode
,
aiNode
*
parent
);
void
ReadBinaryMesh
(
IOStream
*
stream
,
aiMesh
*
mesh
);
void
ReadBinaryBone
(
IOStream
*
stream
,
aiBone
*
bone
);
void
ReadBinaryMaterial
(
IOStream
*
stream
,
aiMaterial
*
mat
);
void
ReadBinaryMaterialProperty
(
IOStream
*
stream
,
aiMaterialProperty
*
prop
);
void
ReadBinaryNodeAnim
(
IOStream
*
stream
,
aiNodeAnim
*
nd
);
void
ReadBinaryAnim
(
IOStream
*
stream
,
aiAnimation
*
anim
);
void
ReadBinaryTexture
(
IOStream
*
stream
,
aiTexture
*
tex
);
void
ReadBinaryLight
(
IOStream
*
stream
,
aiLight
*
l
);
void
ReadBinaryCamera
(
IOStream
*
stream
,
aiCamera
*
cam
);
};
}
// end of namespace Assimp
#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER
#endif // AI_ASSBINIMPORTER_H_INC
deps/assimp/code/AssetLib/Assjson/cencode.c
0 → 100644
View file @
c6fcf2f0
/*
cencoder.c - c source to a base64 encoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#include "cencode.h" // changed from <B64/cencode.h>
const
int
CHARS_PER_LINE
=
72
;
#pragma warning(push)
#pragma warning(disable : 4244)
void
base64_init_encodestate
(
base64_encodestate
*
state_in
)
{
state_in
->
step
=
step_A
;
state_in
->
result
=
0
;
state_in
->
stepcount
=
0
;
}
char
base64_encode_value
(
char
value_in
)
{
static
const
char
*
encoding
=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
;
if
(
value_in
>
63
)
return
'='
;
return
encoding
[(
int
)
value_in
];
}
int
base64_encode_block
(
const
char
*
plaintext_in
,
int
length_in
,
char
*
code_out
,
base64_encodestate
*
state_in
)
{
const
char
*
plainchar
=
plaintext_in
;
const
char
*
const
plaintextend
=
plaintext_in
+
length_in
;
char
*
codechar
=
code_out
;
char
result
;
char
fragment
;
result
=
state_in
->
result
;
switch
(
state_in
->
step
)
{
while
(
1
)
{
case
step_A
:
if
(
plainchar
==
plaintextend
)
{
state_in
->
result
=
result
;
state_in
->
step
=
step_A
;
return
(
int
)(
codechar
-
code_out
);
}
fragment
=
*
plainchar
++
;
result
=
(
fragment
&
0x0fc
)
>>
2
;
*
codechar
++
=
base64_encode_value
(
result
);
result
=
(
fragment
&
0x003
)
<<
4
;
case
step_B
:
if
(
plainchar
==
plaintextend
)
{
state_in
->
result
=
result
;
state_in
->
step
=
step_B
;
return
(
int
)(
codechar
-
code_out
);
}
fragment
=
*
plainchar
++
;
result
|=
(
fragment
&
0x0f0
)
>>
4
;
*
codechar
++
=
base64_encode_value
(
result
);
result
=
(
fragment
&
0x00f
)
<<
2
;
case
step_C
:
if
(
plainchar
==
plaintextend
)
{
state_in
->
result
=
result
;
state_in
->
step
=
step_C
;
return
(
int
)(
codechar
-
code_out
);
}
fragment
=
*
plainchar
++
;
result
|=
(
fragment
&
0x0c0
)
>>
6
;
*
codechar
++
=
base64_encode_value
(
result
);
result
=
(
fragment
&
0x03f
)
>>
0
;
*
codechar
++
=
base64_encode_value
(
result
);
++
(
state_in
->
stepcount
);
if
(
state_in
->
stepcount
==
CHARS_PER_LINE
/
4
)
{
*
codechar
++
=
'\n'
;
state_in
->
stepcount
=
0
;
}
}
}
/* control should not reach here */
return
(
int
)(
codechar
-
code_out
);
}
int
base64_encode_blockend
(
char
*
code_out
,
base64_encodestate
*
state_in
)
{
char
*
codechar
=
code_out
;
switch
(
state_in
->
step
)
{
case
step_B
:
*
codechar
++
=
base64_encode_value
(
state_in
->
result
);
*
codechar
++
=
'='
;
*
codechar
++
=
'='
;
break
;
case
step_C
:
*
codechar
++
=
base64_encode_value
(
state_in
->
result
);
*
codechar
++
=
'='
;
break
;
case
step_A
:
break
;
}
*
codechar
++
=
'\n'
;
return
(
int
)(
codechar
-
code_out
);
}
#pragma warning(pop)
deps/assimp/code/AssetLib/Assjson/cencode.h
0 → 100644
View file @
c6fcf2f0
/*
cencode.h - c header for a base64 encoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_CENCODE_H
#define BASE64_CENCODE_H
#ifdef _WIN32
#pragma warning(disable : 4127 )
#endif // _WIN32
typedef
enum
{
step_A
,
step_B
,
step_C
}
base64_encodestep
;
typedef
struct
{
base64_encodestep
step
;
char
result
;
int
stepcount
;
}
base64_encodestate
;
void
base64_init_encodestate
(
base64_encodestate
*
state_in
);
char
base64_encode_value
(
char
value_in
);
int
base64_encode_block
(
const
char
*
plaintext_in
,
int
length_in
,
char
*
code_out
,
base64_encodestate
*
state_in
);
int
base64_encode_blockend
(
char
*
code_out
,
base64_encodestate
*
state_in
);
#endif
/* BASE64_CENCODE_H */
deps/assimp/code/AssetLib/Assjson/json_exporter.cpp
0 → 100644
View file @
c6fcf2f0
/*
Assimp2Json
Copyright (c) 2011, Alexander C. Gessler
Licensed under a 3-clause BSD license. See the LICENSE file for more information.
*/
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
#include <assimp/scene.h>
#include <assimp/Exporter.hpp>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/Importer.hpp>
#include <assimp/Exceptional.h>
#include <cassert>
#include <limits>
#include <memory>
#include <sstream>
#define CURRENT_FORMAT_VERSION 100
// grab scoped_ptr from assimp to avoid a dependency on boost.
//#include <assimp/../../code/BoostWorkaround/boost/scoped_ptr.hpp>
#include "mesh_splitter.h"
extern
"C"
{
#include "cencode.h"
}
namespace
Assimp
{
void
ExportAssimp2Json
(
const
char
*
,
Assimp
::
IOSystem
*
,
const
aiScene
*
,
const
Assimp
::
ExportProperties
*
);
// small utility class to simplify serializing the aiScene to Json
class
JSONWriter
{
public:
enum
{
Flag_DoNotIndent
=
0x1
,
Flag_WriteSpecialFloats
=
0x2
,
};
JSONWriter
(
Assimp
::
IOStream
&
out
,
unsigned
int
flags
=
0u
)
:
out
(
out
),
first
(),
flags
(
flags
)
{
// make sure that all formatting happens using the standard, C locale and not the user's current locale
buff
.
imbue
(
std
::
locale
(
"C"
));
}
~
JSONWriter
()
{
Flush
();
}
void
Flush
()
{
const
std
::
string
s
=
buff
.
str
();
out
.
Write
(
s
.
c_str
(),
s
.
length
(),
1
);
buff
.
clear
();
}
void
PushIndent
()
{
indent
+=
'\t'
;
}
void
PopIndent
()
{
indent
.
erase
(
indent
.
end
()
-
1
);
}
void
Key
(
const
std
::
string
&
name
)
{
AddIndentation
();
Delimit
();
buff
<<
'\"'
+
name
+
"
\"
: "
;
}
template
<
typename
Literal
>
void
Element
(
const
Literal
&
name
)
{
AddIndentation
();
Delimit
();
LiteralToString
(
buff
,
name
)
<<
'\n'
;
}
template
<
typename
Literal
>
void
SimpleValue
(
const
Literal
&
s
)
{
LiteralToString
(
buff
,
s
)
<<
'\n'
;
}
void
SimpleValue
(
const
void
*
buffer
,
size_t
len
)
{
base64_encodestate
s
;
base64_init_encodestate
(
&
s
);
char
*
const
cur_out
=
new
char
[
std
::
max
(
len
*
2
,
static_cast
<
size_t
>
(
16u
))];
const
int
n
=
base64_encode_block
(
reinterpret_cast
<
const
char
*>
(
buffer
),
static_cast
<
int
>
(
len
),
cur_out
,
&
s
);
cur_out
[
n
+
base64_encode_blockend
(
cur_out
+
n
,
&
s
)]
=
'\0'
;
// base64 encoding may add newlines, but JSON strings may not contain 'real' newlines
// (only escaped ones). Remove any newlines in out.
for
(
char
*
cur
=
cur_out
;
*
cur
;
++
cur
)
{
if
(
*
cur
==
'\n'
)
{
*
cur
=
' '
;
}
}
buff
<<
'\"'
<<
cur_out
<<
"
\"\n
"
;
delete
[]
cur_out
;
}
void
StartObj
(
bool
is_element
=
false
)
{
// if this appears as a plain array element, we need to insert a delimiter and we should also indent it
if
(
is_element
)
{
AddIndentation
();
if
(
!
first
)
{
buff
<<
','
;
}
}
first
=
true
;
buff
<<
"{
\n
"
;
PushIndent
();
}
void
EndObj
()
{
PopIndent
();
AddIndentation
();
first
=
false
;
buff
<<
"}
\n
"
;
}
void
StartArray
(
bool
is_element
=
false
)
{
// if this appears as a plain array element, we need to insert a delimiter and we should also indent it
if
(
is_element
)
{
AddIndentation
();
if
(
!
first
)
{
buff
<<
','
;
}
}
first
=
true
;
buff
<<
"[
\n
"
;
PushIndent
();
}
void
EndArray
()
{
PopIndent
();
AddIndentation
();
buff
<<
"]
\n
"
;
first
=
false
;
}
void
AddIndentation
()
{
if
(
!
(
flags
&
Flag_DoNotIndent
))
{
buff
<<
indent
;
}
}
void
Delimit
()
{
if
(
!
first
)
{
buff
<<
','
;
}
else
{
buff
<<
' '
;
first
=
false
;
}
}
private:
template
<
typename
Literal
>
std
::
stringstream
&
LiteralToString
(
std
::
stringstream
&
stream
,
const
Literal
&
s
)
{
stream
<<
s
;
return
stream
;
}
std
::
stringstream
&
LiteralToString
(
std
::
stringstream
&
stream
,
const
aiString
&
s
)
{
std
::
string
t
;
// escape backslashes and single quotes, both would render the JSON invalid if left as is
t
.
reserve
(
s
.
length
);
for
(
size_t
i
=
0
;
i
<
s
.
length
;
++
i
)
{
if
(
s
.
data
[
i
]
==
'\\'
||
s
.
data
[
i
]
==
'\''
||
s
.
data
[
i
]
==
'\"'
)
{
t
.
push_back
(
'\\'
);
}
t
.
push_back
(
s
.
data
[
i
]);
}
stream
<<
"
\"
"
;
stream
<<
t
;
stream
<<
"
\"
"
;
return
stream
;
}
std
::
stringstream
&
LiteralToString
(
std
::
stringstream
&
stream
,
float
f
)
{
if
(
!
std
::
numeric_limits
<
float
>::
is_iec559
)
{
// on a non IEEE-754 platform, we make no assumptions about the representation or existence
// of special floating-point numbers.
stream
<<
f
;
return
stream
;
}
// JSON does not support writing Inf/Nan
// [RFC 4672: "Numeric values that cannot be represented as sequences of digits
// (such as Infinity and NaN) are not permitted."]
// Nevertheless, many parsers will accept the special keywords Infinity, -Infinity and NaN
if
(
std
::
numeric_limits
<
float
>::
infinity
()
==
fabs
(
f
))
{
if
(
flags
&
Flag_WriteSpecialFloats
)
{
stream
<<
(
f
<
0
?
"
\"
-"
:
"
\"
"
)
+
std
::
string
(
"Infinity
\"
"
);
return
stream
;
}
// we should print this warning, but we can't - this is called from within a generic assimp exporter, we cannot use cerr
// std::cerr << "warning: cannot represent infinite number literal, substituting 0 instead (use -i flag to enforce Infinity/NaN)" << std::endl;
stream
<<
"0.0"
;
return
stream
;
}
// f!=f is the most reliable test for NaNs that I know of
else
if
(
f
!=
f
)
{
if
(
flags
&
Flag_WriteSpecialFloats
)
{
stream
<<
"
\"
NaN
\"
"
;
return
stream
;
}
// we should print this warning, but we can't - this is called from within a generic assimp exporter, we cannot use cerr
// std::cerr << "warning: cannot represent infinite number literal, substituting 0 instead (use -i flag to enforce Infinity/NaN)" << std::endl;
stream
<<
"0.0"
;
return
stream
;
}
stream
<<
f
;
return
stream
;
}
private:
Assimp
::
IOStream
&
out
;
std
::
string
indent
,
newline
;
std
::
stringstream
buff
;
bool
first
;
unsigned
int
flags
;
};
void
Write
(
JSONWriter
&
out
,
const
aiVector3D
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartArray
(
is_elem
);
out
.
Element
(
ai
.
x
);
out
.
Element
(
ai
.
y
);
out
.
Element
(
ai
.
z
);
out
.
EndArray
();
}
void
Write
(
JSONWriter
&
out
,
const
aiQuaternion
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartArray
(
is_elem
);
out
.
Element
(
ai
.
w
);
out
.
Element
(
ai
.
x
);
out
.
Element
(
ai
.
y
);
out
.
Element
(
ai
.
z
);
out
.
EndArray
();
}
void
Write
(
JSONWriter
&
out
,
const
aiColor3D
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartArray
(
is_elem
);
out
.
Element
(
ai
.
r
);
out
.
Element
(
ai
.
g
);
out
.
Element
(
ai
.
b
);
out
.
EndArray
();
}
void
Write
(
JSONWriter
&
out
,
const
aiMatrix4x4
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartArray
(
is_elem
);
for
(
unsigned
int
x
=
0
;
x
<
4
;
++
x
)
{
for
(
unsigned
int
y
=
0
;
y
<
4
;
++
y
)
{
out
.
Element
(
ai
[
x
][
y
]);
}
}
out
.
EndArray
();
}
void
Write
(
JSONWriter
&
out
,
const
aiBone
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartObj
(
is_elem
);
out
.
Key
(
"name"
);
out
.
SimpleValue
(
ai
.
mName
);
out
.
Key
(
"offsetmatrix"
);
Write
(
out
,
ai
.
mOffsetMatrix
,
false
);
out
.
Key
(
"weights"
);
out
.
StartArray
();
for
(
unsigned
int
i
=
0
;
i
<
ai
.
mNumWeights
;
++
i
)
{
out
.
StartArray
(
true
);
out
.
Element
(
ai
.
mWeights
[
i
].
mVertexId
);
out
.
Element
(
ai
.
mWeights
[
i
].
mWeight
);
out
.
EndArray
();
}
out
.
EndArray
();
out
.
EndObj
();
}
void
Write
(
JSONWriter
&
out
,
const
aiFace
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartArray
(
is_elem
);
for
(
unsigned
int
i
=
0
;
i
<
ai
.
mNumIndices
;
++
i
)
{
out
.
Element
(
ai
.
mIndices
[
i
]);
}
out
.
EndArray
();
}
void
Write
(
JSONWriter
&
out
,
const
aiMesh
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartObj
(
is_elem
);
out
.
Key
(
"name"
);
out
.
SimpleValue
(
ai
.
mName
);
out
.
Key
(
"materialindex"
);
out
.
SimpleValue
(
ai
.
mMaterialIndex
);
out
.
Key
(
"primitivetypes"
);
out
.
SimpleValue
(
ai
.
mPrimitiveTypes
);
out
.
Key
(
"vertices"
);
out
.
StartArray
();
for
(
unsigned
int
i
=
0
;
i
<
ai
.
mNumVertices
;
++
i
)
{
out
.
Element
(
ai
.
mVertices
[
i
].
x
);
out
.
Element
(
ai
.
mVertices
[
i
].
y
);
out
.
Element
(
ai
.
mVertices
[
i
].
z
);
}
out
.
EndArray
();
if
(
ai
.
HasNormals
())
{
out
.
Key
(
"normals"
);
out
.
StartArray
();
for
(
unsigned
int
i
=
0
;
i
<
ai
.
mNumVertices
;
++
i
)
{
out
.
Element
(
ai
.
mNormals
[
i
].
x
);
out
.
Element
(
ai
.
mNormals
[
i
].
y
);
out
.
Element
(
ai
.
mNormals
[
i
].
z
);
}
out
.
EndArray
();
}
if
(
ai
.
HasTangentsAndBitangents
())
{
out
.
Key
(
"tangents"
);
out
.
StartArray
();
for
(
unsigned
int
i
=
0
;
i
<
ai
.
mNumVertices
;
++
i
)
{
out
.
Element
(
ai
.
mTangents
[
i
].
x
);
out
.
Element
(
ai
.
mTangents
[
i
].
y
);
out
.
Element
(
ai
.
mTangents
[
i
].
z
);
}
out
.
EndArray
();
out
.
Key
(
"bitangents"
);
out
.
StartArray
();
for
(
unsigned
int
i
=
0
;
i
<
ai
.
mNumVertices
;
++
i
)
{
out
.
Element
(
ai
.
mBitangents
[
i
].
x
);
out
.
Element
(
ai
.
mBitangents
[
i
].
y
);
out
.
Element
(
ai
.
mBitangents
[
i
].
z
);
}
out
.
EndArray
();
}
if
(
ai
.
GetNumUVChannels
())
{
out
.
Key
(
"numuvcomponents"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
GetNumUVChannels
();
++
n
)
{
out
.
Element
(
ai
.
mNumUVComponents
[
n
]);
}
out
.
EndArray
();
out
.
Key
(
"texturecoords"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
GetNumUVChannels
();
++
n
)
{
const
unsigned
int
numc
=
ai
.
mNumUVComponents
[
n
]
?
ai
.
mNumUVComponents
[
n
]
:
2
;
out
.
StartArray
(
true
);
for
(
unsigned
int
i
=
0
;
i
<
ai
.
mNumVertices
;
++
i
)
{
for
(
unsigned
int
c
=
0
;
c
<
numc
;
++
c
)
{
out
.
Element
(
ai
.
mTextureCoords
[
n
][
i
][
c
]);
}
}
out
.
EndArray
();
}
out
.
EndArray
();
}
if
(
ai
.
GetNumColorChannels
())
{
out
.
Key
(
"colors"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
GetNumColorChannels
();
++
n
)
{
out
.
StartArray
(
true
);
for
(
unsigned
int
i
=
0
;
i
<
ai
.
mNumVertices
;
++
i
)
{
out
.
Element
(
ai
.
mColors
[
n
][
i
].
r
);
out
.
Element
(
ai
.
mColors
[
n
][
i
].
g
);
out
.
Element
(
ai
.
mColors
[
n
][
i
].
b
);
out
.
Element
(
ai
.
mColors
[
n
][
i
].
a
);
}
out
.
EndArray
();
}
out
.
EndArray
();
}
if
(
ai
.
mNumBones
)
{
out
.
Key
(
"bones"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumBones
;
++
n
)
{
Write
(
out
,
*
ai
.
mBones
[
n
]);
}
out
.
EndArray
();
}
out
.
Key
(
"faces"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumFaces
;
++
n
)
{
Write
(
out
,
ai
.
mFaces
[
n
]);
}
out
.
EndArray
();
out
.
EndObj
();
}
void
Write
(
JSONWriter
&
out
,
const
aiNode
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartObj
(
is_elem
);
out
.
Key
(
"name"
);
out
.
SimpleValue
(
ai
.
mName
);
out
.
Key
(
"transformation"
);
Write
(
out
,
ai
.
mTransformation
,
false
);
if
(
ai
.
mNumMeshes
)
{
out
.
Key
(
"meshes"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumMeshes
;
++
n
)
{
out
.
Element
(
ai
.
mMeshes
[
n
]);
}
out
.
EndArray
();
}
if
(
ai
.
mNumChildren
)
{
out
.
Key
(
"children"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumChildren
;
++
n
)
{
Write
(
out
,
*
ai
.
mChildren
[
n
]);
}
out
.
EndArray
();
}
out
.
EndObj
();
}
void
Write
(
JSONWriter
&
out
,
const
aiMaterial
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartObj
(
is_elem
);
out
.
Key
(
"properties"
);
out
.
StartArray
();
for
(
unsigned
int
i
=
0
;
i
<
ai
.
mNumProperties
;
++
i
)
{
const
aiMaterialProperty
*
const
prop
=
ai
.
mProperties
[
i
];
out
.
StartObj
(
true
);
out
.
Key
(
"key"
);
out
.
SimpleValue
(
prop
->
mKey
);
out
.
Key
(
"semantic"
);
out
.
SimpleValue
(
prop
->
mSemantic
);
out
.
Key
(
"index"
);
out
.
SimpleValue
(
prop
->
mIndex
);
out
.
Key
(
"type"
);
out
.
SimpleValue
(
prop
->
mType
);
out
.
Key
(
"value"
);
switch
(
prop
->
mType
)
{
case
aiPTI_Float
:
if
(
prop
->
mDataLength
/
sizeof
(
float
)
>
1
)
{
out
.
StartArray
();
for
(
unsigned
int
ii
=
0
;
ii
<
prop
->
mDataLength
/
sizeof
(
float
);
++
ii
)
{
out
.
Element
(
reinterpret_cast
<
float
*>
(
prop
->
mData
)[
ii
]);
}
out
.
EndArray
();
}
else
{
out
.
SimpleValue
(
*
reinterpret_cast
<
float
*>
(
prop
->
mData
));
}
break
;
case
aiPTI_Integer
:
if
(
prop
->
mDataLength
/
sizeof
(
int
)
>
1
)
{
out
.
StartArray
();
for
(
unsigned
int
ii
=
0
;
ii
<
prop
->
mDataLength
/
sizeof
(
int
);
++
ii
)
{
out
.
Element
(
reinterpret_cast
<
int
*>
(
prop
->
mData
)[
ii
]);
}
out
.
EndArray
();
}
else
{
out
.
SimpleValue
(
*
reinterpret_cast
<
int
*>
(
prop
->
mData
));
}
break
;
case
aiPTI_String
:
{
aiString
s
;
aiGetMaterialString
(
&
ai
,
prop
->
mKey
.
data
,
prop
->
mSemantic
,
prop
->
mIndex
,
&
s
);
out
.
SimpleValue
(
s
);
}
break
;
case
aiPTI_Buffer
:
{
// binary data is written as series of hex-encoded octets
out
.
SimpleValue
(
prop
->
mData
,
prop
->
mDataLength
);
}
break
;
default:
assert
(
false
);
}
out
.
EndObj
();
}
out
.
EndArray
();
out
.
EndObj
();
}
void
Write
(
JSONWriter
&
out
,
const
aiTexture
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartObj
(
is_elem
);
out
.
Key
(
"width"
);
out
.
SimpleValue
(
ai
.
mWidth
);
out
.
Key
(
"height"
);
out
.
SimpleValue
(
ai
.
mHeight
);
out
.
Key
(
"formathint"
);
out
.
SimpleValue
(
aiString
(
ai
.
achFormatHint
));
out
.
Key
(
"data"
);
if
(
!
ai
.
mHeight
)
{
out
.
SimpleValue
(
ai
.
pcData
,
ai
.
mWidth
);
}
else
{
out
.
StartArray
();
for
(
unsigned
int
y
=
0
;
y
<
ai
.
mHeight
;
++
y
)
{
out
.
StartArray
(
true
);
for
(
unsigned
int
x
=
0
;
x
<
ai
.
mWidth
;
++
x
)
{
const
aiTexel
&
tx
=
ai
.
pcData
[
y
*
ai
.
mWidth
+
x
];
out
.
StartArray
(
true
);
out
.
Element
(
static_cast
<
unsigned
int
>
(
tx
.
r
));
out
.
Element
(
static_cast
<
unsigned
int
>
(
tx
.
g
));
out
.
Element
(
static_cast
<
unsigned
int
>
(
tx
.
b
));
out
.
Element
(
static_cast
<
unsigned
int
>
(
tx
.
a
));
out
.
EndArray
();
}
out
.
EndArray
();
}
out
.
EndArray
();
}
out
.
EndObj
();
}
void
Write
(
JSONWriter
&
out
,
const
aiLight
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartObj
(
is_elem
);
out
.
Key
(
"name"
);
out
.
SimpleValue
(
ai
.
mName
);
out
.
Key
(
"type"
);
out
.
SimpleValue
(
ai
.
mType
);
if
(
ai
.
mType
==
aiLightSource_SPOT
||
ai
.
mType
==
aiLightSource_UNDEFINED
)
{
out
.
Key
(
"angleinnercone"
);
out
.
SimpleValue
(
ai
.
mAngleInnerCone
);
out
.
Key
(
"angleoutercone"
);
out
.
SimpleValue
(
ai
.
mAngleOuterCone
);
}
out
.
Key
(
"attenuationconstant"
);
out
.
SimpleValue
(
ai
.
mAttenuationConstant
);
out
.
Key
(
"attenuationlinear"
);
out
.
SimpleValue
(
ai
.
mAttenuationLinear
);
out
.
Key
(
"attenuationquadratic"
);
out
.
SimpleValue
(
ai
.
mAttenuationQuadratic
);
out
.
Key
(
"diffusecolor"
);
Write
(
out
,
ai
.
mColorDiffuse
,
false
);
out
.
Key
(
"specularcolor"
);
Write
(
out
,
ai
.
mColorSpecular
,
false
);
out
.
Key
(
"ambientcolor"
);
Write
(
out
,
ai
.
mColorAmbient
,
false
);
if
(
ai
.
mType
!=
aiLightSource_POINT
)
{
out
.
Key
(
"direction"
);
Write
(
out
,
ai
.
mDirection
,
false
);
}
if
(
ai
.
mType
!=
aiLightSource_DIRECTIONAL
)
{
out
.
Key
(
"position"
);
Write
(
out
,
ai
.
mPosition
,
false
);
}
out
.
EndObj
();
}
void
Write
(
JSONWriter
&
out
,
const
aiNodeAnim
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartObj
(
is_elem
);
out
.
Key
(
"name"
);
out
.
SimpleValue
(
ai
.
mNodeName
);
out
.
Key
(
"prestate"
);
out
.
SimpleValue
(
ai
.
mPreState
);
out
.
Key
(
"poststate"
);
out
.
SimpleValue
(
ai
.
mPostState
);
if
(
ai
.
mNumPositionKeys
)
{
out
.
Key
(
"positionkeys"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumPositionKeys
;
++
n
)
{
const
aiVectorKey
&
pos
=
ai
.
mPositionKeys
[
n
];
out
.
StartArray
(
true
);
out
.
Element
(
pos
.
mTime
);
Write
(
out
,
pos
.
mValue
);
out
.
EndArray
();
}
out
.
EndArray
();
}
if
(
ai
.
mNumRotationKeys
)
{
out
.
Key
(
"rotationkeys"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumRotationKeys
;
++
n
)
{
const
aiQuatKey
&
rot
=
ai
.
mRotationKeys
[
n
];
out
.
StartArray
(
true
);
out
.
Element
(
rot
.
mTime
);
Write
(
out
,
rot
.
mValue
);
out
.
EndArray
();
}
out
.
EndArray
();
}
if
(
ai
.
mNumScalingKeys
)
{
out
.
Key
(
"scalingkeys"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumScalingKeys
;
++
n
)
{
const
aiVectorKey
&
scl
=
ai
.
mScalingKeys
[
n
];
out
.
StartArray
(
true
);
out
.
Element
(
scl
.
mTime
);
Write
(
out
,
scl
.
mValue
);
out
.
EndArray
();
}
out
.
EndArray
();
}
out
.
EndObj
();
}
void
Write
(
JSONWriter
&
out
,
const
aiAnimation
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartObj
(
is_elem
);
out
.
Key
(
"name"
);
out
.
SimpleValue
(
ai
.
mName
);
out
.
Key
(
"tickspersecond"
);
out
.
SimpleValue
(
ai
.
mTicksPerSecond
);
out
.
Key
(
"duration"
);
out
.
SimpleValue
(
ai
.
mDuration
);
out
.
Key
(
"channels"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumChannels
;
++
n
)
{
Write
(
out
,
*
ai
.
mChannels
[
n
]);
}
out
.
EndArray
();
out
.
EndObj
();
}
void
Write
(
JSONWriter
&
out
,
const
aiCamera
&
ai
,
bool
is_elem
=
true
)
{
out
.
StartObj
(
is_elem
);
out
.
Key
(
"name"
);
out
.
SimpleValue
(
ai
.
mName
);
out
.
Key
(
"aspect"
);
out
.
SimpleValue
(
ai
.
mAspect
);
out
.
Key
(
"clipplanefar"
);
out
.
SimpleValue
(
ai
.
mClipPlaneFar
);
out
.
Key
(
"clipplanenear"
);
out
.
SimpleValue
(
ai
.
mClipPlaneNear
);
out
.
Key
(
"horizontalfov"
);
out
.
SimpleValue
(
ai
.
mHorizontalFOV
);
out
.
Key
(
"up"
);
Write
(
out
,
ai
.
mUp
,
false
);
out
.
Key
(
"lookat"
);
Write
(
out
,
ai
.
mLookAt
,
false
);
out
.
EndObj
();
}
void
WriteFormatInfo
(
JSONWriter
&
out
)
{
out
.
StartObj
();
out
.
Key
(
"format"
);
out
.
SimpleValue
(
"
\"
assimp2json
\"
"
);
out
.
Key
(
"version"
);
out
.
SimpleValue
(
CURRENT_FORMAT_VERSION
);
out
.
EndObj
();
}
void
Write
(
JSONWriter
&
out
,
const
aiScene
&
ai
)
{
out
.
StartObj
();
out
.
Key
(
"__metadata__"
);
WriteFormatInfo
(
out
);
out
.
Key
(
"rootnode"
);
Write
(
out
,
*
ai
.
mRootNode
,
false
);
out
.
Key
(
"flags"
);
out
.
SimpleValue
(
ai
.
mFlags
);
if
(
ai
.
HasMeshes
())
{
out
.
Key
(
"meshes"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumMeshes
;
++
n
)
{
Write
(
out
,
*
ai
.
mMeshes
[
n
]);
}
out
.
EndArray
();
}
if
(
ai
.
HasMaterials
())
{
out
.
Key
(
"materials"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumMaterials
;
++
n
)
{
Write
(
out
,
*
ai
.
mMaterials
[
n
]);
}
out
.
EndArray
();
}
if
(
ai
.
HasAnimations
())
{
out
.
Key
(
"animations"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumAnimations
;
++
n
)
{
Write
(
out
,
*
ai
.
mAnimations
[
n
]);
}
out
.
EndArray
();
}
if
(
ai
.
HasLights
())
{
out
.
Key
(
"lights"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumLights
;
++
n
)
{
Write
(
out
,
*
ai
.
mLights
[
n
]);
}
out
.
EndArray
();
}
if
(
ai
.
HasCameras
())
{
out
.
Key
(
"cameras"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumCameras
;
++
n
)
{
Write
(
out
,
*
ai
.
mCameras
[
n
]);
}
out
.
EndArray
();
}
if
(
ai
.
HasTextures
())
{
out
.
Key
(
"textures"
);
out
.
StartArray
();
for
(
unsigned
int
n
=
0
;
n
<
ai
.
mNumTextures
;
++
n
)
{
Write
(
out
,
*
ai
.
mTextures
[
n
]);
}
out
.
EndArray
();
}
out
.
EndObj
();
}
void
ExportAssimp2Json
(
const
char
*
file
,
Assimp
::
IOSystem
*
io
,
const
aiScene
*
scene
,
const
Assimp
::
ExportProperties
*
)
{
std
::
unique_ptr
<
Assimp
::
IOStream
>
str
(
io
->
Open
(
file
,
"wt"
));
if
(
!
str
)
{
throw
DeadlyExportError
(
"could not open output file"
);
}
// get a copy of the scene so we can modify it
aiScene
*
scenecopy_tmp
;
aiCopyScene
(
scene
,
&
scenecopy_tmp
);
try
{
// split meshes so they fit into a 16 bit index buffer
MeshSplitter
splitter
;
splitter
.
SetLimit
(
1
<<
16
);
splitter
.
Execute
(
scenecopy_tmp
);
// XXX Flag_WriteSpecialFloats is turned on by default, right now we don't have a configuration interface for exporters
JSONWriter
s
(
*
str
,
JSONWriter
::
Flag_WriteSpecialFloats
);
Write
(
s
,
*
scenecopy_tmp
);
}
catch
(...)
{
aiFreeScene
(
scenecopy_tmp
);
throw
;
}
aiFreeScene
(
scenecopy_tmp
);
}
}
// namespace Assimp
#endif // ASSIMP_BUILD_NO_ASSJSON_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT
deps/assimp/code/AssetLib/Assjson/mesh_splitter.cpp
0 → 100644
View file @
c6fcf2f0
/*
Assimp2Json
Copyright (c) 2011, Alexander C. Gessler
Licensed under a 3-clause BSD license. See the LICENSE file for more information.
*/
#include "mesh_splitter.h"
#include <assimp/scene.h>
// ----------------------------------------------------------------------------
// Note: this is largely based on assimp's SplitLargeMeshes_Vertex process.
// it is refactored and the coding style is slightly improved, though.
// ----------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void
MeshSplitter
::
Execute
(
aiScene
*
pScene
)
{
std
::
vector
<
std
::
pair
<
aiMesh
*
,
unsigned
int
>
>
source_mesh_map
;
for
(
unsigned
int
a
=
0
;
a
<
pScene
->
mNumMeshes
;
a
++
)
{
SplitMesh
(
a
,
pScene
->
mMeshes
[
a
],
source_mesh_map
);
}
const
unsigned
int
size
=
static_cast
<
unsigned
int
>
(
source_mesh_map
.
size
());
if
(
size
!=
pScene
->
mNumMeshes
)
{
// it seems something has been split. rebuild the mesh list
delete
[]
pScene
->
mMeshes
;
pScene
->
mNumMeshes
=
size
;
pScene
->
mMeshes
=
new
aiMesh
*
[
size
]();
for
(
unsigned
int
i
=
0
;
i
<
size
;
++
i
)
{
pScene
->
mMeshes
[
i
]
=
source_mesh_map
[
i
].
first
;
}
// now we need to update all nodes
UpdateNode
(
pScene
->
mRootNode
,
source_mesh_map
);
}
}
// ------------------------------------------------------------------------------------------------
void
MeshSplitter
::
UpdateNode
(
aiNode
*
pcNode
,
const
std
::
vector
<
std
::
pair
<
aiMesh
*
,
unsigned
int
>
>&
source_mesh_map
)
{
// TODO: should better use std::(multi)set for source_mesh_map.
// for every index in out list build a new entry
std
::
vector
<
unsigned
int
>
aiEntries
;
aiEntries
.
reserve
(
pcNode
->
mNumMeshes
+
1
);
for
(
unsigned
int
i
=
0
;
i
<
pcNode
->
mNumMeshes
;
++
i
)
{
for
(
unsigned
int
a
=
0
,
end
=
static_cast
<
unsigned
int
>
(
source_mesh_map
.
size
());
a
<
end
;
++
a
)
{
if
(
source_mesh_map
[
a
].
second
==
pcNode
->
mMeshes
[
i
])
{
aiEntries
.
push_back
(
a
);
}
}
}
// now build the new list
delete
pcNode
->
mMeshes
;
pcNode
->
mNumMeshes
=
static_cast
<
unsigned
int
>
(
aiEntries
.
size
());
pcNode
->
mMeshes
=
new
unsigned
int
[
pcNode
->
mNumMeshes
];
for
(
unsigned
int
b
=
0
;
b
<
pcNode
->
mNumMeshes
;
++
b
)
{
pcNode
->
mMeshes
[
b
]
=
aiEntries
[
b
];
}
// recursively update children
for
(
unsigned
int
i
=
0
,
end
=
pcNode
->
mNumChildren
;
i
<
end
;
++
i
)
{
UpdateNode
(
pcNode
->
mChildren
[
i
],
source_mesh_map
);
}
return
;
}
#define WAS_NOT_COPIED 0xffffffff
typedef
std
::
pair
<
unsigned
int
,
float
>
PerVertexWeight
;
typedef
std
::
vector
<
PerVertexWeight
>
VertexWeightTable
;
// ------------------------------------------------------------------------------------------------
VertexWeightTable
*
ComputeVertexBoneWeightTable
(
const
aiMesh
*
pMesh
)
{
if
(
!
pMesh
||
!
pMesh
->
mNumVertices
||
!
pMesh
->
mNumBones
)
{
return
nullptr
;
}
VertexWeightTable
*
const
avPerVertexWeights
=
new
VertexWeightTable
[
pMesh
->
mNumVertices
];
for
(
unsigned
int
i
=
0
;
i
<
pMesh
->
mNumBones
;
++
i
)
{
aiBone
*
bone
=
pMesh
->
mBones
[
i
];
for
(
unsigned
int
a
=
0
;
a
<
bone
->
mNumWeights
;
++
a
)
{
const
aiVertexWeight
&
weight
=
bone
->
mWeights
[
a
];
avPerVertexWeights
[
weight
.
mVertexId
].
push_back
(
std
::
make_pair
(
i
,
weight
.
mWeight
)
);
}
}
return
avPerVertexWeights
;
}
// ------------------------------------------------------------------------------------------------
void
MeshSplitter
::
SplitMesh
(
unsigned
int
a
,
aiMesh
*
in_mesh
,
std
::
vector
<
std
::
pair
<
aiMesh
*
,
unsigned
int
>
>&
source_mesh_map
)
{
// TODO: should better use std::(multi)set for source_mesh_map.
if
(
in_mesh
->
mNumVertices
<=
LIMIT
)
{
source_mesh_map
.
push_back
(
std
::
make_pair
(
in_mesh
,
a
));
return
;
}
// build a per-vertex weight list if necessary
VertexWeightTable
*
avPerVertexWeights
=
ComputeVertexBoneWeightTable
(
in_mesh
);
// we need to split this mesh into sub meshes. Estimate submesh size
const
unsigned
int
sub_meshes
=
(
in_mesh
->
mNumVertices
/
LIMIT
)
+
1
;
// create a std::vector<unsigned int> to remember which vertices have already
// been copied and to which position (i.e. output index)
std
::
vector
<
unsigned
int
>
was_copied_to
;
was_copied_to
.
resize
(
in_mesh
->
mNumVertices
,
WAS_NOT_COPIED
);
// Try to find a good estimate for the number of output faces
// per mesh. Add 12.5% as buffer
unsigned
int
size_estimated
=
in_mesh
->
mNumFaces
/
sub_meshes
;
size_estimated
+=
size_estimated
/
8
;
// now generate all submeshes
unsigned
int
base
=
0
;
while
(
true
)
{
const
unsigned
int
out_vertex_index
=
LIMIT
;
aiMesh
*
out_mesh
=
new
aiMesh
();
out_mesh
->
mNumVertices
=
0
;
out_mesh
->
mMaterialIndex
=
in_mesh
->
mMaterialIndex
;
// the name carries the adjacency information between the meshes
out_mesh
->
mName
=
in_mesh
->
mName
;
typedef
std
::
vector
<
aiVertexWeight
>
BoneWeightList
;
if
(
in_mesh
->
HasBones
())
{
out_mesh
->
mBones
=
new
aiBone
*
[
in_mesh
->
mNumBones
]();
}
// clear the temporary helper array
if
(
base
)
{
std
::
fill
(
was_copied_to
.
begin
(),
was_copied_to
.
end
(),
WAS_NOT_COPIED
);
}
std
::
vector
<
aiFace
>
vFaces
;
// reserve enough storage for most cases
if
(
in_mesh
->
HasPositions
())
{
out_mesh
->
mVertices
=
new
aiVector3D
[
out_vertex_index
];
}
if
(
in_mesh
->
HasNormals
())
{
out_mesh
->
mNormals
=
new
aiVector3D
[
out_vertex_index
];
}
if
(
in_mesh
->
HasTangentsAndBitangents
())
{
out_mesh
->
mTangents
=
new
aiVector3D
[
out_vertex_index
];
out_mesh
->
mBitangents
=
new
aiVector3D
[
out_vertex_index
];
}
for
(
unsigned
int
c
=
0
;
in_mesh
->
HasVertexColors
(
c
);
++
c
)
{
out_mesh
->
mColors
[
c
]
=
new
aiColor4D
[
out_vertex_index
];
}
for
(
unsigned
int
c
=
0
;
in_mesh
->
HasTextureCoords
(
c
);
++
c
)
{
out_mesh
->
mNumUVComponents
[
c
]
=
in_mesh
->
mNumUVComponents
[
c
];
out_mesh
->
mTextureCoords
[
c
]
=
new
aiVector3D
[
out_vertex_index
];
}
vFaces
.
reserve
(
size_estimated
);
// (we will also need to copy the array of indices)
while
(
base
<
in_mesh
->
mNumFaces
)
{
const
unsigned
int
iNumIndices
=
in_mesh
->
mFaces
[
base
].
mNumIndices
;
// doesn't catch degenerates but is quite fast
unsigned
int
iNeed
=
0
;
for
(
unsigned
int
v
=
0
;
v
<
iNumIndices
;
++
v
)
{
unsigned
int
index
=
in_mesh
->
mFaces
[
base
].
mIndices
[
v
];
// check whether we do already have this vertex
if
(
WAS_NOT_COPIED
==
was_copied_to
[
index
])
{
iNeed
++
;
}
}
if
(
out_mesh
->
mNumVertices
+
iNeed
>
out_vertex_index
)
{
// don't use this face
break
;
}
vFaces
.
push_back
(
aiFace
());
aiFace
&
rFace
=
vFaces
.
back
();
// setup face type and number of indices
rFace
.
mNumIndices
=
iNumIndices
;
rFace
.
mIndices
=
new
unsigned
int
[
iNumIndices
];
// need to update the output primitive types
switch
(
rFace
.
mNumIndices
)
{
case
1
:
out_mesh
->
mPrimitiveTypes
|=
aiPrimitiveType_POINT
;
break
;
case
2
:
out_mesh
->
mPrimitiveTypes
|=
aiPrimitiveType_LINE
;
break
;
case
3
:
out_mesh
->
mPrimitiveTypes
|=
aiPrimitiveType_TRIANGLE
;
break
;
default:
out_mesh
->
mPrimitiveTypes
|=
aiPrimitiveType_POLYGON
;
}
// and copy the contents of the old array, offset them by current base
for
(
unsigned
int
v
=
0
;
v
<
iNumIndices
;
++
v
)
{
const
unsigned
int
index
=
in_mesh
->
mFaces
[
base
].
mIndices
[
v
];
// check whether we do already have this vertex
if
(
WAS_NOT_COPIED
!=
was_copied_to
[
index
])
{
rFace
.
mIndices
[
v
]
=
was_copied_to
[
index
];
continue
;
}
// copy positions
out_mesh
->
mVertices
[
out_mesh
->
mNumVertices
]
=
(
in_mesh
->
mVertices
[
index
]);
// copy normals
if
(
in_mesh
->
HasNormals
())
{
out_mesh
->
mNormals
[
out_mesh
->
mNumVertices
]
=
(
in_mesh
->
mNormals
[
index
]);
}
// copy tangents/bi-tangents
if
(
in_mesh
->
HasTangentsAndBitangents
())
{
out_mesh
->
mTangents
[
out_mesh
->
mNumVertices
]
=
(
in_mesh
->
mTangents
[
index
]);
out_mesh
->
mBitangents
[
out_mesh
->
mNumVertices
]
=
(
in_mesh
->
mBitangents
[
index
]);
}
// texture coordinates
for
(
unsigned
int
c
=
0
;
c
<
AI_MAX_NUMBER_OF_TEXTURECOORDS
;
++
c
)
{
if
(
in_mesh
->
HasTextureCoords
(
c
))
{
out_mesh
->
mTextureCoords
[
c
][
out_mesh
->
mNumVertices
]
=
in_mesh
->
mTextureCoords
[
c
][
index
];
}
}
// vertex colors
for
(
unsigned
int
c
=
0
;
c
<
AI_MAX_NUMBER_OF_COLOR_SETS
;
++
c
)
{
if
(
in_mesh
->
HasVertexColors
(
c
))
{
out_mesh
->
mColors
[
c
][
out_mesh
->
mNumVertices
]
=
in_mesh
->
mColors
[
c
][
index
];
}
}
// check whether we have bone weights assigned to this vertex
rFace
.
mIndices
[
v
]
=
out_mesh
->
mNumVertices
;
if
(
avPerVertexWeights
)
{
VertexWeightTable
&
table
=
avPerVertexWeights
[
out_mesh
->
mNumVertices
];
for
(
VertexWeightTable
::
const_iterator
iter
=
table
.
begin
(),
end
=
table
.
end
();
iter
!=
end
;
++
iter
)
{
// allocate the bone weight array if necessary and store it in the mBones field (HACK!)
BoneWeightList
*
weight_list
=
reinterpret_cast
<
BoneWeightList
*>
(
out_mesh
->
mBones
[(
*
iter
).
first
]);
if
(
!
weight_list
)
{
weight_list
=
new
BoneWeightList
();
out_mesh
->
mBones
[(
*
iter
).
first
]
=
reinterpret_cast
<
aiBone
*>
(
weight_list
);
}
weight_list
->
push_back
(
aiVertexWeight
(
out_mesh
->
mNumVertices
,(
*
iter
).
second
));
}
}
was_copied_to
[
index
]
=
out_mesh
->
mNumVertices
;
out_mesh
->
mNumVertices
++
;
}
base
++
;
if
(
out_mesh
->
mNumVertices
==
out_vertex_index
)
{
// break here. The face is only added if it was complete
break
;
}
}
// check which bones we'll need to create for this submesh
if
(
in_mesh
->
HasBones
())
{
aiBone
**
ppCurrent
=
out_mesh
->
mBones
;
for
(
unsigned
int
k
=
0
;
k
<
in_mesh
->
mNumBones
;
++
k
)
{
// check whether the bone exists
BoneWeightList
*
const
weight_list
=
reinterpret_cast
<
BoneWeightList
*>
(
out_mesh
->
mBones
[
k
]);
if
(
weight_list
)
{
const
aiBone
*
const
bone_in
=
in_mesh
->
mBones
[
k
];
aiBone
*
const
bone_out
=
new
aiBone
();
*
ppCurrent
++
=
bone_out
;
bone_out
->
mName
=
aiString
(
bone_in
->
mName
);
bone_out
->
mOffsetMatrix
=
bone_in
->
mOffsetMatrix
;
bone_out
->
mNumWeights
=
(
unsigned
int
)
weight_list
->
size
();
bone_out
->
mWeights
=
new
aiVertexWeight
[
bone_out
->
mNumWeights
];
// copy the vertex weights
::
memcpy
(
bone_out
->
mWeights
,
&
(
*
weight_list
)[
0
],
bone_out
->
mNumWeights
*
sizeof
(
aiVertexWeight
));
delete
weight_list
;
out_mesh
->
mNumBones
++
;
}
}
}
// copy the face list to the mesh
out_mesh
->
mFaces
=
new
aiFace
[
vFaces
.
size
()];
out_mesh
->
mNumFaces
=
(
unsigned
int
)
vFaces
.
size
();
for
(
unsigned
int
p
=
0
;
p
<
out_mesh
->
mNumFaces
;
++
p
)
{
out_mesh
->
mFaces
[
p
]
=
vFaces
[
p
];
}
// add the newly created mesh to the list
source_mesh_map
.
push_back
(
std
::
make_pair
(
out_mesh
,
a
));
if
(
base
==
in_mesh
->
mNumFaces
)
{
break
;
}
}
// delete the per-vertex weight list again
delete
[]
avPerVertexWeights
;
// now delete the old mesh data
delete
in_mesh
;
}
deps/assimp/code/AssetLib/Assjson/mesh_splitter.h
0 → 100644
View file @
c6fcf2f0
/*
Assimp2Json
Copyright (c) 2011, Alexander C. Gessler
Licensed under a 3-clause BSD license. See the LICENSE file for more information.
*/
#ifndef INCLUDED_MESH_SPLITTER
#define INCLUDED_MESH_SPLITTER
// ----------------------------------------------------------------------------
// Note: this is largely based on assimp's SplitLargeMeshes_Vertex process.
// it is refactored and the coding style is slightly improved, though.
// ----------------------------------------------------------------------------
#include <vector>
struct
aiScene
;
struct
aiMesh
;
struct
aiNode
;
// ---------------------------------------------------------------------------
/** Splits meshes of unique vertices into meshes with no more vertices than
* a given, configurable threshold value.
*/
class
MeshSplitter
{
public:
void
SetLimit
(
unsigned
int
l
)
{
LIMIT
=
l
;
}
unsigned
int
GetLimit
()
const
{
return
LIMIT
;
}
public:
// -------------------------------------------------------------------
/** Executes the post processing step on the given imported data.
* At the moment a process is not supposed to fail.
* @param pScene The imported data to work at.
*/
void
Execute
(
aiScene
*
pScene
);
private:
void
UpdateNode
(
aiNode
*
pcNode
,
const
std
::
vector
<
std
::
pair
<
aiMesh
*
,
unsigned
int
>
>&
source_mesh_map
);
void
SplitMesh
(
unsigned
int
index
,
aiMesh
*
mesh
,
std
::
vector
<
std
::
pair
<
aiMesh
*
,
unsigned
int
>
>&
source_mesh_map
);
public:
unsigned
int
LIMIT
;
};
#endif // INCLUDED_MESH_SPLITTER
deps/assimp/code/AssetLib/Assxml/AssxmlExporter.cpp
0 → 100644
View file @
c6fcf2f0
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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 AssxmlExporter.cpp
* ASSXML exporter main code
*/
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
#include "AssxmlFileWriter.h"
#include <assimp/IOSystem.hpp>
#include <assimp/Exporter.hpp>
namespace
Assimp
{
void
ExportSceneAssxml
(
const
char
*
pFile
,
IOSystem
*
pIOSystem
,
const
aiScene
*
pScene
,
const
ExportProperties
*
/*pProperties*/
)
{
DumpSceneToAssxml
(
pFile
,
"
\0
"
,
// command(s)
pIOSystem
,
pScene
,
false
);
// shortened?
}
}
// end of namespace Assimp
#endif // ASSIMP_BUILD_NO_ASSXML_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT
deps/assimp/code/AssetLib/Assxml/AssxmlExporter.h
0 → 100644
View file @
c6fcf2f0
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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 AssxmlExporter.h
* ASSXML Exporter Main Header
*/
#ifndef AI_ASSXMLEXPORTER_H_INC
#define AI_ASSXMLEXPORTER_H_INC
// nothing really needed here - reserved for future use like properties
#endif
deps/assimp/code/AssetLib/Assxml/AssxmlFileWriter.cpp
0 → 100644
View file @
c6fcf2f0
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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 AssxmlFileWriter.cpp
* @brief Implementation of Assxml file writer.
*/
#include "AssxmlFileWriter.h"
#include "PostProcessing/ProcessHelper.h"
#include <assimp/version.h>
#include <assimp/Exporter.hpp>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include <stdarg.h>
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
#include <zlib.h>
#else
#include <contrib/zlib/zlib.h>
#endif
#include <stdio.h>
#include <time.h>
#include <memory>
using
namespace
Assimp
;
namespace
Assimp
{
namespace
AssxmlFileWriter
{
// -----------------------------------------------------------------------------------
static
int
ioprintf
(
IOStream
*
io
,
const
char
*
format
,
...)
{
using
namespace
std
;
if
(
nullptr
==
io
)
{
return
-
1
;
}
static
const
int
Size
=
4096
;
char
sz
[
Size
];
::
memset
(
sz
,
'\0'
,
Size
);
va_list
va
;
va_start
(
va
,
format
);
const
unsigned
int
nSize
=
vsnprintf
(
sz
,
Size
-
1
,
format
,
va
);
ai_assert
(
nSize
<
Size
);
va_end
(
va
);
io
->
Write
(
sz
,
sizeof
(
char
),
nSize
);
return
nSize
;
}
// -----------------------------------------------------------------------------------
// Convert a name to standard XML format
static
void
ConvertName
(
aiString
&
out
,
const
aiString
&
in
)
{
out
.
length
=
0
;
for
(
unsigned
int
i
=
0
;
i
<
in
.
length
;
++
i
)
{
switch
(
in
.
data
[
i
])
{
case
'<'
:
out
.
Append
(
"<"
);
break
;
case
'>'
:
out
.
Append
(
">"
);
break
;
case
'&'
:
out
.
Append
(
"&"
);
break
;
case
'\"'
:
out
.
Append
(
"""
);
break
;
case
'\''
:
out
.
Append
(
"'"
);
break
;
default:
out
.
data
[
out
.
length
++
]
=
in
.
data
[
i
];
}
}
out
.
data
[
out
.
length
]
=
0
;
}
// -----------------------------------------------------------------------------------
// Write a single node as text dump
static
void
WriteNode
(
const
aiNode
*
node
,
IOStream
*
io
,
unsigned
int
depth
)
{
char
prefix
[
512
];
for
(
unsigned
int
i
=
0
;
i
<
depth
;
++
i
)
prefix
[
i
]
=
'\t'
;
prefix
[
depth
]
=
'\0'
;
const
aiMatrix4x4
&
m
=
node
->
mTransformation
;
aiString
name
;
ConvertName
(
name
,
node
->
mName
);
ioprintf
(
io
,
"%s<Node name=
\"
%s
\"
>
\n
"
"%s
\t
<Matrix4>
\n
"
"%s
\t\t
%0 6f %0 6f %0 6f %0 6f
\n
"
"%s
\t\t
%0 6f %0 6f %0 6f %0 6f
\n
"
"%s
\t\t
%0 6f %0 6f %0 6f %0 6f
\n
"
"%s
\t\t
%0 6f %0 6f %0 6f %0 6f
\n
"
"%s
\t
</Matrix4>
\n
"
,
prefix
,
name
.
data
,
prefix
,
prefix
,
m
.
a1
,
m
.
a2
,
m
.
a3
,
m
.
a4
,
prefix
,
m
.
b1
,
m
.
b2
,
m
.
b3
,
m
.
b4
,
prefix
,
m
.
c1
,
m
.
c2
,
m
.
c3
,
m
.
c4
,
prefix
,
m
.
d1
,
m
.
d2
,
m
.
d3
,
m
.
d4
,
prefix
);
if
(
node
->
mNumMeshes
)
{
ioprintf
(
io
,
"%s
\t
<MeshRefs num=
\"
%u
\"
>
\n
%s
\t
"
,
prefix
,
node
->
mNumMeshes
,
prefix
);
for
(
unsigned
int
i
=
0
;
i
<
node
->
mNumMeshes
;
++
i
)
{
ioprintf
(
io
,
"%u "
,
node
->
mMeshes
[
i
]);
}
ioprintf
(
io
,
"
\n
%s
\t
</MeshRefs>
\n
"
,
prefix
);
}
if
(
node
->
mNumChildren
)
{
ioprintf
(
io
,
"%s
\t
<NodeList num=
\"
%u
\"
>
\n
"
,
prefix
,
node
->
mNumChildren
);
for
(
unsigned
int
i
=
0
;
i
<
node
->
mNumChildren
;
++
i
)
{
WriteNode
(
node
->
mChildren
[
i
],
io
,
depth
+
2
);
}
ioprintf
(
io
,
"%s
\t
</NodeList>
\n
"
,
prefix
);
}
ioprintf
(
io
,
"%s</Node>
\n
"
,
prefix
);
}
// -----------------------------------------------------------------------------------
// Some chuncks of text will need to be encoded for XML
// http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377
static
std
::
string
encodeXML
(
const
std
::
string
&
data
)
{
std
::
string
buffer
;
buffer
.
reserve
(
data
.
size
());
for
(
size_t
pos
=
0
;
pos
!=
data
.
size
();
++
pos
)
{
switch
(
data
[
pos
])
{
case
'&'
:
buffer
.
append
(
"&"
);
break
;
case
'\"'
:
buffer
.
append
(
"""
);
break
;
case
'\''
:
buffer
.
append
(
"'"
);
break
;
case
'<'
:
buffer
.
append
(
"<"
);
break
;
case
'>'
:
buffer
.
append
(
">"
);
break
;
default:
buffer
.
append
(
&
data
[
pos
],
1
);
break
;
}
}
return
buffer
;
}
// -----------------------------------------------------------------------------------
// Write a text model dump
static
void
WriteDump
(
const
char
*
pFile
,
const
char
*
cmd
,
const
aiScene
*
scene
,
IOStream
*
io
,
bool
shortened
)
{
time_t
tt
=
::
time
(
NULL
);
#if _WIN32
tm
*
p
=
gmtime
(
&
tt
);
#else
struct
tm
now
;
tm
*
p
=
gmtime_r
(
&
tt
,
&
now
);
#endif
ai_assert
(
nullptr
!=
p
);
std
::
string
c
=
cmd
;
std
::
string
::
size_type
s
;
// https://sourceforge.net/tracker/?func=detail&aid=3167364&group_id=226462&atid=1067632
// -- not allowed in XML comments
while
((
s
=
c
.
find
(
"--"
))
!=
std
::
string
::
npos
)
{
c
[
s
]
=
'?'
;
}
// write header
std
::
string
header
(
"<?xml version=
\"
1.0
\"
encoding=
\"
utf-8
\"
?>
\n
"
"<ASSIMP format_id=
\"
1
\"
>
\n\n
"
"<!-- XML Model dump produced by assimp dump
\n
"
" Library version: %u.%u.%u
\n
"
" Source: %s
\n
"
" Command line: %s
\n
"
" %s
\n
"
"-->"
"
\n\n
"
"<Scene flags=
\"
%u
\"
postprocessing=
\"
%u
\"
>
\n
"
);
const
unsigned
int
majorVersion
(
aiGetVersionMajor
());
const
unsigned
int
minorVersion
(
aiGetVersionMinor
());
const
unsigned
int
rev
(
aiGetVersionRevision
());
const
char
*
curtime
(
asctime
(
p
));
ioprintf
(
io
,
header
.
c_str
(),
majorVersion
,
minorVersion
,
rev
,
pFile
,
c
.
c_str
(),
curtime
,
scene
->
mFlags
,
0u
);
// write the node graph
WriteNode
(
scene
->
mRootNode
,
io
,
0
);
#if 0
// write cameras
for (unsigned int i = 0; i < scene->mNumCameras;++i) {
aiCamera* cam = scene->mCameras[i];
ConvertName(name,cam->mName);
// camera header
ioprintf(io,"\t<Camera parent=\"%s\">\n"
"\t\t<Vector3 name=\"up\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Float name=\"fov\" > %f </Float>\n"
"\t\t<Float name=\"aspect\" > %f </Float>\n"
"\t\t<Float name=\"near_clip\" > %f </Float>\n"
"\t\t<Float name=\"far_clip\" > %f </Float>\n"
"\t</Camera>\n",
name.data,
cam->mUp.x,cam->mUp.y,cam->mUp.z,
cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z,
cam->mPosition.x,cam->mPosition.y,cam->mPosition.z,
cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i);
}
// write lights
for (unsigned int i = 0; i < scene->mNumLights;++i) {
aiLight* l = scene->mLights[i];
ConvertName(name,l->mName);
// light header
ioprintf(io,"\t<Light parent=\"%s\"> type=\"%s\"\n"
"\t\t<Vector3 name=\"diffuse\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Vector3 name=\"specular\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Vector3 name=\"ambient\" > %0 8f %0 8f %0 8f </Vector3>\n",
name.data,
(l->mType == aiLightSource_DIRECTIONAL ? "directional" :
(l->mType == aiLightSource_POINT ? "point" : "spot" )),
l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b,
l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b,
l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b);
if (l->mType != aiLightSource_DIRECTIONAL) {
ioprintf(io,
"\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Float name=\"atten_cst\" > %f </Float>\n"
"\t\t<Float name=\"atten_lin\" > %f </Float>\n"
"\t\t<Float name=\"atten_sqr\" > %f </Float>\n",
l->mPosition.x,l->mPosition.y,l->mPosition.z,
l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic);
}
if (l->mType != aiLightSource_POINT) {
ioprintf(io,
"\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n",
l->mDirection.x,l->mDirection.y,l->mDirection.z);
}
if (l->mType == aiLightSource_SPOT) {
ioprintf(io,
"\t\t<Float name=\"cone_out\" > %f </Float>\n"
"\t\t<Float name=\"cone_inn\" > %f </Float>\n",
l->mAngleOuterCone,l->mAngleInnerCone);
}
ioprintf(io,"\t</Light>\n");
}
#endif
aiString
name
;
// write textures
if
(
scene
->
mNumTextures
)
{
ioprintf
(
io
,
"<TextureList num=
\"
%u
\"
>
\n
"
,
scene
->
mNumTextures
);
for
(
unsigned
int
i
=
0
;
i
<
scene
->
mNumTextures
;
++
i
)
{
aiTexture
*
tex
=
scene
->
mTextures
[
i
];
bool
compressed
=
(
tex
->
mHeight
==
0
);
// mesh header
ioprintf
(
io
,
"
\t
<Texture width=
\"
%u
\"
height=
\"
%u
\"
compressed=
\"
%s
\"
>
\n
"
,
(
compressed
?
-
1
:
tex
->
mWidth
),
(
compressed
?
-
1
:
tex
->
mHeight
),
(
compressed
?
"true"
:
"false"
));
if
(
compressed
)
{
ioprintf
(
io
,
"
\t\t
<Data length=
\"
%u
\"
>
\n
"
,
tex
->
mWidth
);
if
(
!
shortened
)
{
for
(
unsigned
int
n
=
0
;
n
<
tex
->
mWidth
;
++
n
)
{
ioprintf
(
io
,
"
\t\t\t
%2x"
,
reinterpret_cast
<
uint8_t
*>
(
tex
->
pcData
)[
n
]);
if
(
n
&&
!
(
n
%
50
))
{
ioprintf
(
io
,
"
\n
"
);
}
}
}
}
else
if
(
!
shortened
)
{
ioprintf
(
io
,
"
\t\t
<Data length=
\"
%u
\"
>
\n
"
,
tex
->
mWidth
*
tex
->
mHeight
*
4
);
// const unsigned int width = (unsigned int)std::log10((double)std::max(tex->mHeight,tex->mWidth))+1;
for
(
unsigned
int
y
=
0
;
y
<
tex
->
mHeight
;
++
y
)
{
for
(
unsigned
int
x
=
0
;
x
<
tex
->
mWidth
;
++
x
)
{
aiTexel
*
tx
=
tex
->
pcData
+
y
*
tex
->
mWidth
+
x
;
unsigned
int
r
=
tx
->
r
,
g
=
tx
->
g
,
b
=
tx
->
b
,
a
=
tx
->
a
;
ioprintf
(
io
,
"
\t\t\t
%2x %2x %2x %2x"
,
r
,
g
,
b
,
a
);
// group by four for readability
if
(
0
==
(
x
+
y
*
tex
->
mWidth
)
%
4
)
{
ioprintf
(
io
,
"
\n
"
);
}
}
}
}
ioprintf
(
io
,
"
\t\t
</Data>
\n\t
</Texture>
\n
"
);
}
ioprintf
(
io
,
"</TextureList>
\n
"
);
}
// write materials
if
(
scene
->
mNumMaterials
)
{
ioprintf
(
io
,
"<MaterialList num=
\"
%u
\"
>
\n
"
,
scene
->
mNumMaterials
);
for
(
unsigned
int
i
=
0
;
i
<
scene
->
mNumMaterials
;
++
i
)
{
const
aiMaterial
*
mat
=
scene
->
mMaterials
[
i
];
ioprintf
(
io
,
"
\t
<Material>
\n
"
);
ioprintf
(
io
,
"
\t\t
<MatPropertyList num=
\"
%u
\"
>
\n
"
,
mat
->
mNumProperties
);
for
(
unsigned
int
n
=
0
;
n
<
mat
->
mNumProperties
;
++
n
)
{
const
aiMaterialProperty
*
prop
=
mat
->
mProperties
[
n
];
const
char
*
sz
=
""
;
if
(
prop
->
mType
==
aiPTI_Float
)
{
sz
=
"float"
;
}
else
if
(
prop
->
mType
==
aiPTI_Integer
)
{
sz
=
"integer"
;
}
else
if
(
prop
->
mType
==
aiPTI_String
)
{
sz
=
"string"
;
}
else
if
(
prop
->
mType
==
aiPTI_Buffer
)
{
sz
=
"binary_buffer"
;
}
ioprintf
(
io
,
"
\t\t\t
<MatProperty key=
\"
%s
\"
\n\t\t\t
type=
\"
%s
\"
tex_usage=
\"
%s
\"
tex_index=
\"
%u
\"
"
,
prop
->
mKey
.
data
,
sz
,
::
TextureTypeToString
((
aiTextureType
)
prop
->
mSemantic
),
prop
->
mIndex
);
if
(
prop
->
mType
==
aiPTI_Float
)
{
ioprintf
(
io
,
" size=
\"
%i
\"
>
\n\t\t\t\t
"
,
static_cast
<
int
>
(
prop
->
mDataLength
/
sizeof
(
float
)));
for
(
unsigned
int
pp
=
0
;
pp
<
prop
->
mDataLength
/
sizeof
(
float
);
++
pp
)
{
ioprintf
(
io
,
"%f "
,
*
((
float
*
)(
prop
->
mData
+
pp
*
sizeof
(
float
))));
}
}
else
if
(
prop
->
mType
==
aiPTI_Integer
)
{
ioprintf
(
io
,
" size=
\"
%i
\"
>
\n\t\t\t\t
"
,
static_cast
<
int
>
(
prop
->
mDataLength
/
sizeof
(
int
)));
for
(
unsigned
int
pp
=
0
;
pp
<
prop
->
mDataLength
/
sizeof
(
int
);
++
pp
)
{
ioprintf
(
io
,
"%i "
,
*
((
int
*
)(
prop
->
mData
+
pp
*
sizeof
(
int
))));
}
}
else
if
(
prop
->
mType
==
aiPTI_Buffer
)
{
ioprintf
(
io
,
" size=
\"
%i
\"
>
\n\t\t\t\t
"
,
static_cast
<
int
>
(
prop
->
mDataLength
));
for
(
unsigned
int
pp
=
0
;
pp
<
prop
->
mDataLength
;
++
pp
)
{
ioprintf
(
io
,
"%2x "
,
prop
->
mData
[
pp
]);
if
(
pp
&&
0
==
pp
%
30
)
{
ioprintf
(
io
,
"
\n\t\t\t\t
"
);
}
}
}
else
if
(
prop
->
mType
==
aiPTI_String
)
{
ioprintf
(
io
,
">
\n\t\t\t\t\"
%s
\"
"
,
encodeXML
(
prop
->
mData
+
4
).
c_str
()
/* skip length */
);
}
ioprintf
(
io
,
"
\n\t\t\t
</MatProperty>
\n
"
);
}
ioprintf
(
io
,
"
\t\t
</MatPropertyList>
\n
"
);
ioprintf
(
io
,
"
\t
</Material>
\n
"
);
}
ioprintf
(
io
,
"</MaterialList>
\n
"
);
}
// write animations
if
(
scene
->
mNumAnimations
)
{
ioprintf
(
io
,
"<AnimationList num=
\"
%u
\"
>
\n
"
,
scene
->
mNumAnimations
);
for
(
unsigned
int
i
=
0
;
i
<
scene
->
mNumAnimations
;
++
i
)
{
aiAnimation
*
anim
=
scene
->
mAnimations
[
i
];
// anim header
ConvertName
(
name
,
anim
->
mName
);
ioprintf
(
io
,
"
\t
<Animation name=
\"
%s
\"
duration=
\"
%e
\"
tick_cnt=
\"
%e
\"
>
\n
"
,
name
.
data
,
anim
->
mDuration
,
anim
->
mTicksPerSecond
);
// write bone animation channels
if
(
anim
->
mNumChannels
)
{
ioprintf
(
io
,
"
\t\t
<NodeAnimList num=
\"
%u
\"
>
\n
"
,
anim
->
mNumChannels
);
for
(
unsigned
int
n
=
0
;
n
<
anim
->
mNumChannels
;
++
n
)
{
aiNodeAnim
*
nd
=
anim
->
mChannels
[
n
];
// node anim header
ConvertName
(
name
,
nd
->
mNodeName
);
ioprintf
(
io
,
"
\t\t\t
<NodeAnim node=
\"
%s
\"
>
\n
"
,
name
.
data
);
if
(
!
shortened
)
{
// write position keys
if
(
nd
->
mNumPositionKeys
)
{
ioprintf
(
io
,
"
\t\t\t\t
<PositionKeyList num=
\"
%u
\"
>
\n
"
,
nd
->
mNumPositionKeys
);
for
(
unsigned
int
a
=
0
;
a
<
nd
->
mNumPositionKeys
;
++
a
)
{
aiVectorKey
*
vc
=
nd
->
mPositionKeys
+
a
;
ioprintf
(
io
,
"
\t\t\t\t\t
<PositionKey time=
\"
%e
\"
>
\n
"
"
\t\t\t\t\t\t
%0 8f %0 8f %0 8f
\n\t\t\t\t\t
</PositionKey>
\n
"
,
vc
->
mTime
,
vc
->
mValue
.
x
,
vc
->
mValue
.
y
,
vc
->
mValue
.
z
);
}
ioprintf
(
io
,
"
\t\t\t\t
</PositionKeyList>
\n
"
);
}
// write scaling keys
if
(
nd
->
mNumScalingKeys
)
{
ioprintf
(
io
,
"
\t\t\t\t
<ScalingKeyList num=
\"
%u
\"
>
\n
"
,
nd
->
mNumScalingKeys
);
for
(
unsigned
int
a
=
0
;
a
<
nd
->
mNumScalingKeys
;
++
a
)
{
aiVectorKey
*
vc
=
nd
->
mScalingKeys
+
a
;
ioprintf
(
io
,
"
\t\t\t\t\t
<ScalingKey time=
\"
%e
\"
>
\n
"
"
\t\t\t\t\t\t
%0 8f %0 8f %0 8f
\n\t\t\t\t\t
</ScalingKey>
\n
"
,
vc
->
mTime
,
vc
->
mValue
.
x
,
vc
->
mValue
.
y
,
vc
->
mValue
.
z
);
}
ioprintf
(
io
,
"
\t\t\t\t
</ScalingKeyList>
\n
"
);
}
// write rotation keys
if
(
nd
->
mNumRotationKeys
)
{
ioprintf
(
io
,
"
\t\t\t\t
<RotationKeyList num=
\"
%u
\"
>
\n
"
,
nd
->
mNumRotationKeys
);
for
(
unsigned
int
a
=
0
;
a
<
nd
->
mNumRotationKeys
;
++
a
)
{
aiQuatKey
*
vc
=
nd
->
mRotationKeys
+
a
;
ioprintf
(
io
,
"
\t\t\t\t\t
<RotationKey time=
\"
%e
\"
>
\n
"
"
\t\t\t\t\t\t
%0 8f %0 8f %0 8f %0 8f
\n\t\t\t\t\t
</RotationKey>
\n
"
,
vc
->
mTime
,
vc
->
mValue
.
x
,
vc
->
mValue
.
y
,
vc
->
mValue
.
z
,
vc
->
mValue
.
w
);
}
ioprintf
(
io
,
"
\t\t\t\t
</RotationKeyList>
\n
"
);
}
}
ioprintf
(
io
,
"
\t\t\t
</NodeAnim>
\n
"
);
}
ioprintf
(
io
,
"
\t\t
</NodeAnimList>
\n
"
);
}
ioprintf
(
io
,
"
\t
</Animation>
\n
"
);
}
ioprintf
(
io
,
"</AnimationList>
\n
"
);
}
// write meshes
if
(
scene
->
mNumMeshes
)
{
ioprintf
(
io
,
"<MeshList num=
\"
%u
\"
>
\n
"
,
scene
->
mNumMeshes
);
for
(
unsigned
int
i
=
0
;
i
<
scene
->
mNumMeshes
;
++
i
)
{
aiMesh
*
mesh
=
scene
->
mMeshes
[
i
];
// const unsigned int width = (unsigned int)std::log10((double)mesh->mNumVertices)+1;
// mesh header
ioprintf
(
io
,
"
\t
<Mesh types=
\"
%s %s %s %s
\"
material_index=
\"
%u
\"
>
\n
"
,
(
mesh
->
mPrimitiveTypes
&
aiPrimitiveType_POINT
?
"points"
:
""
),
(
mesh
->
mPrimitiveTypes
&
aiPrimitiveType_LINE
?
"lines"
:
""
),
(
mesh
->
mPrimitiveTypes
&
aiPrimitiveType_TRIANGLE
?
"triangles"
:
""
),
(
mesh
->
mPrimitiveTypes
&
aiPrimitiveType_POLYGON
?
"polygons"
:
""
),
mesh
->
mMaterialIndex
);
// bones
if
(
mesh
->
mNumBones
)
{
ioprintf
(
io
,
"
\t\t
<BoneList num=
\"
%u
\"
>
\n
"
,
mesh
->
mNumBones
);
for
(
unsigned
int
n
=
0
;
n
<
mesh
->
mNumBones
;
++
n
)
{
aiBone
*
bone
=
mesh
->
mBones
[
n
];
ConvertName
(
name
,
bone
->
mName
);
// bone header
ioprintf
(
io
,
"
\t\t\t
<Bone name=
\"
%s
\"
>
\n
"
"
\t\t\t\t
<Matrix4>
\n
"
"
\t\t\t\t\t
%0 6f %0 6f %0 6f %0 6f
\n
"
"
\t\t\t\t\t
%0 6f %0 6f %0 6f %0 6f
\n
"
"
\t\t\t\t\t
%0 6f %0 6f %0 6f %0 6f
\n
"
"
\t\t\t\t\t
%0 6f %0 6f %0 6f %0 6f
\n
"
"
\t\t\t\t
</Matrix4>
\n
"
,
name
.
data
,
bone
->
mOffsetMatrix
.
a1
,
bone
->
mOffsetMatrix
.
a2
,
bone
->
mOffsetMatrix
.
a3
,
bone
->
mOffsetMatrix
.
a4
,
bone
->
mOffsetMatrix
.
b1
,
bone
->
mOffsetMatrix
.
b2
,
bone
->
mOffsetMatrix
.
b3
,
bone
->
mOffsetMatrix
.
b4
,
bone
->
mOffsetMatrix
.
c1
,
bone
->
mOffsetMatrix
.
c2
,
bone
->
mOffsetMatrix
.
c3
,
bone
->
mOffsetMatrix
.
c4
,
bone
->
mOffsetMatrix
.
d1
,
bone
->
mOffsetMatrix
.
d2
,
bone
->
mOffsetMatrix
.
d3
,
bone
->
mOffsetMatrix
.
d4
);
if
(
!
shortened
&&
bone
->
mNumWeights
)
{
ioprintf
(
io
,
"
\t\t\t\t
<WeightList num=
\"
%u
\"
>
\n
"
,
bone
->
mNumWeights
);
// bone weights
for
(
unsigned
int
a
=
0
;
a
<
bone
->
mNumWeights
;
++
a
)
{
aiVertexWeight
*
wght
=
bone
->
mWeights
+
a
;
ioprintf
(
io
,
"
\t\t\t\t\t
<Weight index=
\"
%u
\"
>
\n\t\t\t\t\t\t
%f
\n\t\t\t\t\t
</Weight>
\n
"
,
wght
->
mVertexId
,
wght
->
mWeight
);
}
ioprintf
(
io
,
"
\t\t\t\t
</WeightList>
\n
"
);
}
ioprintf
(
io
,
"
\t\t\t
</Bone>
\n
"
);
}
ioprintf
(
io
,
"
\t\t
</BoneList>
\n
"
);
}
// faces
if
(
!
shortened
&&
mesh
->
mNumFaces
)
{
ioprintf
(
io
,
"
\t\t
<FaceList num=
\"
%u
\"
>
\n
"
,
mesh
->
mNumFaces
);
for
(
unsigned
int
n
=
0
;
n
<
mesh
->
mNumFaces
;
++
n
)
{
aiFace
&
f
=
mesh
->
mFaces
[
n
];
ioprintf
(
io
,
"
\t\t\t
<Face num=
\"
%u
\"
>
\n
"
"
\t\t\t\t
"
,
f
.
mNumIndices
);
for
(
unsigned
int
j
=
0
;
j
<
f
.
mNumIndices
;
++
j
)
ioprintf
(
io
,
"%u "
,
f
.
mIndices
[
j
]);
ioprintf
(
io
,
"
\n\t\t\t
</Face>
\n
"
);
}
ioprintf
(
io
,
"
\t\t
</FaceList>
\n
"
);
}
// vertex positions
if
(
mesh
->
HasPositions
())
{
ioprintf
(
io
,
"
\t\t
<Positions num=
\"
%u
\"
set=
\"
0
\"
num_components=
\"
3
\"
>
\n
"
,
mesh
->
mNumVertices
);
if
(
!
shortened
)
{
for
(
unsigned
int
n
=
0
;
n
<
mesh
->
mNumVertices
;
++
n
)
{
ioprintf
(
io
,
"
\t\t
%0 8f %0 8f %0 8f
\n
"
,
mesh
->
mVertices
[
n
].
x
,
mesh
->
mVertices
[
n
].
y
,
mesh
->
mVertices
[
n
].
z
);
}
}
ioprintf
(
io
,
"
\t\t
</Positions>
\n
"
);
}
// vertex normals
if
(
mesh
->
HasNormals
())
{
ioprintf
(
io
,
"
\t\t
<Normals num=
\"
%u
\"
set=
\"
0
\"
num_components=
\"
3
\"
>
\n
"
,
mesh
->
mNumVertices
);
if
(
!
shortened
)
{
for
(
unsigned
int
n
=
0
;
n
<
mesh
->
mNumVertices
;
++
n
)
{
ioprintf
(
io
,
"
\t\t
%0 8f %0 8f %0 8f
\n
"
,
mesh
->
mNormals
[
n
].
x
,
mesh
->
mNormals
[
n
].
y
,
mesh
->
mNormals
[
n
].
z
);
}
}
ioprintf
(
io
,
"
\t\t
</Normals>
\n
"
);
}
// vertex tangents and bitangents
if
(
mesh
->
HasTangentsAndBitangents
())
{
ioprintf
(
io
,
"
\t\t
<Tangents num=
\"
%u
\"
set=
\"
0
\"
num_components=
\"
3
\"
>
\n
"
,
mesh
->
mNumVertices
);
if
(
!
shortened
)
{
for
(
unsigned
int
n
=
0
;
n
<
mesh
->
mNumVertices
;
++
n
)
{
ioprintf
(
io
,
"
\t\t
%0 8f %0 8f %0 8f
\n
"
,
mesh
->
mTangents
[
n
].
x
,
mesh
->
mTangents
[
n
].
y
,
mesh
->
mTangents
[
n
].
z
);
}
}
ioprintf
(
io
,
"
\t\t
</Tangents>
\n
"
);
ioprintf
(
io
,
"
\t\t
<Bitangents num=
\"
%u
\"
set=
\"
0
\"
num_components=
\"
3
\"
>
\n
"
,
mesh
->
mNumVertices
);
if
(
!
shortened
)
{
for
(
unsigned
int
n
=
0
;
n
<
mesh
->
mNumVertices
;
++
n
)
{
ioprintf
(
io
,
"
\t\t
%0 8f %0 8f %0 8f
\n
"
,
mesh
->
mBitangents
[
n
].
x
,
mesh
->
mBitangents
[
n
].
y
,
mesh
->
mBitangents
[
n
].
z
);
}
}
ioprintf
(
io
,
"
\t\t
</Bitangents>
\n
"
);
}
// texture coordinates
for
(
unsigned
int
a
=
0
;
a
<
AI_MAX_NUMBER_OF_TEXTURECOORDS
;
++
a
)
{
if
(
!
mesh
->
mTextureCoords
[
a
])
break
;
ioprintf
(
io
,
"
\t\t
<TextureCoords num=
\"
%u
\"
set=
\"
%u
\"
num_components=
\"
%u
\"
>
\n
"
,
mesh
->
mNumVertices
,
a
,
mesh
->
mNumUVComponents
[
a
]);
if
(
!
shortened
)
{
if
(
mesh
->
mNumUVComponents
[
a
]
==
3
)
{
for
(
unsigned
int
n
=
0
;
n
<
mesh
->
mNumVertices
;
++
n
)
{
ioprintf
(
io
,
"
\t\t
%0 8f %0 8f %0 8f
\n
"
,
mesh
->
mTextureCoords
[
a
][
n
].
x
,
mesh
->
mTextureCoords
[
a
][
n
].
y
,
mesh
->
mTextureCoords
[
a
][
n
].
z
);
}
}
else
{
for
(
unsigned
int
n
=
0
;
n
<
mesh
->
mNumVertices
;
++
n
)
{
ioprintf
(
io
,
"
\t\t
%0 8f %0 8f
\n
"
,
mesh
->
mTextureCoords
[
a
][
n
].
x
,
mesh
->
mTextureCoords
[
a
][
n
].
y
);
}
}
}
ioprintf
(
io
,
"
\t\t
</TextureCoords>
\n
"
);
}
// vertex colors
for
(
unsigned
int
a
=
0
;
a
<
AI_MAX_NUMBER_OF_COLOR_SETS
;
++
a
)
{
if
(
!
mesh
->
mColors
[
a
])
break
;
ioprintf
(
io
,
"
\t\t
<Colors num=
\"
%u
\"
set=
\"
%u
\"
num_components=
\"
4
\"
>
\n
"
,
mesh
->
mNumVertices
,
a
);
if
(
!
shortened
)
{
for
(
unsigned
int
n
=
0
;
n
<
mesh
->
mNumVertices
;
++
n
)
{
ioprintf
(
io
,
"
\t\t
%0 8f %0 8f %0 8f %0 8f
\n
"
,
mesh
->
mColors
[
a
][
n
].
r
,
mesh
->
mColors
[
a
][
n
].
g
,
mesh
->
mColors
[
a
][
n
].
b
,
mesh
->
mColors
[
a
][
n
].
a
);
}
}
ioprintf
(
io
,
"
\t\t
</Colors>
\n
"
);
}
ioprintf
(
io
,
"
\t
</Mesh>
\n
"
);
}
ioprintf
(
io
,
"</MeshList>
\n
"
);
}
ioprintf
(
io
,
"</Scene>
\n
</ASSIMP>"
);
}
}
// end of namespace AssxmlFileWriter
void
DumpSceneToAssxml
(
const
char
*
pFile
,
const
char
*
cmd
,
IOSystem
*
pIOSystem
,
const
aiScene
*
pScene
,
bool
shortened
)
{
std
::
unique_ptr
<
IOStream
>
file
(
pIOSystem
->
Open
(
pFile
,
"wt"
));
if
(
!
file
.
get
())
{
throw
std
::
runtime_error
(
"Unable to open output file "
+
std
::
string
(
pFile
)
+
'\n'
);
}
AssxmlFileWriter
::
WriteDump
(
pFile
,
cmd
,
pScene
,
file
.
get
(),
shortened
);
}
}
// end of namespace Assimp
deps/assimp/code/AssetLib/Assxml/AssxmlFileWriter.h
0 → 100644
View file @
c6fcf2f0
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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 AssxmlFileWriter.h
* @brief Declaration of Assxml file writer.
*/
#ifndef AI_ASSXMLFILEWRITER_H_INC
#define AI_ASSXMLFILEWRITER_H_INC
#include <assimp/defs.h>
#include <assimp/scene.h>
#include <assimp/IOSystem.hpp>
namespace
Assimp
{
void
ASSIMP_API
DumpSceneToAssxml
(
const
char
*
pFile
,
const
char
*
cmd
,
IOSystem
*
pIOSystem
,
const
aiScene
*
pScene
,
bool
shortened
);
}
#endif // AI_ASSXMLFILEWRITER_H_INC
deps/assimp/code/AssetLib/B3D/B3DImporter.cpp
0 → 100644
View file @
c6fcf2f0
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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 B3DImporter.cpp
* @brief Implementation of the b3d importer class
*/
#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
// internal headers
#include "AssetLib/B3D/B3DImporter.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include "PostProcessing/TextureTransform.h"
#include <assimp/StringUtils.h>
#include <assimp/anim.h>
#include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <memory>
using
namespace
Assimp
;
using
namespace
std
;
static
const
aiImporterDesc
desc
=
{
"BlitzBasic 3D Importer"
,
""
,
""
,
"http://www.blitzbasic.com/"
,
aiImporterFlags_SupportBinaryFlavour
,
0
,
0
,
0
,
0
,
"b3d"
};
#ifdef _MSC_VER
#pragma warning(disable : 4018)
#endif
//#define DEBUG_B3D
template
<
typename
T
>
void
DeleteAllBarePointers
(
std
::
vector
<
T
>
&
x
)
{
for
(
auto
p
:
x
)
{
delete
p
;
}
}
B3DImporter
::~
B3DImporter
()
{
}
// ------------------------------------------------------------------------------------------------
bool
B3DImporter
::
CanRead
(
const
std
::
string
&
pFile
,
IOSystem
*
/*pIOHandler*/
,
bool
/*checkSig*/
)
const
{
size_t
pos
=
pFile
.
find_last_of
(
'.'
);
if
(
pos
==
string
::
npos
)
{
return
false
;
}
string
ext
=
pFile
.
substr
(
pos
+
1
);
if
(
ext
.
size
()
!=
3
)
{
return
false
;
}
return
(
ext
[
0
]
==
'b'
||
ext
[
0
]
==
'B'
)
&&
(
ext
[
1
]
==
'3'
)
&&
(
ext
[
2
]
==
'd'
||
ext
[
2
]
==
'D'
);
}
// ------------------------------------------------------------------------------------------------
// Loader meta information
const
aiImporterDesc
*
B3DImporter
::
GetInfo
()
const
{
return
&
desc
;
}
// ------------------------------------------------------------------------------------------------
void
B3DImporter
::
InternReadFile
(
const
std
::
string
&
pFile
,
aiScene
*
pScene
,
IOSystem
*
pIOHandler
)
{
std
::
unique_ptr
<
IOStream
>
file
(
pIOHandler
->
Open
(
pFile
));
// Check whether we can read from the file
if
(
file
.
get
()
==
nullptr
)
{
throw
DeadlyImportError
(
"Failed to open B3D file "
+
pFile
+
"."
);
}
// check whether the .b3d file is large enough to contain
// at least one chunk.
size_t
fileSize
=
file
->
FileSize
();
if
(
fileSize
<
8
)
{
throw
DeadlyImportError
(
"B3D File is too small."
);
}
_pos
=
0
;
_buf
.
resize
(
fileSize
);
file
->
Read
(
&
_buf
[
0
],
1
,
fileSize
);
_stack
.
clear
();
ReadBB3D
(
pScene
);
}
// ------------------------------------------------------------------------------------------------
AI_WONT_RETURN
void
B3DImporter
::
Oops
()
{
throw
DeadlyImportError
(
"B3D Importer - INTERNAL ERROR"
);
}
// ------------------------------------------------------------------------------------------------
AI_WONT_RETURN
void
B3DImporter
::
Fail
(
string
str
)
{
#ifdef DEBUG_B3D
ASSIMP_LOG_ERROR_F
(
"Error in B3D file data: "
,
str
);
#endif
throw
DeadlyImportError
(
"B3D Importer - error in B3D file data: "
+
str
);
}
// ------------------------------------------------------------------------------------------------
int
B3DImporter
::
ReadByte
()
{
if
(
_pos
>
_buf
.
size
())
{
Fail
(
"EOF"
);
}
return
_buf
[
_pos
++
];
}
// ------------------------------------------------------------------------------------------------
int
B3DImporter
::
ReadInt
()
{
if
(
_pos
+
4
>
_buf
.
size
())
{
Fail
(
"EOF"
);
}
int
n
;
memcpy
(
&
n
,
&
_buf
[
_pos
],
4
);
_pos
+=
4
;
return
n
;
}
// ------------------------------------------------------------------------------------------------
float
B3DImporter
::
ReadFloat
()
{
if
(
_pos
+
4
>
_buf
.
size
())
{
Fail
(
"EOF"
);
}
float
n
;
memcpy
(
&
n
,
&
_buf
[
_pos
],
4
);
_pos
+=
4
;
return
n
;
}
// ------------------------------------------------------------------------------------------------
aiVector2D
B3DImporter
::
ReadVec2
()
{
float
x
=
ReadFloat
();
float
y
=
ReadFloat
();
return
aiVector2D
(
x
,
y
);
}
// ------------------------------------------------------------------------------------------------
aiVector3D
B3DImporter
::
ReadVec3
()
{
float
x
=
ReadFloat
();
float
y
=
ReadFloat
();
float
z
=
ReadFloat
();
return
aiVector3D
(
x
,
y
,
z
);
}
// ------------------------------------------------------------------------------------------------
aiQuaternion
B3DImporter
::
ReadQuat
()
{
// (aramis_acg) Fix to adapt the loader to changed quat orientation
float
w
=
-
ReadFloat
();
float
x
=
ReadFloat
();
float
y
=
ReadFloat
();
float
z
=
ReadFloat
();
return
aiQuaternion
(
w
,
x
,
y
,
z
);
}
// ------------------------------------------------------------------------------------------------
string
B3DImporter
::
ReadString
()
{
if
(
_pos
>
_buf
.
size
())
{
Fail
(
"EOF"
);
}
string
str
;
while
(
_pos
<
_buf
.
size
())
{
char
c
=
(
char
)
ReadByte
();
if
(
!
c
)
{
return
str
;
}
str
+=
c
;
}
return
string
();
}
// ------------------------------------------------------------------------------------------------
string
B3DImporter
::
ReadChunk
()
{
string
tag
;
for
(
int
i
=
0
;
i
<
4
;
++
i
)
{
tag
+=
char
(
ReadByte
());
}
#ifdef DEBUG_B3D
ASSIMP_LOG_DEBUG_F
(
"ReadChunk: "
,
tag
);
#endif
unsigned
sz
=
(
unsigned
)
ReadInt
();
_stack
.
push_back
(
_pos
+
sz
);
return
tag
;
}
// ------------------------------------------------------------------------------------------------
void
B3DImporter
::
ExitChunk
()
{
_pos
=
_stack
.
back
();
_stack
.
pop_back
();
}
// ------------------------------------------------------------------------------------------------
size_t
B3DImporter
::
ChunkSize
()
{
return
_stack
.
back
()
-
_pos
;
}
// ------------------------------------------------------------------------------------------------
template
<
class
T
>
T
*
B3DImporter
::
to_array
(
const
vector
<
T
>
&
v
)
{
if
(
v
.
empty
())
{
return
0
;
}
T
*
p
=
new
T
[
v
.
size
()];
for
(
size_t
i
=
0
;
i
<
v
.
size
();
++
i
)
{
p
[
i
]
=
v
[
i
];
}
return
p
;
}
// ------------------------------------------------------------------------------------------------
template
<
class
T
>
T
**
unique_to_array
(
vector
<
std
::
unique_ptr
<
T
>>
&
v
)
{
if
(
v
.
empty
())
{
return
0
;
}
T
**
p
=
new
T
*
[
v
.
size
()];
for
(
size_t
i
=
0
;
i
<
v
.
size
();
++
i
)
{
p
[
i
]
=
v
[
i
].
release
();
}
return
p
;
}
// ------------------------------------------------------------------------------------------------
void
B3DImporter
::
ReadTEXS
()
{
while
(
ChunkSize
())
{
string
name
=
ReadString
();
/*int flags=*/
ReadInt
();
/*int blend=*/
ReadInt
();
/*aiVector2D pos=*/
ReadVec2
();
/*aiVector2D scale=*/
ReadVec2
();
/*float rot=*/
ReadFloat
();
_textures
.
push_back
(
name
);
}
}
// ------------------------------------------------------------------------------------------------
void
B3DImporter
::
ReadBRUS
()
{
int
n_texs
=
ReadInt
();
if
(
n_texs
<
0
||
n_texs
>
8
)
{
Fail
(
"Bad texture count"
);
}
while
(
ChunkSize
())
{
string
name
=
ReadString
();
aiVector3D
color
=
ReadVec3
();
float
alpha
=
ReadFloat
();
float
shiny
=
ReadFloat
();
/*int blend=**/
ReadInt
();
int
fx
=
ReadInt
();
std
::
unique_ptr
<
aiMaterial
>
mat
(
new
aiMaterial
);
// Name
aiString
ainame
(
name
);
mat
->
AddProperty
(
&
ainame
,
AI_MATKEY_NAME
);
// Diffuse color
mat
->
AddProperty
(
&
color
,
1
,
AI_MATKEY_COLOR_DIFFUSE
);
// Opacity
mat
->
AddProperty
(
&
alpha
,
1
,
AI_MATKEY_OPACITY
);
// Specular color
aiColor3D
speccolor
(
shiny
,
shiny
,
shiny
);
mat
->
AddProperty
(
&
speccolor
,
1
,
AI_MATKEY_COLOR_SPECULAR
);
// Specular power
float
specpow
=
shiny
*
128
;
mat
->
AddProperty
(
&
specpow
,
1
,
AI_MATKEY_SHININESS
);
// Double sided
if
(
fx
&
0x10
)
{
int
i
=
1
;
mat
->
AddProperty
(
&
i
,
1
,
AI_MATKEY_TWOSIDED
);
}
//Textures
for
(
int
i
=
0
;
i
<
n_texs
;
++
i
)
{
int
texid
=
ReadInt
();
if
(
texid
<
-
1
||
(
texid
>=
0
&&
texid
>=
static_cast
<
int
>
(
_textures
.
size
())))
{
Fail
(
"Bad texture id"
);
}
if
(
i
==
0
&&
texid
>=
0
)
{
aiString
texname
(
_textures
[
texid
]);
mat
->
AddProperty
(
&
texname
,
AI_MATKEY_TEXTURE_DIFFUSE
(
0
));
}
}
_materials
.
emplace_back
(
std
::
move
(
mat
));
}
}
// ------------------------------------------------------------------------------------------------
void
B3DImporter
::
ReadVRTS
()
{
_vflags
=
ReadInt
();
_tcsets
=
ReadInt
();
_tcsize
=
ReadInt
();
if
(
_tcsets
<
0
||
_tcsets
>
4
||
_tcsize
<
0
||
_tcsize
>
4
)
{
Fail
(
"Bad texcoord data"
);
}
int
sz
=
12
+
(
_vflags
&
1
?
12
:
0
)
+
(
_vflags
&
2
?
16
:
0
)
+
(
_tcsets
*
_tcsize
*
4
);
size_t
n_verts
=
ChunkSize
()
/
sz
;
int
v0
=
static_cast
<
int
>
(
_vertices
.
size
());
_vertices
.
resize
(
v0
+
n_verts
);
for
(
unsigned
int
i
=
0
;
i
<
n_verts
;
++
i
)
{
Vertex
&
v
=
_vertices
[
v0
+
i
];
memset
(
v
.
bones
,
0
,
sizeof
(
v
.
bones
));
memset
(
v
.
weights
,
0
,
sizeof
(
v
.
weights
));
v
.
vertex
=
ReadVec3
();
if
(
_vflags
&
1
)
{
v
.
normal
=
ReadVec3
();
}
if
(
_vflags
&
2
)
{
ReadQuat
();
//skip v 4bytes...
}
for
(
int
j
=
0
;
j
<
_tcsets
;
++
j
)
{
float
t
[
4
]
=
{
0
,
0
,
0
,
0
};
for
(
int
k
=
0
;
k
<
_tcsize
;
++
k
)
{
t
[
k
]
=
ReadFloat
();
}
t
[
1
]
=
1
-
t
[
1
];
if
(
!
j
)
{
v
.
texcoords
=
aiVector3D
(
t
[
0
],
t
[
1
],
t
[
2
]);
}
}
}
}
// ------------------------------------------------------------------------------------------------
void
B3DImporter
::
ReadTRIS
(
int
v0
)
{
int
matid
=
ReadInt
();
if
(
matid
==
-
1
)
{
matid
=
0
;
}
else
if
(
matid
<
0
||
matid
>=
(
int
)
_materials
.
size
())
{
#ifdef DEBUG_B3D
ASSIMP_LOG_ERROR_F
(
"material id="
,
matid
);
#endif
Fail
(
"Bad material id"
);
}
std
::
unique_ptr
<
aiMesh
>
mesh
(
new
aiMesh
);
mesh
->
mMaterialIndex
=
matid
;
mesh
->
mNumFaces
=
0
;
mesh
->
mPrimitiveTypes
=
aiPrimitiveType_TRIANGLE
;
size_t
n_tris
=
ChunkSize
()
/
12
;
aiFace
*
face
=
mesh
->
mFaces
=
new
aiFace
[
n_tris
];
for
(
unsigned
int
i
=
0
;
i
<
n_tris
;
++
i
)
{
int
i0
=
ReadInt
()
+
v0
;
int
i1
=
ReadInt
()
+
v0
;
int
i2
=
ReadInt
()
+
v0
;
if
(
i0
<
0
||
i0
>=
(
int
)
_vertices
.
size
()
||
i1
<
0
||
i1
>=
(
int
)
_vertices
.
size
()
||
i2
<
0
||
i2
>=
(
int
)
_vertices
.
size
())
{
#ifdef DEBUG_B3D
ASSIMP_LOG_ERROR_F
(
"Bad triangle index: i0="
,
i0
,
", i1="
,
i1
,
", i2="
,
i2
);
#endif
Fail
(
"Bad triangle index"
);
continue
;
}
face
->
mNumIndices
=
3
;
face
->
mIndices
=
new
unsigned
[
3
];
face
->
mIndices
[
0
]
=
i0
;
face
->
mIndices
[
1
]
=
i1
;
face
->
mIndices
[
2
]
=
i2
;
++
mesh
->
mNumFaces
;
++
face
;
}
_meshes
.
emplace_back
(
std
::
move
(
mesh
));
}
// ------------------------------------------------------------------------------------------------
void
B3DImporter
::
ReadMESH
()
{
/*int matid=*/
ReadInt
();
int
v0
=
static_cast
<
int
>
(
_vertices
.
size
());
while
(
ChunkSize
())
{
string
t
=
ReadChunk
();
if
(
t
==
"VRTS"
)
{
ReadVRTS
();
}
else
if
(
t
==
"TRIS"
)
{
ReadTRIS
(
v0
);
}
ExitChunk
();
}
}
// ------------------------------------------------------------------------------------------------
void
B3DImporter
::
ReadBONE
(
int
id
)
{
while
(
ChunkSize
())
{
int
vertex
=
ReadInt
();
float
weight
=
ReadFloat
();
if
(
vertex
<
0
||
vertex
>=
(
int
)
_vertices
.
size
())
{
Fail
(
"Bad vertex index"
);
}
Vertex
&
v
=
_vertices
[
vertex
];
for
(
int
i
=
0
;
i
<
4
;
++
i
)
{
if
(
!
v
.
weights
[
i
])
{
v
.
bones
[
i
]
=
static_cast
<
unsigned
char
>
(
id
);
v
.
weights
[
i
]
=
weight
;
break
;
}
}
}
}
// ------------------------------------------------------------------------------------------------
void
B3DImporter
::
ReadKEYS
(
aiNodeAnim
*
nodeAnim
)
{
vector
<
aiVectorKey
>
trans
,
scale
;
vector
<
aiQuatKey
>
rot
;
int
flags
=
ReadInt
();
while
(
ChunkSize
())
{
int
frame
=
ReadInt
();
if
(
flags
&
1
)
{
trans
.
push_back
(
aiVectorKey
(
frame
,
ReadVec3
()));
}
if
(
flags
&
2
)
{
scale
.
push_back
(
aiVectorKey
(
frame
,
ReadVec3
()));
}
if
(
flags
&
4
)
{
rot
.
push_back
(
aiQuatKey
(
frame
,
ReadQuat
()));
}
}
if
(
flags
&
1
)
{
nodeAnim
->
mNumPositionKeys
=
static_cast
<
unsigned
int
>
(
trans
.
size
());
nodeAnim
->
mPositionKeys
=
to_array
(
trans
);
}
if
(
flags
&
2
)
{
nodeAnim
->
mNumScalingKeys
=
static_cast
<
unsigned
int
>
(
scale
.
size
());
nodeAnim
->
mScalingKeys
=
to_array
(
scale
);
}
if
(
flags
&
4
)
{
nodeAnim
->
mNumRotationKeys
=
static_cast
<
unsigned
int
>
(
rot
.
size
());
nodeAnim
->
mRotationKeys
=
to_array
(
rot
);
}
}
// ------------------------------------------------------------------------------------------------
void
B3DImporter
::
ReadANIM
()
{
/*int flags=*/
ReadInt
();
int
frames
=
ReadInt
();
float
fps
=
ReadFloat
();
std
::
unique_ptr
<
aiAnimation
>
anim
(
new
aiAnimation
);
anim
->
mDuration
=
frames
;
anim
->
mTicksPerSecond
=
fps
;
_animations
.
emplace_back
(
std
::
move
(
anim
));
}
// ------------------------------------------------------------------------------------------------
aiNode
*
B3DImporter
::
ReadNODE
(
aiNode
*
parent
)
{
string
name
=
ReadString
();
aiVector3D
t
=
ReadVec3
();
aiVector3D
s
=
ReadVec3
();
aiQuaternion
r
=
ReadQuat
();
aiMatrix4x4
trans
,
scale
,
rot
;
aiMatrix4x4
::
Translation
(
t
,
trans
);
aiMatrix4x4
::
Scaling
(
s
,
scale
);
rot
=
aiMatrix4x4
(
r
.
GetMatrix
());
aiMatrix4x4
tform
=
trans
*
rot
*
scale
;
int
nodeid
=
static_cast
<
int
>
(
_nodes
.
size
());
aiNode
*
node
=
new
aiNode
(
name
);
_nodes
.
push_back
(
node
);
node
->
mParent
=
parent
;
node
->
mTransformation
=
tform
;
std
::
unique_ptr
<
aiNodeAnim
>
nodeAnim
;
vector
<
unsigned
>
meshes
;
vector
<
aiNode
*>
children
;
while
(
ChunkSize
())
{
const
string
chunk
=
ReadChunk
();
if
(
chunk
==
"MESH"
)
{
unsigned
int
n
=
static_cast
<
unsigned
int
>
(
_meshes
.
size
());
ReadMESH
();
for
(
unsigned
int
i
=
n
;
i
<
static_cast
<
unsigned
int
>
(
_meshes
.
size
());
++
i
)
{
meshes
.
push_back
(
i
);
}
}
else
if
(
chunk
==
"BONE"
)
{
ReadBONE
(
nodeid
);
}
else
if
(
chunk
==
"ANIM"
)
{
ReadANIM
();
}
else
if
(
chunk
==
"KEYS"
)
{
if
(
!
nodeAnim
)
{
nodeAnim
.
reset
(
new
aiNodeAnim
);
nodeAnim
->
mNodeName
=
node
->
mName
;
}
ReadKEYS
(
nodeAnim
.
get
());
}
else
if
(
chunk
==
"NODE"
)
{
aiNode
*
child
=
ReadNODE
(
node
);
children
.
push_back
(
child
);
}
ExitChunk
();
}
if
(
nodeAnim
)
{
_nodeAnims
.
emplace_back
(
std
::
move
(
nodeAnim
));
}
node
->
mNumMeshes
=
static_cast
<
unsigned
int
>
(
meshes
.
size
());
node
->
mMeshes
=
to_array
(
meshes
);
node
->
mNumChildren
=
static_cast
<
unsigned
int
>
(
children
.
size
());
node
->
mChildren
=
to_array
(
children
);
return
node
;
}
// ------------------------------------------------------------------------------------------------
void
B3DImporter
::
ReadBB3D
(
aiScene
*
scene
)
{
_textures
.
clear
();
_materials
.
clear
();
_vertices
.
clear
();
_meshes
.
clear
();
DeleteAllBarePointers
(
_nodes
);
_nodes
.
clear
();
_nodeAnims
.
clear
();
_animations
.
clear
();
string
t
=
ReadChunk
();
if
(
t
==
"BB3D"
)
{
int
version
=
ReadInt
();
if
(
!
DefaultLogger
::
isNullLogger
())
{
char
dmp
[
128
];
ai_snprintf
(
dmp
,
128
,
"B3D file format version: %i"
,
version
);
ASSIMP_LOG_INFO
(
dmp
);
}
while
(
ChunkSize
())
{
const
string
chunk
=
ReadChunk
();
if
(
chunk
==
"TEXS"
)
{
ReadTEXS
();
}
else
if
(
chunk
==
"BRUS"
)
{
ReadBRUS
();
}
else
if
(
chunk
==
"NODE"
)
{
ReadNODE
(
0
);
}
ExitChunk
();
}
}
ExitChunk
();
if
(
!
_nodes
.
size
())
{
Fail
(
"No nodes"
);
}
if
(
!
_meshes
.
size
())
{
Fail
(
"No meshes"
);
}
// Fix nodes/meshes/bones
for
(
size_t
i
=
0
;
i
<
_nodes
.
size
();
++
i
)
{
aiNode
*
node
=
_nodes
[
i
];
for
(
size_t
j
=
0
;
j
<
node
->
mNumMeshes
;
++
j
)
{
aiMesh
*
mesh
=
_meshes
[
node
->
mMeshes
[
j
]].
get
();
int
n_tris
=
mesh
->
mNumFaces
;
int
n_verts
=
mesh
->
mNumVertices
=
n_tris
*
3
;
aiVector3D
*
mv
=
mesh
->
mVertices
=
new
aiVector3D
[
n_verts
],
*
mn
=
0
,
*
mc
=
0
;
if
(
_vflags
&
1
)
{
mn
=
mesh
->
mNormals
=
new
aiVector3D
[
n_verts
];
}
if
(
_tcsets
)
{
mc
=
mesh
->
mTextureCoords
[
0
]
=
new
aiVector3D
[
n_verts
];
}
aiFace
*
face
=
mesh
->
mFaces
;
vector
<
vector
<
aiVertexWeight
>>
vweights
(
_nodes
.
size
());
for
(
int
vertIdx
=
0
;
vertIdx
<
n_verts
;
vertIdx
+=
3
)
{
for
(
int
faceIndex
=
0
;
faceIndex
<
3
;
++
faceIndex
)
{
Vertex
&
v
=
_vertices
[
face
->
mIndices
[
faceIndex
]];
*
mv
++
=
v
.
vertex
;
if
(
mn
)
*
mn
++
=
v
.
normal
;
if
(
mc
)
*
mc
++
=
v
.
texcoords
;
face
->
mIndices
[
faceIndex
]
=
vertIdx
+
faceIndex
;
for
(
int
k
=
0
;
k
<
4
;
++
k
)
{
if
(
!
v
.
weights
[
k
])
break
;
int
bone
=
v
.
bones
[
k
];
float
weight
=
v
.
weights
[
k
];
vweights
[
bone
].
push_back
(
aiVertexWeight
(
vertIdx
+
faceIndex
,
weight
));
}
}
++
face
;
}
vector
<
aiBone
*>
bones
;
for
(
size_t
weightIndx
=
0
;
weightIndx
<
vweights
.
size
();
++
weightIndx
)
{
vector
<
aiVertexWeight
>
&
weights
=
vweights
[
weightIndx
];
if
(
!
weights
.
size
())
{
continue
;
}
aiBone
*
bone
=
new
aiBone
;
bones
.
push_back
(
bone
);
aiNode
*
bnode
=
_nodes
[
weightIndx
];
bone
->
mName
=
bnode
->
mName
;
bone
->
mNumWeights
=
static_cast
<
unsigned
int
>
(
weights
.
size
());
bone
->
mWeights
=
to_array
(
weights
);
aiMatrix4x4
mat
=
bnode
->
mTransformation
;
while
(
bnode
->
mParent
)
{
bnode
=
bnode
->
mParent
;
mat
=
bnode
->
mTransformation
*
mat
;
}
bone
->
mOffsetMatrix
=
mat
.
Inverse
();
}
mesh
->
mNumBones
=
static_cast
<
unsigned
int
>
(
bones
.
size
());
mesh
->
mBones
=
to_array
(
bones
);
}
}
//nodes
scene
->
mRootNode
=
_nodes
[
0
];
_nodes
.
clear
();
// node ownership now belongs to scene
//material
if
(
!
_materials
.
size
())
{
_materials
.
emplace_back
(
std
::
unique_ptr
<
aiMaterial
>
(
new
aiMaterial
));
}
scene
->
mNumMaterials
=
static_cast
<
unsigned
int
>
(
_materials
.
size
());
scene
->
mMaterials
=
unique_to_array
(
_materials
);
//meshes
scene
->
mNumMeshes
=
static_cast
<
unsigned
int
>
(
_meshes
.
size
());
scene
->
mMeshes
=
unique_to_array
(
_meshes
);
//animations
if
(
_animations
.
size
()
==
1
&&
_nodeAnims
.
size
())
{
aiAnimation
*
anim
=
_animations
.
back
().
get
();
anim
->
mNumChannels
=
static_cast
<
unsigned
int
>
(
_nodeAnims
.
size
());
anim
->
mChannels
=
unique_to_array
(
_nodeAnims
);
scene
->
mNumAnimations
=
static_cast
<
unsigned
int
>
(
_animations
.
size
());
scene
->
mAnimations
=
unique_to_array
(
_animations
);
}
// convert to RH
MakeLeftHandedProcess
makeleft
;
makeleft
.
Execute
(
scene
);
FlipWindingOrderProcess
flip
;
flip
.
Execute
(
scene
);
}
#endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER
deps/assimp/code/AssetLib/B3D/B3DImporter.h
0 → 100644
View file @
c6fcf2f0
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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 Definition of the .b3d importer class. */
#ifndef AI_B3DIMPORTER_H_INC
#define AI_B3DIMPORTER_H_INC
#include <assimp/types.h>
#include <assimp/mesh.h>
#include <assimp/material.h>
#include <assimp/BaseImporter.h>
#include <memory>
#include <vector>
struct
aiNodeAnim
;
struct
aiNode
;
struct
aiAnimation
;
namespace
Assimp
{
class
B3DImporter
:
public
BaseImporter
{
public:
B3DImporter
()
=
default
;
virtual
~
B3DImporter
();
virtual
bool
CanRead
(
const
std
::
string
&
pFile
,
IOSystem
*
pIOHandler
,
bool
checkSig
)
const
;
protected:
virtual
const
aiImporterDesc
*
GetInfo
()
const
;
virtual
void
InternReadFile
(
const
std
::
string
&
pFile
,
aiScene
*
pScene
,
IOSystem
*
pIOHandler
);
private:
int
ReadByte
();
int
ReadInt
();
float
ReadFloat
();
aiVector2D
ReadVec2
();
aiVector3D
ReadVec3
();
aiQuaternion
ReadQuat
();
std
::
string
ReadString
();
std
::
string
ReadChunk
();
void
ExitChunk
();
size_t
ChunkSize
();
template
<
class
T
>
T
*
to_array
(
const
std
::
vector
<
T
>
&
v
);
struct
Vertex
{
aiVector3D
vertex
;
aiVector3D
normal
;
aiVector3D
texcoords
;
unsigned
char
bones
[
4
];
float
weights
[
4
];
};
AI_WONT_RETURN
void
Oops
()
AI_WONT_RETURN_SUFFIX
;
AI_WONT_RETURN
void
Fail
(
std
::
string
str
)
AI_WONT_RETURN_SUFFIX
;
void
ReadTEXS
();
void
ReadBRUS
();
void
ReadVRTS
();
void
ReadTRIS
(
int
v0
);
void
ReadMESH
();
void
ReadBONE
(
int
id
);
void
ReadKEYS
(
aiNodeAnim
*
nodeAnim
);
void
ReadANIM
();
aiNode
*
ReadNODE
(
aiNode
*
parent
);
void
ReadBB3D
(
aiScene
*
scene
);
size_t
_pos
;
// unsigned _size;
std
::
vector
<
unsigned
char
>
_buf
;
std
::
vector
<
size_t
>
_stack
;
std
::
vector
<
std
::
string
>
_textures
;
std
::
vector
<
std
::
unique_ptr
<
aiMaterial
>
>
_materials
;
int
_vflags
,
_tcsets
,
_tcsize
;
std
::
vector
<
Vertex
>
_vertices
;
std
::
vector
<
aiNode
*>
_nodes
;
std
::
vector
<
std
::
unique_ptr
<
aiMesh
>
>
_meshes
;
std
::
vector
<
std
::
unique_ptr
<
aiNodeAnim
>
>
_nodeAnims
;
std
::
vector
<
std
::
unique_ptr
<
aiAnimation
>
>
_animations
;
};
}
#endif
deps/assimp/code/AssetLib/BVH/BVHLoader.cpp
0 → 100644
View file @
c6fcf2f0
/** Implementation of the BVH loader */
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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.
---------------------------------------------------------------------------
*/
#ifndef ASSIMP_BUILD_NO_BVH_IMPORTER
#include "BVHLoader.h"
#include <assimp/SkeletonMeshBuilder.h>
#include <assimp/TinyFormatter.h>
#include <assimp/fast_atof.h>
#include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/IOSystem.hpp>
#include <assimp/Importer.hpp>
#include <map>
#include <memory>
using
namespace
Assimp
;
using
namespace
Assimp
::
Formatter
;
static
const
aiImporterDesc
desc
=
{
"BVH Importer (MoCap)"
,
""
,
""
,
""
,
aiImporterFlags_SupportTextFlavour
,
0
,
0
,
0
,
0
,
"bvh"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
BVHLoader
::
BVHLoader
()
:
mLine
(),
mAnimTickDuration
(),
mAnimNumFrames
(),
noSkeletonMesh
()
{}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
BVHLoader
::~
BVHLoader
()
{}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool
BVHLoader
::
CanRead
(
const
std
::
string
&
pFile
,
IOSystem
*
pIOHandler
,
bool
cs
)
const
{
// check file extension
const
std
::
string
extension
=
GetExtension
(
pFile
);
if
(
extension
==
"bvh"
)
return
true
;
if
((
!
extension
.
length
()
||
cs
)
&&
pIOHandler
)
{
const
char
*
tokens
[]
=
{
"HIERARCHY"
};
return
SearchFileHeaderForToken
(
pIOHandler
,
pFile
,
tokens
,
1
);
}
return
false
;
}
// ------------------------------------------------------------------------------------------------
void
BVHLoader
::
SetupProperties
(
const
Importer
*
pImp
)
{
noSkeletonMesh
=
pImp
->
GetPropertyInteger
(
AI_CONFIG_IMPORT_NO_SKELETON_MESHES
,
0
)
!=
0
;
}
// ------------------------------------------------------------------------------------------------
// Loader meta information
const
aiImporterDesc
*
BVHLoader
::
GetInfo
()
const
{
return
&
desc
;
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void
BVHLoader
::
InternReadFile
(
const
std
::
string
&
pFile
,
aiScene
*
pScene
,
IOSystem
*
pIOHandler
)
{
mFileName
=
pFile
;
// read file into memory
std
::
unique_ptr
<
IOStream
>
file
(
pIOHandler
->
Open
(
pFile
));
if
(
file
.
get
()
==
nullptr
)
{
throw
DeadlyImportError
(
"Failed to open file "
+
pFile
+
"."
);
}
size_t
fileSize
=
file
->
FileSize
();
if
(
fileSize
==
0
)
{
throw
DeadlyImportError
(
"File is too small."
);
}
mBuffer
.
resize
(
fileSize
);
file
->
Read
(
&
mBuffer
.
front
(),
1
,
fileSize
);
// start reading
mReader
=
mBuffer
.
begin
();
mLine
=
1
;
ReadStructure
(
pScene
);
if
(
!
noSkeletonMesh
)
{
// build a dummy mesh for the skeleton so that we see something at least
SkeletonMeshBuilder
meshBuilder
(
pScene
);
}
// construct an animation from all the motion data we read
CreateAnimation
(
pScene
);
}
// ------------------------------------------------------------------------------------------------
// Reads the file
void
BVHLoader
::
ReadStructure
(
aiScene
*
pScene
)
{
// first comes hierarchy
std
::
string
header
=
GetNextToken
();
if
(
header
!=
"HIERARCHY"
)
ThrowException
(
"Expected header string
\"
HIERARCHY
\"
."
);
ReadHierarchy
(
pScene
);
// then comes the motion data
std
::
string
motion
=
GetNextToken
();
if
(
motion
!=
"MOTION"
)
ThrowException
(
"Expected beginning of motion data
\"
MOTION
\"
."
);
ReadMotion
(
pScene
);
}
// ------------------------------------------------------------------------------------------------
// Reads the hierarchy
void
BVHLoader
::
ReadHierarchy
(
aiScene
*
pScene
)
{
std
::
string
root
=
GetNextToken
();
if
(
root
!=
"ROOT"
)
ThrowException
(
"Expected root node
\"
ROOT
\"
."
);
// Go read the hierarchy from here
pScene
->
mRootNode
=
ReadNode
();
}
// ------------------------------------------------------------------------------------------------
// Reads a node and recursively its childs and returns the created node;
aiNode
*
BVHLoader
::
ReadNode
()
{
// first token is name
std
::
string
nodeName
=
GetNextToken
();
if
(
nodeName
.
empty
()
||
nodeName
==
"{"
)
ThrowException
(
format
()
<<
"Expected node name, but found
\"
"
<<
nodeName
<<
"
\"
."
);
// then an opening brace should follow
std
::
string
openBrace
=
GetNextToken
();
if
(
openBrace
!=
"{"
)
ThrowException
(
format
()
<<
"Expected opening brace
\"
{
\"
, but found
\"
"
<<
openBrace
<<
"
\"
."
);
// Create a node
aiNode
*
node
=
new
aiNode
(
nodeName
);
std
::
vector
<
aiNode
*>
childNodes
;
// and create an bone entry for it
mNodes
.
push_back
(
Node
(
node
));
Node
&
internNode
=
mNodes
.
back
();
// now read the node's contents
std
::
string
siteToken
;
while
(
1
)
{
std
::
string
token
=
GetNextToken
();
// node offset to parent node
if
(
token
==
"OFFSET"
)
ReadNodeOffset
(
node
);
else
if
(
token
==
"CHANNELS"
)
ReadNodeChannels
(
internNode
);
else
if
(
token
==
"JOINT"
)
{
// child node follows
aiNode
*
child
=
ReadNode
();
child
->
mParent
=
node
;
childNodes
.
push_back
(
child
);
}
else
if
(
token
==
"End"
)
{
// The real symbol is "End Site". Second part comes in a separate token
siteToken
.
clear
();
siteToken
=
GetNextToken
();
if
(
siteToken
!=
"Site"
)
ThrowException
(
format
()
<<
"Expected
\"
End Site
\"
keyword, but found
\"
"
<<
token
<<
" "
<<
siteToken
<<
"
\"
."
);
aiNode
*
child
=
ReadEndSite
(
nodeName
);
child
->
mParent
=
node
;
childNodes
.
push_back
(
child
);
}
else
if
(
token
==
"}"
)
{
// we're done with that part of the hierarchy
break
;
}
else
{
// everything else is a parse error
ThrowException
(
format
()
<<
"Unknown keyword
\"
"
<<
token
<<
"
\"
."
);
}
}
// add the child nodes if there are any
if
(
childNodes
.
size
()
>
0
)
{
node
->
mNumChildren
=
static_cast
<
unsigned
int
>
(
childNodes
.
size
());
node
->
mChildren
=
new
aiNode
*
[
node
->
mNumChildren
];
std
::
copy
(
childNodes
.
begin
(),
childNodes
.
end
(),
node
->
mChildren
);
}
// and return the sub-hierarchy we built here
return
node
;
}
// ------------------------------------------------------------------------------------------------
// Reads an end node and returns the created node.
aiNode
*
BVHLoader
::
ReadEndSite
(
const
std
::
string
&
pParentName
)
{
// check opening brace
std
::
string
openBrace
=
GetNextToken
();
if
(
openBrace
!=
"{"
)
ThrowException
(
format
()
<<
"Expected opening brace
\"
{
\"
, but found
\"
"
<<
openBrace
<<
"
\"
."
);
// Create a node
aiNode
*
node
=
new
aiNode
(
"EndSite_"
+
pParentName
);
// now read the node's contents. Only possible entry is "OFFSET"
std
::
string
token
;
while
(
1
)
{
token
.
clear
();
token
=
GetNextToken
();
// end node's offset
if
(
token
==
"OFFSET"
)
{
ReadNodeOffset
(
node
);
}
else
if
(
token
==
"}"
)
{
// we're done with the end node
break
;
}
else
{
// everything else is a parse error
ThrowException
(
format
()
<<
"Unknown keyword
\"
"
<<
token
<<
"
\"
."
);
}
}
// and return the sub-hierarchy we built here
return
node
;
}
// ------------------------------------------------------------------------------------------------
// Reads a node offset for the given node
void
BVHLoader
::
ReadNodeOffset
(
aiNode
*
pNode
)
{
// Offset consists of three floats to read
aiVector3D
offset
;
offset
.
x
=
GetNextTokenAsFloat
();
offset
.
y
=
GetNextTokenAsFloat
();
offset
.
z
=
GetNextTokenAsFloat
();
// build a transformation matrix from it
pNode
->
mTransformation
=
aiMatrix4x4
(
1.0
f
,
0.0
f
,
0.0
f
,
offset
.
x
,
0.0
f
,
1.0
f
,
0.0
f
,
offset
.
y
,
0.0
f
,
0.0
f
,
1.0
f
,
offset
.
z
,
0.0
f
,
0.0
f
,
0.0
f
,
1.0
f
);
}
// ------------------------------------------------------------------------------------------------
// Reads the animation channels for the given node
void
BVHLoader
::
ReadNodeChannels
(
BVHLoader
::
Node
&
pNode
)
{
// number of channels. Use the float reader because we're lazy
float
numChannelsFloat
=
GetNextTokenAsFloat
();
unsigned
int
numChannels
=
(
unsigned
int
)
numChannelsFloat
;
for
(
unsigned
int
a
=
0
;
a
<
numChannels
;
a
++
)
{
std
::
string
channelToken
=
GetNextToken
();
if
(
channelToken
==
"Xposition"
)
pNode
.
mChannels
.
push_back
(
Channel_PositionX
);
else
if
(
channelToken
==
"Yposition"
)
pNode
.
mChannels
.
push_back
(
Channel_PositionY
);
else
if
(
channelToken
==
"Zposition"
)
pNode
.
mChannels
.
push_back
(
Channel_PositionZ
);
else
if
(
channelToken
==
"Xrotation"
)
pNode
.
mChannels
.
push_back
(
Channel_RotationX
);
else
if
(
channelToken
==
"Yrotation"
)
pNode
.
mChannels
.
push_back
(
Channel_RotationY
);
else
if
(
channelToken
==
"Zrotation"
)
pNode
.
mChannels
.
push_back
(
Channel_RotationZ
);
else
ThrowException
(
format
()
<<
"Invalid channel specifier
\"
"
<<
channelToken
<<
"
\"
."
);
}
}
// ------------------------------------------------------------------------------------------------
// Reads the motion data
void
BVHLoader
::
ReadMotion
(
aiScene
*
/*pScene*/
)
{
// Read number of frames
std
::
string
tokenFrames
=
GetNextToken
();
if
(
tokenFrames
!=
"Frames:"
)
ThrowException
(
format
()
<<
"Expected frame count
\"
Frames:
\"
, but found
\"
"
<<
tokenFrames
<<
"
\"
."
);
float
numFramesFloat
=
GetNextTokenAsFloat
();
mAnimNumFrames
=
(
unsigned
int
)
numFramesFloat
;
// Read frame duration
std
::
string
tokenDuration1
=
GetNextToken
();
std
::
string
tokenDuration2
=
GetNextToken
();
if
(
tokenDuration1
!=
"Frame"
||
tokenDuration2
!=
"Time:"
)
ThrowException
(
format
()
<<
"Expected frame duration
\"
Frame Time:
\"
, but found
\"
"
<<
tokenDuration1
<<
" "
<<
tokenDuration2
<<
"
\"
."
);
mAnimTickDuration
=
GetNextTokenAsFloat
();
// resize value vectors for each node
for
(
std
::
vector
<
Node
>::
iterator
it
=
mNodes
.
begin
();
it
!=
mNodes
.
end
();
++
it
)
it
->
mChannelValues
.
reserve
(
it
->
mChannels
.
size
()
*
mAnimNumFrames
);
// now read all the data and store it in the corresponding node's value vector
for
(
unsigned
int
frame
=
0
;
frame
<
mAnimNumFrames
;
++
frame
)
{
// on each line read the values for all nodes
for
(
std
::
vector
<
Node
>::
iterator
it
=
mNodes
.
begin
();
it
!=
mNodes
.
end
();
++
it
)
{
// get as many values as the node has channels
for
(
unsigned
int
c
=
0
;
c
<
it
->
mChannels
.
size
();
++
c
)
it
->
mChannelValues
.
push_back
(
GetNextTokenAsFloat
());
}
// after one frame worth of values for all nodes there should be a newline, but we better don't rely on it
}
}
// ------------------------------------------------------------------------------------------------
// Retrieves the next token
std
::
string
BVHLoader
::
GetNextToken
()
{
// skip any preceding whitespace
while
(
mReader
!=
mBuffer
.
end
())
{
if
(
!
isspace
(
*
mReader
))
break
;
// count lines
if
(
*
mReader
==
'\n'
)
mLine
++
;
++
mReader
;
}
// collect all chars till the next whitespace. BVH is easy in respect to that.
std
::
string
token
;
while
(
mReader
!=
mBuffer
.
end
())
{
if
(
isspace
(
*
mReader
))
break
;
token
.
push_back
(
*
mReader
);
++
mReader
;
// little extra logic to make sure braces are counted correctly
if
(
token
==
"{"
||
token
==
"}"
)
break
;
}
// empty token means end of file, which is just fine
return
token
;
}
// ------------------------------------------------------------------------------------------------
// Reads the next token as a float
float
BVHLoader
::
GetNextTokenAsFloat
()
{
std
::
string
token
=
GetNextToken
();
if
(
token
.
empty
())
ThrowException
(
"Unexpected end of file while trying to read a float"
);
// check if the float is valid by testing if the atof() function consumed every char of the token
const
char
*
ctoken
=
token
.
c_str
();
float
result
=
0.0
f
;
ctoken
=
fast_atoreal_move
<
float
>
(
ctoken
,
result
);
if
(
ctoken
!=
token
.
c_str
()
+
token
.
length
())
ThrowException
(
format
()
<<
"Expected a floating point number, but found
\"
"
<<
token
<<
"
\"
."
);
return
result
;
}
// ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception
AI_WONT_RETURN
void
BVHLoader
::
ThrowException
(
const
std
::
string
&
pError
)
{
throw
DeadlyImportError
(
format
()
<<
mFileName
<<
":"
<<
mLine
<<
" - "
<<
pError
);
}
// ------------------------------------------------------------------------------------------------
// Constructs an animation for the motion data and stores it in the given scene
void
BVHLoader
::
CreateAnimation
(
aiScene
*
pScene
)
{
// create the animation
pScene
->
mNumAnimations
=
1
;
pScene
->
mAnimations
=
new
aiAnimation
*
[
1
];
aiAnimation
*
anim
=
new
aiAnimation
;
pScene
->
mAnimations
[
0
]
=
anim
;
// put down the basic parameters
anim
->
mName
.
Set
(
"Motion"
);
anim
->
mTicksPerSecond
=
1.0
/
double
(
mAnimTickDuration
);
anim
->
mDuration
=
double
(
mAnimNumFrames
-
1
);
// now generate the tracks for all nodes
anim
->
mNumChannels
=
static_cast
<
unsigned
int
>
(
mNodes
.
size
());
anim
->
mChannels
=
new
aiNodeAnim
*
[
anim
->
mNumChannels
];
// FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown
for
(
unsigned
int
i
=
0
;
i
<
anim
->
mNumChannels
;
++
i
)
anim
->
mChannels
[
i
]
=
NULL
;
for
(
unsigned
int
a
=
0
;
a
<
anim
->
mNumChannels
;
a
++
)
{
const
Node
&
node
=
mNodes
[
a
];
const
std
::
string
nodeName
=
std
::
string
(
node
.
mNode
->
mName
.
data
);
aiNodeAnim
*
nodeAnim
=
new
aiNodeAnim
;
anim
->
mChannels
[
a
]
=
nodeAnim
;
nodeAnim
->
mNodeName
.
Set
(
nodeName
);
std
::
map
<
BVHLoader
::
ChannelType
,
int
>
channelMap
;
//Build map of channels
for
(
unsigned
int
channel
=
0
;
channel
<
node
.
mChannels
.
size
();
++
channel
)
{
channelMap
[
node
.
mChannels
[
channel
]]
=
channel
;
}
// translational part, if given
if
(
node
.
mChannels
.
size
()
==
6
)
{
nodeAnim
->
mNumPositionKeys
=
mAnimNumFrames
;
nodeAnim
->
mPositionKeys
=
new
aiVectorKey
[
mAnimNumFrames
];
aiVectorKey
*
poskey
=
nodeAnim
->
mPositionKeys
;
for
(
unsigned
int
fr
=
0
;
fr
<
mAnimNumFrames
;
++
fr
)
{
poskey
->
mTime
=
double
(
fr
);
// Now compute all translations
for
(
BVHLoader
::
ChannelType
channel
=
Channel_PositionX
;
channel
<=
Channel_PositionZ
;
channel
=
(
BVHLoader
::
ChannelType
)(
channel
+
1
))
{
//Find channel in node
std
::
map
<
BVHLoader
::
ChannelType
,
int
>::
iterator
mapIter
=
channelMap
.
find
(
channel
);
if
(
mapIter
==
channelMap
.
end
())
throw
DeadlyImportError
(
"Missing position channel in node "
+
nodeName
);
else
{
int
channelIdx
=
mapIter
->
second
;
switch
(
channel
)
{
case
Channel_PositionX
:
poskey
->
mValue
.
x
=
node
.
mChannelValues
[
fr
*
node
.
mChannels
.
size
()
+
channelIdx
];
break
;
case
Channel_PositionY
:
poskey
->
mValue
.
y
=
node
.
mChannelValues
[
fr
*
node
.
mChannels
.
size
()
+
channelIdx
];
break
;
case
Channel_PositionZ
:
poskey
->
mValue
.
z
=
node
.
mChannelValues
[
fr
*
node
.
mChannels
.
size
()
+
channelIdx
];
break
;
default:
break
;
}
}
}
++
poskey
;
}
}
else
{
// if no translation part is given, put a default sequence
aiVector3D
nodePos
(
node
.
mNode
->
mTransformation
.
a4
,
node
.
mNode
->
mTransformation
.
b4
,
node
.
mNode
->
mTransformation
.
c4
);
nodeAnim
->
mNumPositionKeys
=
1
;
nodeAnim
->
mPositionKeys
=
new
aiVectorKey
[
1
];
nodeAnim
->
mPositionKeys
[
0
].
mTime
=
0.0
;
nodeAnim
->
mPositionKeys
[
0
].
mValue
=
nodePos
;
}
// rotation part. Always present. First find value offsets
{
// Then create the number of rotation keys
nodeAnim
->
mNumRotationKeys
=
mAnimNumFrames
;
nodeAnim
->
mRotationKeys
=
new
aiQuatKey
[
mAnimNumFrames
];
aiQuatKey
*
rotkey
=
nodeAnim
->
mRotationKeys
;
for
(
unsigned
int
fr
=
0
;
fr
<
mAnimNumFrames
;
++
fr
)
{
aiMatrix4x4
temp
;
aiMatrix3x3
rotMatrix
;
for
(
BVHLoader
::
ChannelType
channel
=
Channel_RotationX
;
channel
<=
Channel_RotationZ
;
channel
=
(
BVHLoader
::
ChannelType
)(
channel
+
1
))
{
//Find channel in node
std
::
map
<
BVHLoader
::
ChannelType
,
int
>::
iterator
mapIter
=
channelMap
.
find
(
channel
);
if
(
mapIter
==
channelMap
.
end
())
throw
DeadlyImportError
(
"Missing rotation channel in node "
+
nodeName
);
else
{
int
channelIdx
=
mapIter
->
second
;
// translate ZXY euler angels into a quaternion
const
float
angle
=
node
.
mChannelValues
[
fr
*
node
.
mChannels
.
size
()
+
channelIdx
]
*
float
(
AI_MATH_PI
)
/
180.0
f
;
// Compute rotation transformations in the right order
switch
(
channel
)
{
case
Channel_RotationX
:
aiMatrix4x4
::
RotationX
(
angle
,
temp
);
rotMatrix
*=
aiMatrix3x3
(
temp
);
break
;
case
Channel_RotationY
:
aiMatrix4x4
::
RotationY
(
angle
,
temp
);
rotMatrix
*=
aiMatrix3x3
(
temp
);
break
;
case
Channel_RotationZ
:
aiMatrix4x4
::
RotationZ
(
angle
,
temp
);
rotMatrix
*=
aiMatrix3x3
(
temp
);
break
;
default:
break
;
}
}
}
rotkey
->
mTime
=
double
(
fr
);
rotkey
->
mValue
=
aiQuaternion
(
rotMatrix
);
++
rotkey
;
}
}
// scaling part. Always just a default track
{
nodeAnim
->
mNumScalingKeys
=
1
;
nodeAnim
->
mScalingKeys
=
new
aiVectorKey
[
1
];
nodeAnim
->
mScalingKeys
[
0
].
mTime
=
0.0
;
nodeAnim
->
mScalingKeys
[
0
].
mValue
.
Set
(
1.0
f
,
1.0
f
,
1.0
f
);
}
}
}
#endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER
deps/assimp/code/AssetLib/BVH/BVHLoader.h
0 → 100644
View file @
c6fcf2f0
/** Defines the BHV motion capturing loader class */
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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 BVHLoader.h
* @brief Biovision BVH import
*/
#ifndef AI_BVHLOADER_H_INC
#define AI_BVHLOADER_H_INC
#include <assimp/BaseImporter.h>
struct
aiNode
;
namespace
Assimp
{
// --------------------------------------------------------------------------------
/** Loader class to read Motion Capturing data from a .bvh file.
*
* This format only contains a hierarchy of joints and a series of keyframes for
* the hierarchy. It contains no actual mesh data, but we generate a dummy mesh
* inside the loader just to be able to see something.
*/
class
BVHLoader
:
public
BaseImporter
{
/** Possible animation channels for which the motion data holds the values */
enum
ChannelType
{
Channel_PositionX
,
Channel_PositionY
,
Channel_PositionZ
,
Channel_RotationX
,
Channel_RotationY
,
Channel_RotationZ
};
/** Collected list of node. Will be bones of the dummy mesh some day, addressed by their array index */
struct
Node
{
const
aiNode
*
mNode
;
std
::
vector
<
ChannelType
>
mChannels
;
std
::
vector
<
float
>
mChannelValues
;
// motion data values for that node. Of size NumChannels * NumFrames
Node
()
:
mNode
(
nullptr
)
{}
explicit
Node
(
const
aiNode
*
pNode
)
:
mNode
(
pNode
)
{}
};
public:
BVHLoader
();
~
BVHLoader
();
public:
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */
bool
CanRead
(
const
std
::
string
&
pFile
,
IOSystem
*
pIOHandler
,
bool
cs
)
const
;
void
SetupProperties
(
const
Importer
*
pImp
);
const
aiImporterDesc
*
GetInfo
()
const
;
protected:
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void
InternReadFile
(
const
std
::
string
&
pFile
,
aiScene
*
pScene
,
IOSystem
*
pIOHandler
);
protected:
/** Reads the file */
void
ReadStructure
(
aiScene
*
pScene
);
/** Reads the hierarchy */
void
ReadHierarchy
(
aiScene
*
pScene
);
/** Reads a node and recursively its childs and returns the created node. */
aiNode
*
ReadNode
();
/** Reads an end node and returns the created node. */
aiNode
*
ReadEndSite
(
const
std
::
string
&
pParentName
);
/** Reads a node offset for the given node */
void
ReadNodeOffset
(
aiNode
*
pNode
);
/** Reads the animation channels into the given node */
void
ReadNodeChannels
(
BVHLoader
::
Node
&
pNode
);
/** Reads the motion data */
void
ReadMotion
(
aiScene
*
pScene
);
/** Retrieves the next token */
std
::
string
GetNextToken
();
/** Reads the next token as a float */
float
GetNextTokenAsFloat
();
/** Aborts the file reading with an exception */
AI_WONT_RETURN
void
ThrowException
(
const
std
::
string
&
pError
)
AI_WONT_RETURN_SUFFIX
;
/** Constructs an animation for the motion data and stores it in the given scene */
void
CreateAnimation
(
aiScene
*
pScene
);
protected:
/** Filename, for a verbose error message */
std
::
string
mFileName
;
/** Buffer to hold the loaded file */
std
::
vector
<
char
>
mBuffer
;
/** Next char to read from the buffer */
std
::
vector
<
char
>::
const_iterator
mReader
;
/** Current line, for error messages */
unsigned
int
mLine
;
/** Collected list of nodes. Will be bones of the dummy mesh some day, addressed by their array index.
* Also contain the motion data for the node's channels
*/
std
::
vector
<
Node
>
mNodes
;
/** basic Animation parameters */
float
mAnimTickDuration
;
unsigned
int
mAnimNumFrames
;
bool
noSkeletonMesh
;
};
}
// end of namespace Assimp
#endif // AI_BVHLOADER_H_INC
deps/assimp/code/AssetLib/Blender/BlenderBMesh.cpp
0 → 100644
View file @
c6fcf2f0
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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 "BlenderBMesh.h"
#include "BlenderDNA.h"
#include "BlenderScene.h"
#include "BlenderTessellator.h"
namespace
Assimp
{
template
<
>
const
char
*
LogFunctions
<
BlenderBMeshConverter
>::
Prefix
()
{
static
auto
prefix
=
"BLEND_BMESH: "
;
return
prefix
;
}
}
// namespace Assimp
using
namespace
Assimp
;
using
namespace
Assimp
::
Blender
;
using
namespace
Assimp
::
Formatter
;
// ------------------------------------------------------------------------------------------------
BlenderBMeshConverter
::
BlenderBMeshConverter
(
const
Mesh
*
mesh
)
:
BMesh
(
mesh
),
triMesh
(
nullptr
)
{
ai_assert
(
nullptr
!=
mesh
);
}
// ------------------------------------------------------------------------------------------------
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
=
nullptr
;
}
// ------------------------------------------------------------------------------------------------
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
;
face
.
flag
=
0
;
// 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
deps/assimp/code/AssetLib/Blender/BlenderBMesh.h
0 → 100644
View file @
c6fcf2f0
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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
deps/assimp/code/AssetLib/Blender/BlenderCustomData.cpp
0 → 100644
View file @
c6fcf2f0
#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
;
}
}
// namespace Blender
}
// namespace Assimp
deps/assimp/code/AssetLib/Blender/BlenderCustomData.h
0 → 100644
View file @
c6fcf2f0
#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
);
}
}
Prev
1
2
3
4
5
6
7
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment