167 lines
6.0 KiB
C++
167 lines
6.0 KiB
C++
/**
|
|
* Copyright (c) 2014-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <fstream>
|
|
|
|
#include "FBX2glTF.h"
|
|
|
|
#include "gltf/properties/AccessorData.hpp"
|
|
#include "gltf/properties/AnimationData.hpp"
|
|
#include "gltf/properties/BufferData.hpp"
|
|
#include "gltf/properties/BufferViewData.hpp"
|
|
#include "gltf/properties/CameraData.hpp"
|
|
#include "gltf/properties/ImageData.hpp"
|
|
#include "gltf/properties/MaterialData.hpp"
|
|
#include "gltf/properties/MeshData.hpp"
|
|
#include "gltf/properties/NodeData.hpp"
|
|
#include "gltf/properties/PrimitiveData.hpp"
|
|
#include "gltf/properties/SamplerData.hpp"
|
|
#include "gltf/properties/SceneData.hpp"
|
|
#include "gltf/properties/SkinData.hpp"
|
|
#include "gltf/properties/TextureData.hpp"
|
|
|
|
/**
|
|
* glTF 2.0 is based on the idea that data structs within a file are referenced by index; an accessor will
|
|
* point to the n:th buffer view, and so on. The Holder class takes a freshly instantiated class, and then
|
|
* creates, stored, and returns a shared_ptr<T> for it.
|
|
*
|
|
* The idea is that every glTF resource in the file will live as long as the Holder does, and the Holders
|
|
* are all kept in the GLTFData struct. Clients may certainly cnhoose to perpetuate the full shared_ptr<T>
|
|
* reference counting type, but generally speaking we pass around simple T& and T* types because the GLTFData
|
|
* struct will, by design, outlive all other activity that takes place during in a single conversion run.
|
|
*/
|
|
template<typename T>
|
|
class Holder
|
|
{
|
|
public:
|
|
std::shared_ptr<T> hold(T *ptr)
|
|
{
|
|
ptr->ix = ptrs.size();
|
|
ptrs.emplace_back(ptr);
|
|
return ptrs.back();
|
|
}
|
|
std::vector<std::shared_ptr<T>> ptrs;
|
|
};
|
|
|
|
class GltfModel
|
|
{
|
|
public:
|
|
explicit GltfModel(const GltfOptions &options)
|
|
: binary(new std::vector<uint8_t>)
|
|
, isGlb(options.outputBinary)
|
|
, defaultSampler(nullptr)
|
|
, defaultBuffer(buffers.hold(buildDefaultBuffer(options)))
|
|
{
|
|
defaultSampler = samplers.hold(buildDefaultSampler());
|
|
}
|
|
|
|
std::shared_ptr<BufferViewData> GetAlignedBufferView(BufferData &buffer, const BufferViewData::GL_ArrayType target);
|
|
std::shared_ptr<BufferViewData> AddRawBufferView(BufferData &buffer, const char *source, uint32_t bytes);
|
|
std::shared_ptr<BufferViewData> AddBufferViewForFile(BufferData &buffer, const std::string &filename);
|
|
|
|
template<class T>
|
|
std::shared_ptr<AccessorData> AddAccessorWithView(
|
|
BufferViewData &bufferView, const GLType &type, const std::vector<T> &source, std::string name)
|
|
{
|
|
auto accessor = accessors.hold(new AccessorData(bufferView, type, name));
|
|
accessor->appendAsBinaryArray(source, *binary);
|
|
bufferView.byteLength = accessor->byteLength();
|
|
return accessor;
|
|
}
|
|
|
|
template<class T>
|
|
std::shared_ptr<AccessorData> AddAccessorAndView(
|
|
BufferData &buffer, const GLType &type, const std::vector<T> &source)
|
|
{
|
|
auto bufferView = GetAlignedBufferView(buffer, BufferViewData::GL_ARRAY_NONE);
|
|
return AddAccessorWithView(*bufferView, type, source, std::string(""));
|
|
}
|
|
|
|
template<class T>
|
|
std::shared_ptr<AccessorData> AddAccessorAndView(
|
|
BufferData &buffer, const GLType &type, const std::vector<T> &source, std::string name)
|
|
{
|
|
auto bufferView = GetAlignedBufferView(buffer, BufferViewData::GL_ARRAY_NONE);
|
|
return AddAccessorWithView(*bufferView, type, source, name);
|
|
}
|
|
|
|
template<class T>
|
|
std::shared_ptr<AccessorData> AddAttributeToPrimitive(
|
|
BufferData &buffer, const RawModel &surfaceModel, PrimitiveData &primitive,
|
|
const AttributeDefinition<T> &attrDef)
|
|
{
|
|
// copy attribute data into vector
|
|
std::vector<T> attribArr;
|
|
surfaceModel.GetAttributeArray<T>(attribArr, attrDef.rawAttributeIx);
|
|
|
|
std::shared_ptr<AccessorData> accessor;
|
|
if (attrDef.dracoComponentType != draco::DT_INVALID && primitive.dracoMesh != nullptr) {
|
|
primitive.AddDracoAttrib(attrDef, attribArr);
|
|
|
|
accessor = accessors.hold(new AccessorData(attrDef.glType));
|
|
accessor->count = attribArr.size();
|
|
} else {
|
|
auto bufferView = GetAlignedBufferView(buffer, BufferViewData::GL_ARRAY_BUFFER);
|
|
accessor = AddAccessorWithView(*bufferView, attrDef.glType, attribArr, std::string(""));
|
|
}
|
|
primitive.AddAttrib(attrDef.gltfName, *accessor);
|
|
return accessor;
|
|
};
|
|
|
|
template<class T>
|
|
void serializeHolder(json &glTFJson, std::string key, const Holder<T> holder)
|
|
{
|
|
if (!holder.ptrs.empty()) {
|
|
std::vector<json> bits;
|
|
for (const auto &ptr : holder.ptrs) {
|
|
bits.push_back(ptr->serialize());
|
|
}
|
|
glTFJson[key] = bits;
|
|
}
|
|
}
|
|
|
|
void serializeHolders(json &glTFJson);
|
|
|
|
const bool isGlb;
|
|
|
|
// cache BufferViewData instances that've already been created from a given filename
|
|
std::map<std::string, std::shared_ptr<BufferViewData>> filenameToBufferView;
|
|
|
|
std::shared_ptr<std::vector<uint8_t>> binary;
|
|
|
|
Holder<BufferData> buffers;
|
|
Holder<BufferViewData> bufferViews;
|
|
Holder<AccessorData> accessors;
|
|
Holder<ImageData> images;
|
|
Holder<SamplerData> samplers;
|
|
Holder<TextureData> textures;
|
|
Holder<MaterialData> materials;
|
|
Holder<MeshData> meshes;
|
|
Holder<SkinData> skins;
|
|
Holder<AnimationData> animations;
|
|
Holder<CameraData> cameras;
|
|
Holder<NodeData> nodes;
|
|
Holder<SceneData> scenes;
|
|
|
|
std::shared_ptr<SamplerData> defaultSampler;
|
|
std::shared_ptr<BufferData> defaultBuffer;
|
|
|
|
private:
|
|
SamplerData *buildDefaultSampler() {
|
|
return new SamplerData();
|
|
}
|
|
BufferData *buildDefaultBuffer(const GltfOptions &options) {
|
|
return options.outputBinary ?
|
|
new BufferData(binary) :
|
|
new BufferData(extBufferFilename, binary, options.embedResources);
|
|
}
|
|
};
|