diff --git a/code/glTFAsset.h b/code/glTFAsset.h index 3b3c513a2..80a2d0008 100644 --- a/code/glTFAsset.h +++ b/code/glTFAsset.h @@ -362,8 +362,6 @@ namespace glTF { return id; } }; - - // // Classes for each glTF top-level object type // @@ -478,6 +476,15 @@ namespace glTF bool LoadFromStream(IOStream& stream, size_t length = 0, size_t baseOffset = 0); + /// \fn bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count) + /// Replace part of buffer data. For example: decoded/encoded data. + /// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed. + /// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced. + /// \param [in] pReplace_Data - pointer to array with new data for buffer. + /// \param [in] pReplace_Count - count of bytes in new data. + /// \return true - if successfully replaced, false if input arguments is out of range. + bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count); + size_t AppendData(uint8_t* data, size_t length); void Grow(size_t amount); @@ -702,10 +709,57 @@ namespace glTF Ref material; }; + /// \struct SExtension + /// Extension used for mesh. + struct SExtension + { + /// \enum EType + /// Type of extension. + enum class EType + { + Compression_Open3DGC ///< Compression of mesh data using Open3DGC algorythm. + }; + + EType Type;///< Type of extension. + + /// \fn SExtension + /// Constructor. + /// \param [in] pType - type of extension. + SExtension(const EType pType) + : Type(pType) + {} + }; + + /// \struct SCompression_Open3DGC + /// Compression of mesh data using Open3DGC algorythm. + struct SCompression_Open3DGC final : public SExtension + { + using SExtension::Type; + + std::string BufferView;///< Name of "bufferView" used for storing compressed data. + size_t Offset;///< Offset in "bufferView" where compressed data are stored. + size_t Count;///< Count of elements in compressed data. Is always equivalent to size in bytes: look comments for "Type" and "Component_Type". + size_t IndicesCount;///< Count of indices in mesh. + size_t VerticesCount;///< Count of vertices in mesh. + // AttribType::Value Type;///< Is always "SCALAR". + // ComponentType Component_Type;///< Is always "ComponentType_UNSIGNED_BYTE" (5121). + + /// \fn SCompression_Open3DGC + /// Constructor. + SCompression_Open3DGC() + : SExtension(EType::Compression_Open3DGC) + {} + }; + std::vector primitives; + std::list Extension;///< List of extensions used in mesh. Mesh() {} + /// \fn ~Mesh() + /// Destructor. + ~Mesh() { for(auto e : Extension) { delete e; }; } + /// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root) /// Get mesh data from JSON-object and place them to root asset. /// \param [in] pJSON_Object - reference to pJSON-object from which data are read. diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index 40740bacc..de9c16575 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -330,6 +330,28 @@ inline bool Buffer::LoadFromStream(IOStream& stream, size_t length, size_t baseO return true; } +inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count) +{ +const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count; + +uint8_t* new_data; + + if((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) return false; + + new_data = new uint8_t[new_data_size]; + // Copy data which place before replacing part. + memcpy(new_data, mData.get(), pBufferData_Offset); + // Copy new data. + memcpy(&new_data[pBufferData_Offset], pReplace_Data, pReplace_Count); + // Copy data which place after replacing part. + memcpy(&new_data[pBufferData_Offset + pReplace_Count], &mData.get()[pBufferData_Offset + pBufferData_Count], pBufferData_Offset); + // Apply new data + mData.reset(new_data); + byteLength = new_data_size; + + return true; +} + inline size_t Buffer::AppendData(uint8_t* data, size_t length) { size_t offset = this->byteLength; diff --git a/code/glTFAssetWriter.inl b/code/glTFAssetWriter.inl index 00c907bcb..e8ca28bb5 100644 --- a/code/glTFAssetWriter.inl +++ b/code/glTFAssetWriter.inl @@ -199,6 +199,53 @@ namespace glTF { inline void Write(Value& obj, Mesh& m, AssetWriter& w) { + /********************* Name **********************/ + obj.AddMember("name", m.name, w.mAl); + + /**************** Mesh extensions ****************/ + if(m.Extension.size() > 0) + { + Value json_extensions; + + json_extensions.SetObject(); + for(Mesh::SExtension* ptr_ext : m.Extension) + { + switch(ptr_ext->Type) + { + case Mesh::SExtension::EType::Compression_Open3DGC: + { + Value json_comp_data; + Mesh::SCompression_Open3DGC* ptr_ext_comp = (Mesh::SCompression_Open3DGC*)ptr_ext; + + // filling object "compressedData" + json_comp_data.SetObject(); + json_comp_data.AddMember("bufferView", ptr_ext_comp->BufferView, w.mAl); + json_comp_data.AddMember("byteOffset", ptr_ext_comp->Offset, w.mAl); + json_comp_data.AddMember("componentType", 5121, w.mAl); + json_comp_data.AddMember("type", "SCALAR", w.mAl); + json_comp_data.AddMember("count", ptr_ext_comp->Count, w.mAl); + json_comp_data.AddMember("indicesCount", ptr_ext_comp->IndicesCount, w.mAl); + json_comp_data.AddMember("verticesCount", ptr_ext_comp->VerticesCount, w.mAl); + // filling object "Open3DGC-compression" + Value json_o3dgc; + + json_o3dgc.SetObject(); + json_o3dgc.AddMember("compressedData", json_comp_data, w.mAl); + // add member to object "extensions" + json_extensions.AddMember("Open3DGC-compression", json_o3dgc, w.mAl); + } + + break; + default: + throw DeadlyImportError("GLTF: Unknown mesh extension, Only Open3DGC is supported."); + }// switch(ptr_ext->Type) + }// for(Mesh::SExtension* ptr_ext : m.Extension) + + // Add extensions to mesh + obj.AddMember("extensions", json_extensions, w.mAl); + }// if(m.Extension.size() > 0) + + /****************** Primitives *******************/ Value primitives; primitives.SetArray(); primitives.Reserve(unsigned(m.primitives.size()), w.mAl); diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index ff5c25675..2f30cd579 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -357,10 +357,16 @@ bool comp_allow;// Point that data of current mesh can be compressed. ///TODO: animation: weights, joints. if(comp_allow) { + // Only one type of compression supported at now - Open3DGC. + // o3dgc::BinaryStream bs; o3dgc::SC3DMCEncoder encoder; o3dgc::IndexedFaceSet comp_o3dgc_ifs; o3dgc::SC3DMCEncodeParams comp_o3dgc_params; + + // + // Fill data for encoder. + // unsigned qcoord = 12;///TODO: dbg unsigned qnormal = 10;///TODO: dbg unsigned qtexCoord = 10;///TODO: dbg @@ -407,10 +413,26 @@ bool comp_allow;// Point that data of current mesh can be compressed. // Prepare to enconding comp_o3dgc_params.SetNumFloatAttributes(comp_o3dgc_ifs.GetNumFloatAttributes()); comp_o3dgc_params.SetStreamType(o3dgc::O3DGC_STREAM_TYPE_BINARY);///TODO: exporter params + // // Encoding + // encoder.Encode(comp_o3dgc_params, comp_o3dgc_ifs, bs); + // Replace data in buffer. + b->ReplaceData(idx_srcdata_begin, b->byteLength - idx_srcdata_begin, bs.GetBuffer(), bs.GetSize()); + // + // Add information about extension to mesh. + // + // Create extension structure. + Mesh::SCompression_Open3DGC* ext = new Mesh::SCompression_Open3DGC; - ///TODO: replace data in buffer + // Fill it. + ext->BufferView = p.indices->bufferView->id; + ext->Offset = idx_srcdata_begin; + ext->Count = b->byteLength - idx_srcdata_begin; + ext->IndicesCount = comp_o3dgc_ifs.GetNCoordIndex(); + ext->VerticesCount = comp_o3dgc_ifs.GetNCoord(); + // And assign to mesh. + m->Extension.push_back(ext); }// if(comp_allow) }// for (unsigned int i = 0; i < mScene->mNumMeshes; ++i) {