Created exporter class and fixed a few bugs
parent
148a20a703
commit
b307ec643d
|
@ -568,6 +568,9 @@ ADD_ASSIMP_IMPORTER(GLTF
|
||||||
glTFUtil.cpp
|
glTFUtil.cpp
|
||||||
glTFUtil.h
|
glTFUtil.h
|
||||||
glTFFileData.h
|
glTFFileData.h
|
||||||
|
|
||||||
|
glTFExporter.h
|
||||||
|
glTFExporter.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
SET( Step_SRCS
|
SET( Step_SRCS
|
||||||
|
|
|
@ -87,6 +87,8 @@ void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportPro
|
||||||
void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
|
void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
|
void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
|
|
||||||
|
@ -135,6 +137,13 @@ Exporter::ExportFormatEntry gExporters[] =
|
||||||
aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
|
aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
|
||||||
|
Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF,
|
||||||
|
aiProcess_JoinIdenticalVertices),
|
||||||
|
Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
|
||||||
|
aiProcess_JoinIdenticalVertices),
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
|
||||||
Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0),
|
Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0),
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,401 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2015, 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_EXPORT
|
||||||
|
#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
|
||||||
|
|
||||||
|
#include "glTFExporter.h"
|
||||||
|
#include "Exceptional.h"
|
||||||
|
#include "StringComparison.h"
|
||||||
|
#include "ByteSwapper.h"
|
||||||
|
|
||||||
|
#include <assimp/version.h>
|
||||||
|
#include <assimp/IOSystem.hpp>
|
||||||
|
#include <assimp/Exporter.hpp>
|
||||||
|
#include <assimp/material.h>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
|
||||||
|
#define RAPIDJSON_HAS_STDSTRING 1
|
||||||
|
#include <rapidjson/document.h>
|
||||||
|
#include <rapidjson/writer.h>
|
||||||
|
#include <rapidjson/prettywriter.h>
|
||||||
|
#include <rapidjson/stringbuffer.h>
|
||||||
|
|
||||||
|
#include "glTFFileData.h"
|
||||||
|
#include "glTFUtil.h"
|
||||||
|
|
||||||
|
using namespace rapidjson;
|
||||||
|
|
||||||
|
using namespace Assimp;
|
||||||
|
using namespace Assimp::glTF;
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// Worker function for exporting a scene to GLTF. Prototyped and registered in Exporter.cpp
|
||||||
|
void ExportSceneGLTF(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
|
||||||
|
{
|
||||||
|
// invoke the exporter
|
||||||
|
glTFExporter exporter(pFile, pIOSystem, pScene, pProperties, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// Worker function for exporting a scene to GLB. Prototyped and registered in Exporter.cpp
|
||||||
|
void ExportSceneGLB(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
|
||||||
|
{
|
||||||
|
// invoke the exporter
|
||||||
|
glTFExporter exporter(pFile, pIOSystem, pScene, pProperties, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace Assimp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class glTFSceneExporter
|
||||||
|
{
|
||||||
|
typedef std::gltf_unordered_map<std::string, int> IdMap;
|
||||||
|
|
||||||
|
Document& mDoc;
|
||||||
|
MemoryPoolAllocator<>& mAl;
|
||||||
|
|
||||||
|
const aiScene* mScene;
|
||||||
|
|
||||||
|
std::string mRootNodeId;
|
||||||
|
|
||||||
|
std::vector<std::string> mMeshIds;
|
||||||
|
|
||||||
|
IdMap mUsedIds;
|
||||||
|
|
||||||
|
public:
|
||||||
|
glTFSceneExporter(Document& doc, const aiScene* pScene)
|
||||||
|
: mDoc(doc)
|
||||||
|
, mAl(doc.GetAllocator())
|
||||||
|
, mScene(pScene)
|
||||||
|
{
|
||||||
|
doc.SetObject();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < pScene->mNumLights; ++i) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < pScene->mNumLights; ++i) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AddMeshes();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AddNodes();
|
||||||
|
|
||||||
|
CreateScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Pushf(Value& val, float f)
|
||||||
|
{
|
||||||
|
val.PushBack(Value(f).Move(), mAl);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetMatrix(Value& v, const aiMatrix4x4& m)
|
||||||
|
{
|
||||||
|
v.SetArray();
|
||||||
|
v.Reserve(16, mAl);
|
||||||
|
|
||||||
|
Pushf(v, m.a1); Pushf(v, m.b1); Pushf(v, m.c1); Pushf(v, m.d1);
|
||||||
|
Pushf(v, m.a2); Pushf(v, m.b2); Pushf(v, m.c2); Pushf(v, m.d2);
|
||||||
|
Pushf(v, m.a3); Pushf(v, m.b3); Pushf(v, m.c3); Pushf(v, m.d3);
|
||||||
|
Pushf(v, m.a4); Pushf(v, m.b4); Pushf(v, m.c4); Pushf(v, m.d4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddMeshes()
|
||||||
|
{
|
||||||
|
if (mScene->mNumMeshes == 0) return;
|
||||||
|
|
||||||
|
Value meshes;
|
||||||
|
meshes.SetObject();
|
||||||
|
|
||||||
|
mMeshIds.reserve(mScene->mNumMeshes);
|
||||||
|
for (unsigned int i = 0; i < mScene->mNumMeshes; ++i) {
|
||||||
|
aiMesh* m = mScene->mMeshes[i];
|
||||||
|
std::string meshId = FindID(m->mName, "mesh");
|
||||||
|
mMeshIds.push_back(meshId);
|
||||||
|
|
||||||
|
Value mesh;
|
||||||
|
mesh.SetObject();
|
||||||
|
{
|
||||||
|
Value primitives;
|
||||||
|
primitives.SetObject();
|
||||||
|
|
||||||
|
|
||||||
|
mesh.AddMember("primitives", primitives, mAl);
|
||||||
|
}
|
||||||
|
|
||||||
|
meshes.AddMember(StringRef(mMeshIds.back()), mesh, mAl);
|
||||||
|
}
|
||||||
|
|
||||||
|
mDoc.AddMember("meshes", meshes, mAl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddNodes()
|
||||||
|
{
|
||||||
|
if (!mScene->mRootNode) return;
|
||||||
|
|
||||||
|
Value nodes;
|
||||||
|
nodes.SetObject();
|
||||||
|
|
||||||
|
mRootNodeId = AddNode(nodes, mScene->mRootNode);
|
||||||
|
|
||||||
|
mDoc.AddMember("nodes", nodes, mAl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string AddNode(Value& nodes, const aiNode* n)
|
||||||
|
{
|
||||||
|
std::string nodeId = FindID(n->mName, "node");
|
||||||
|
|
||||||
|
Value node;
|
||||||
|
node.SetObject();
|
||||||
|
|
||||||
|
if (!n->mTransformation.IsIdentity()) {
|
||||||
|
Value matrix;
|
||||||
|
SetMatrix(matrix, n->mTransformation);
|
||||||
|
node.AddMember("matrix", matrix, mAl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n->mNumMeshes > 0) {
|
||||||
|
Value meshes;
|
||||||
|
meshes.SetArray();
|
||||||
|
for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
|
||||||
|
meshes.PushBack(StringRef(mMeshIds[n->mMeshes[i]]), mAl);
|
||||||
|
}
|
||||||
|
node.AddMember("meshes", meshes, mAl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n->mNumChildren > 0) {
|
||||||
|
Value children;
|
||||||
|
children.SetArray();
|
||||||
|
for (unsigned int i = 0; i < n->mNumChildren; ++i) {
|
||||||
|
std::string id = AddNode(nodes, n->mChildren[i]);
|
||||||
|
children.PushBack(Value(id, mAl), mAl);
|
||||||
|
}
|
||||||
|
node.AddMember("children", children, mAl);
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes.AddMember(Value(nodeId, mAl), node, mAl);
|
||||||
|
|
||||||
|
return nodeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateScene()
|
||||||
|
{
|
||||||
|
const char* sceneName = "defaultScene";
|
||||||
|
|
||||||
|
mDoc.AddMember("scene", Value(sceneName, mAl), mAl);
|
||||||
|
|
||||||
|
Value scenes;
|
||||||
|
scenes.SetObject();
|
||||||
|
{
|
||||||
|
Value scene;
|
||||||
|
scene.SetObject();
|
||||||
|
{
|
||||||
|
Value nodes;
|
||||||
|
nodes.SetArray();
|
||||||
|
|
||||||
|
if (!mRootNodeId.empty()) {
|
||||||
|
nodes.PushBack(StringRef(mRootNodeId), mAl);
|
||||||
|
}
|
||||||
|
|
||||||
|
scene.AddMember("nodes", nodes, mAl);
|
||||||
|
}
|
||||||
|
scenes.AddMember(Value(sceneName, mAl), scene, mAl);
|
||||||
|
}
|
||||||
|
mDoc.AddMember("scenes", scenes, mAl);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FindID(const aiString& str, const char* suffix)
|
||||||
|
{
|
||||||
|
std::string id = str.C_Str();
|
||||||
|
|
||||||
|
IdMap::iterator it;
|
||||||
|
|
||||||
|
if (!id.empty()) {
|
||||||
|
it = mUsedIds.find(id);
|
||||||
|
if (it == mUsedIds.end()) goto found;
|
||||||
|
|
||||||
|
id += "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
id += suffix;
|
||||||
|
|
||||||
|
it = mUsedIds.find(id);
|
||||||
|
if (it == mUsedIds.end()) goto found;
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
int offset = sprintf(buffer, "%s-", id.c_str());
|
||||||
|
for (int i = 0; ; ++i) {
|
||||||
|
ASSIMP_itoa10(buffer + offset, sizeof(buffer), i);
|
||||||
|
|
||||||
|
id = buffer;
|
||||||
|
it = mUsedIds.find(id);
|
||||||
|
if (it == mUsedIds.end()) goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
found:
|
||||||
|
mUsedIds[id] = true;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
|
||||||
|
const ExportProperties* pProperties, bool isBinary)
|
||||||
|
: mFilename(filename)
|
||||||
|
, mIOSystem(pIOSystem)
|
||||||
|
, mScene(pScene)
|
||||||
|
, mProperties(pProperties)
|
||||||
|
, mIsBinary(isBinary)
|
||||||
|
{
|
||||||
|
boost::scoped_ptr<IOStream> outfile(pIOSystem->Open(mFilename, "wt"));
|
||||||
|
if (outfile == 0) {
|
||||||
|
throw DeadlyExportError("Could not open output file: " + std::string(mFilename));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBinary) {
|
||||||
|
// we will write the header later, skip its size
|
||||||
|
outfile->Seek(sizeof(GLB_Header), aiOrigin_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Document doc;
|
||||||
|
StringBuffer docBuffer;
|
||||||
|
{
|
||||||
|
glTFSceneExporter exportScene(doc, mScene);
|
||||||
|
|
||||||
|
bool pretty = true;
|
||||||
|
if (!isBinary && pretty) {
|
||||||
|
PrettyWriter<StringBuffer> writer(docBuffer);
|
||||||
|
doc.Accept(writer);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Writer<StringBuffer> writer(docBuffer);
|
||||||
|
doc.Accept(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
|
||||||
|
throw DeadlyExportError("Failed to write scene data!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBinary) {
|
||||||
|
WriteBinaryData(outfile.get(), docBuffer.GetSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void glTFExporter::WriteBinaryData(IOStream* outfile, std::size_t sceneLength)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// write the body data
|
||||||
|
//
|
||||||
|
|
||||||
|
if (!mBodyData.empty()) {
|
||||||
|
std::size_t bodyOffset = sizeof(GLB_Header) + sceneLength;
|
||||||
|
bodyOffset = (bodyOffset + 3) & ~3; // Round up to next multiple of 4
|
||||||
|
|
||||||
|
outfile->Seek(bodyOffset, aiOrigin_SET);
|
||||||
|
|
||||||
|
if (outfile->Write(&mBodyData[0], mBodyData.size(), 1) != 1) {
|
||||||
|
throw DeadlyExportError("Failed to write body data!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// write the header
|
||||||
|
//
|
||||||
|
|
||||||
|
outfile->Seek(0, aiOrigin_SET);
|
||||||
|
|
||||||
|
GLB_Header header;
|
||||||
|
memcpy(header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic));
|
||||||
|
|
||||||
|
header.version = 1;
|
||||||
|
AI_SWAP4(header.version);
|
||||||
|
|
||||||
|
header.length = sizeof(header) + sceneLength + mBodyData.size();
|
||||||
|
AI_SWAP4(header.length);
|
||||||
|
|
||||||
|
header.sceneLength = sceneLength;
|
||||||
|
AI_SWAP4(header.sceneLength);
|
||||||
|
|
||||||
|
header.sceneFormat = SceneFormat_JSON;
|
||||||
|
AI_SWAP4(header.sceneFormat);
|
||||||
|
|
||||||
|
if (outfile->Write(&header, sizeof(header), 1) != 1) {
|
||||||
|
throw DeadlyExportError("Failed to write the header!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ASSIMP_BUILD_NO_GLTF_EXPORTER
|
||||||
|
#endif // ASSIMP_BUILD_NO_EXPORT
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2015, 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 GltfExporter.h
|
||||||
|
* Declares the exporter class to write a scene to a gltf/glb file
|
||||||
|
*/
|
||||||
|
#ifndef AI_GLTFEXPORTER_H_INC
|
||||||
|
#define AI_GLTFEXPORTER_H_INC
|
||||||
|
|
||||||
|
#include <assimp/types.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
struct aiScene;
|
||||||
|
|
||||||
|
namespace Assimp
|
||||||
|
{
|
||||||
|
class IOSystem;
|
||||||
|
class IOStream;
|
||||||
|
class ExportProperties;
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
/** Helper class to export a given scene to an glTF file. */
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
class glTFExporter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Constructor for a specific scene to export
|
||||||
|
glTFExporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
|
||||||
|
const ExportProperties* pProperties, bool binary);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const char* mFilename;
|
||||||
|
IOSystem* mIOSystem;
|
||||||
|
const aiScene* mScene;
|
||||||
|
const ExportProperties* mProperties;
|
||||||
|
bool mIsBinary;
|
||||||
|
|
||||||
|
std::vector<unsigned char> mBodyData;
|
||||||
|
|
||||||
|
void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "glTFFileData.h"
|
#include "glTFFileData.h"
|
||||||
#include "glTFUtil.h"
|
#include "glTFUtil.h"
|
||||||
|
|
||||||
|
#define RAPIDJSON_HAS_STDSTRING 1
|
||||||
#include <rapidjson/rapidjson.h>
|
#include <rapidjson/rapidjson.h>
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
#include <rapidjson/error/en.h>
|
#include <rapidjson/error/en.h>
|
||||||
|
@ -290,6 +291,10 @@ class glTFReader
|
||||||
mScene->mRootNode = root;
|
mScene->mRootNode = root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if (!mScene->mRootNode) {
|
||||||
|
//mScene->mRootNode = new aiNode("EMPTY");
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetMaterialColorProperty(aiMaterial* mat, Value& vals, const char* propName, aiTextureType texType,
|
void SetMaterialColorProperty(aiMaterial* mat, Value& vals, const char* propName, aiTextureType texType,
|
||||||
|
@ -550,13 +555,15 @@ struct Accessor
|
||||||
template<class T>
|
template<class T>
|
||||||
void ExtractData(T*& outData, unsigned int* outCount = 0, unsigned int* outComponents = 0)
|
void ExtractData(T*& outData, unsigned int* outCount = 0, unsigned int* outComponents = 0)
|
||||||
{
|
{
|
||||||
if (!data) return;
|
ai_assert(data);
|
||||||
|
|
||||||
const std::size_t totalSize = elemSize * count;
|
const std::size_t totalSize = elemSize * count;
|
||||||
|
|
||||||
const std::size_t targetElemSize = sizeof(T);
|
const std::size_t targetElemSize = sizeof(T);
|
||||||
ai_assert(elemSize <= targetElemSize);
|
ai_assert(elemSize <= targetElemSize);
|
||||||
|
|
||||||
|
ai_assert(count*byteStride <= bufferView->byteLength);
|
||||||
|
|
||||||
outData = new T[count];
|
outData = new T[count];
|
||||||
if (byteStride == elemSize && targetElemSize == elemSize) {
|
if (byteStride == elemSize && targetElemSize == elemSize) {
|
||||||
memcpy(outData, data, totalSize);
|
memcpy(outData, data, totalSize);
|
||||||
|
@ -574,6 +581,8 @@ struct Accessor
|
||||||
template<class T = unsigned int>
|
template<class T = unsigned int>
|
||||||
T GetValue(int i)
|
T GetValue(int i)
|
||||||
{
|
{
|
||||||
|
ai_assert(data);
|
||||||
|
ai_assert(i*byteStride < bufferView->byteLength);
|
||||||
T value = T();
|
T value = T();
|
||||||
memcpy(&value, data + i*byteStride, elemSize);
|
memcpy(&value, data + i*byteStride, elemSize);
|
||||||
//value >>= 8 * (sizeof(T) - elemSize);
|
//value >>= 8 * (sizeof(T) - elemSize);
|
||||||
|
@ -708,9 +717,11 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
|
||||||
else if (strcmp(attr, "NORMAL") == 0) {
|
else if (strcmp(attr, "NORMAL") == 0) {
|
||||||
accessor->ExtractData(aimesh->mNormals);
|
accessor->ExtractData(aimesh->mNormals);
|
||||||
}
|
}
|
||||||
else if (strncmp(attr, "TEXCOORD_", 9) == 0) {
|
else if (strncmp(attr, "TEXCOORD_", 9) == 0) {
|
||||||
int idx = attr[9] - '0';
|
int idx = attr[9] - '0';
|
||||||
accessor->ExtractData(aimesh->mTextureCoords[idx], 0, &aimesh->mNumUVComponents[idx]);
|
if (idx >= 0 && idx <= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
||||||
|
accessor->ExtractData(aimesh->mTextureCoords[idx], 0, &aimesh->mNumUVComponents[idx]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -727,7 +738,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
|
||||||
case PrimitiveMode_POINTS: {
|
case PrimitiveMode_POINTS: {
|
||||||
nFaces = acc->count;
|
nFaces = acc->count;
|
||||||
faces = new aiFace[nFaces];
|
faces = new aiFace[nFaces];
|
||||||
for (unsigned i = 0; i < acc->count; ++i) {
|
for (unsigned int i = 0; i < acc->count; ++i) {
|
||||||
setFace(faces[i], acc->GetValue(i));
|
setFace(faces[i], acc->GetValue(i));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -736,7 +747,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
|
||||||
case PrimitiveMode_LINES: {
|
case PrimitiveMode_LINES: {
|
||||||
nFaces = acc->count / 2;
|
nFaces = acc->count / 2;
|
||||||
faces = new aiFace[nFaces];
|
faces = new aiFace[nFaces];
|
||||||
for (unsigned i = 0; i < acc->count; i += 2) {
|
for (unsigned int i = 0; i < acc->count; i += 2) {
|
||||||
setFace(faces[i / 2], acc->GetValue(i), acc->GetValue(i + 1));
|
setFace(faces[i / 2], acc->GetValue(i), acc->GetValue(i + 1));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -747,7 +758,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
|
||||||
nFaces = acc->count - ((primitiveMode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
|
nFaces = acc->count - ((primitiveMode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
|
||||||
faces = new aiFace[nFaces];
|
faces = new aiFace[nFaces];
|
||||||
setFace(faces[0], acc->GetValue(0), acc->GetValue(1));
|
setFace(faces[0], acc->GetValue(0), acc->GetValue(1));
|
||||||
for (unsigned i = 2; i < acc->count; ++i) {
|
for (unsigned int i = 2; i < acc->count; ++i) {
|
||||||
setFace(faces[i - 1], faces[i - 2].mIndices[1], acc->GetValue(i));
|
setFace(faces[i - 1], faces[i - 2].mIndices[1], acc->GetValue(i));
|
||||||
}
|
}
|
||||||
if (primitiveMode == PrimitiveMode_LINE_LOOP) { // close the loop
|
if (primitiveMode == PrimitiveMode_LINE_LOOP) { // close the loop
|
||||||
|
@ -759,7 +770,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
|
||||||
case PrimitiveMode_TRIANGLES: {
|
case PrimitiveMode_TRIANGLES: {
|
||||||
nFaces = acc->count / 3;
|
nFaces = acc->count / 3;
|
||||||
faces = new aiFace[nFaces];
|
faces = new aiFace[nFaces];
|
||||||
for (unsigned i = 0; i < acc->count; i += 3) {
|
for (unsigned int i = 0; i < acc->count; i += 3) {
|
||||||
setFace(faces[i / 3], acc->GetValue(i), acc->GetValue(i + 1), acc->GetValue(i + 2));
|
setFace(faces[i / 3], acc->GetValue(i), acc->GetValue(i + 1), acc->GetValue(i + 2));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -768,7 +779,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
|
||||||
nFaces = acc->count - 2;
|
nFaces = acc->count - 2;
|
||||||
faces = new aiFace[nFaces];
|
faces = new aiFace[nFaces];
|
||||||
setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2));
|
setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2));
|
||||||
for (unsigned i = 3; i < acc->count; ++i) {
|
for (unsigned int i = 3; i < acc->count; ++i) {
|
||||||
setFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], acc->GetValue(i));
|
setFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], acc->GetValue(i));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -777,7 +788,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
|
||||||
nFaces = acc->count - 2;
|
nFaces = acc->count - 2;
|
||||||
faces = new aiFace[nFaces];
|
faces = new aiFace[nFaces];
|
||||||
setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2));
|
setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2));
|
||||||
for (unsigned i = 3; i < acc->count; ++i) {
|
for (unsigned int i = 3; i < acc->count; ++i) {
|
||||||
setFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], acc->GetValue(i));
|
setFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], acc->GetValue(i));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -986,8 +997,10 @@ aiNode* glTFReader::LoadNode(const char* id, Value& node)
|
||||||
if (child.IsString()) {
|
if (child.IsString()) {
|
||||||
// get/create the child node
|
// get/create the child node
|
||||||
aiNode* aichild = mNodes.Get(child.GetString());
|
aiNode* aichild = mNodes.Get(child.GetString());
|
||||||
aichild->mParent = ainode;
|
if (aichild) {
|
||||||
ainode->mChildren[ainode->mNumChildren++] = aichild;
|
aichild->mParent = ainode;
|
||||||
|
ainode->mChildren[ainode->mNumChildren++] = aichild;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1185,4 +1198,8 @@ void glTFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IO
|
||||||
// import the data
|
// import the data
|
||||||
glTFReader reader(pScene, doc, *pIOHandler, bodyBuffer);
|
glTFReader reader(pScene, doc, *pIOHandler, bodyBuffer);
|
||||||
reader.Load();
|
reader.Load();
|
||||||
|
|
||||||
|
if (pScene->mNumMeshes == 0) {
|
||||||
|
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,24 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "LogAux.h"
|
#include "LogAux.h"
|
||||||
#include "DefaultIOSystem.h"
|
#include "DefaultIOSystem.h"
|
||||||
|
|
||||||
#if _MSC_VER > 1500 || (defined __GNUC___)
|
|
||||||
# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
|
|
||||||
# else
|
|
||||||
# define gltf_unordered_map map
|
|
||||||
# define gltf_unordered_multimap multimap
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
|
|
||||||
# include <unordered_map>
|
|
||||||
# if _MSC_VER > 1600
|
|
||||||
# define gltf_unordered_map unordered_map
|
|
||||||
# define gltf_unordered_multimap unordered_multimap
|
|
||||||
# else
|
|
||||||
# define gltf_unordered_map tr1::unordered_map
|
|
||||||
# define gltf_unordered_multimap tr1::unordered_multimap
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -44,6 +44,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//#include "MemoryIOWrapper.h"
|
//#include "MemoryIOWrapper.h"
|
||||||
#include "StringComparison.h"
|
#include "StringComparison.h"
|
||||||
|
|
||||||
|
#if _MSC_VER > 1500 || (defined __GNUC___)
|
||||||
|
# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
|
||||||
|
# else
|
||||||
|
# define gltf_unordered_map map
|
||||||
|
# define gltf_unordered_multimap multimap
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
|
||||||
|
# include <unordered_map>
|
||||||
|
# if _MSC_VER > 1600
|
||||||
|
# define gltf_unordered_map unordered_map
|
||||||
|
# define gltf_unordered_multimap unordered_multimap
|
||||||
|
# else
|
||||||
|
# define gltf_unordered_map tr1::unordered_map
|
||||||
|
# define gltf_unordered_multimap tr1::unordered_multimap
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace glTF {
|
namespace glTF {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue