Comments (6)
Adding solution just in case someone will land here form Google:
// The glTF SDK is decoupled from all file I/O by the IStreamWriter (and IStreamReader)
// interface(s) and the C++ stream-based I/O library. This allows the glTF SDK to be used in
// sandboxed environments, such as WebAssembly modules and UWP apps, where any file I/O code
// must be platform or use-case specific.
class StreamWriter : public Microsoft::glTF::IStreamWriter
{
public:
// Resolves the relative URIs of any external resources declared in the glTF manifest
StreamWriter()
: m_streams()
{
}
//{
// auto stream = std::make_shared<std::ofstream>(filename, std::ios_base::binary);
// return stream;
//}
std::shared_ptr<std::ostream> GetOutputStream(const std::string& uri) const override
{
return GetStream(true);
}
std::shared_ptr<std::istream> getReferenceToOutputStream() const {
return GetStream(false);
}
private:
std::shared_ptr<std::iostream> GetStream(const bool getNewStream) const
{
if (getNewStream) {
m_streams["0"] = std::make_shared<std::stringstream>();
}
return m_streams["0"];
}
mutable std::unordered_map<std::string, std::shared_ptr<std::stringstream>> m_streams;
};
And the function for save. need to remove one of std::moves...
static void writeToGlbFile(const std::string &fileName, const std::vector<Point3f>& points, const std::vector<Vec3f>& normals, const std::vector<int>& indices, const Vec3b &color, std::shared_ptr<std::istream> & stream)
{
// Pass the absolute path, without the filename, to the stream writer
auto streamWriter = std::make_shared<StreamWriter>();
std::unique_ptr< Microsoft::glTF::ResourceWriter> resourceWriter;
// create a GLBResourceWriter. This class derives
// from GLTFResourceWriter and adds support for writing manifests to a GLB container's
// JSON chunk and resource data to the binary chunk.
resourceWriter = std::make_unique< Microsoft::glTF::GLBResourceWriter>(streamWriter);
// The Document instance represents the glTF JSON manifest
Microsoft::glTF::Document document;
std::string accessorIdIndices;
std::string accessorIdPositions;
std::string accessorIdNormals;
// Use the BufferBuilder helper class to simplify the process of
// constructing valid glTF Buffer, BufferView and Accessor entities
Microsoft::glTF::BufferBuilder bufferBuilder(std::move(resourceWriter));
Microsoft::glTF::Color4 glbColor((float)color[0] / 255.0f, (float)color[1] / 255.0f, (float)color[2] / 255.0f, 1.0f);
CreateTriangleResources(document, bufferBuilder, accessorIdIndices, accessorIdPositions, accessorIdNormals, points, normals, indices);
CreateTriangleEntities(document, accessorIdIndices, accessorIdPositions, accessorIdNormals, glbColor);
std::string manifest;
// Serialize the glTF Document into a JSON manifest
manifest = Serialize(document, Microsoft::glTF::SerializeFlags::Pretty);
auto glbResourceWriter = dynamic_cast<Microsoft::glTF::GLBResourceWriter*>(&bufferBuilder.GetResourceWriter());
glbResourceWriter->Flush(manifest, fileName); // A GLB container isn't created until the GLBResourceWriter::Flush member function is called
stream = streamWriter->getReferenceToOutputStream();
}```
from gltf-sdk.
The serialize sample is a better example of how to implement a simple stream writer. The gltf/glb resource writers construct an LRU stream cache by default so there is no need to retain a reference to all the streams created by the writer like the test does (I think the unit test @bghgary linked to predates the stream caching functionality).
from gltf-sdk.
Sorry, I pointed you to the sample code without fully taking into account what you are trying to achieve!
The IStreamWriter interface has caused a fair bit of confusion and many times it's been asked why there isn't a simple and straightforward way to write to a file (or in your case a stream). This part of the SDK is relatively complex because the glTF spec provides different ways to store buffer data (data uri, external buffer files, glb blob etc.) and the SDK has to support all of them. For example, even when creating a glb there will be multiple output streams involved if you write to multiple buffers.
If you can ensure that any glb you create only contains the default buffer then you can do as @bghgary suggested and store a pointer to the first (only?) stream created by the stream writer and access it after flushing the resource writer. Alternatively, you could implement a custom stream cache that makes the streams stored by the resource writer publicly accessible.
Finally, the uri passed to the stream writer doesn't have to be a file name - for your scenario it would only be used to uniquely identify a particular stream.
from gltf-sdk.
I'm not sure what your code looks like, but you can do something like this:
glTF-SDK/GLTFSDK.Test/Source/TestUtils.h
Lines 31 to 59 in dfce430
Create your own writer and then do something like this:
glTF-SDK/GLTFSDK.Test/Source/GLBResourceWriterTests.cpp
Lines 21 to 39 in dfce430
from gltf-sdk.
Thanks to all for explanations, but if I am checking "The serialize sample", the only relevant part as I understand is:
auto& gltfResourceWriter = bufferBuilder.GetResourceWriter();
if (auto glbResourceWriter = dynamic_cast<GLBResourceWriter*>(&gltfResourceWriter))
{
glbResourceWriter->Flush(manifest, pathFile.u8string()); // A GLB container isn't created until the GLBResourceWriter::Flush member function is called
}
else
{
gltfResourceWriter.WriteExternal(pathFile.u8string(), manifest); // Binary resources have already been written, just need to write the manifest
}
And here pathFile.u8string() is still file, while I am looking for stream.
from gltf-sdk.
@chriche-ms & @bghgary thanks for explanations, I have used the way suggested by you and used @bghgary example and I do see when I do flush() my string stream is used.
But I got stuck with C++ features, I want to get access to the stream but I don't understand how: the original object is std:moved twice, so when I want to get pointer to the string stream the streamWriter object is empty.
Here is part of my code:
The StreamWriter class:
class StreamWriter : public Microsoft::glTF::IStreamWriter, Microsoft::glTF::IStreamReader
{
public:
// Resolves the relative URIs of any external resources declared in the glTF manifest
StreamWriter()
: m_streams()
{
}
//{
// auto stream = std::make_shared<std::ofstream>(filename, std::ios_base::binary);
// return stream;
//}
std::shared_ptr<std::ostream> GetOutputStream(const std::string& uri) const override
{
return GetStream(uri);
}
std::shared_ptr<std::istream> GetInputStream(const std::string& uri) const override {
return GetStream(uri);
}
private:
std::shared_ptr<std::iostream> GetStream(const std::string& uri) const
{
if (m_streams.find(uri) == m_streams.end()) {
m_streams[uri] = std::make_shared<std::stringstream>();
}
return m_streams[uri];
}
mutable std::unordered_map<std::string, std::shared_ptr<std::stringstream>> m_streams;
//std::shared_ptr<std::stringstream> binFile;
std::string m_pathBase;
};
And the actual save function:
static void writeToGlbFile(const std::string &fileName, const std::vector<Point3f>& points, const std::vector<Vec3f>& normals, const std::vector<int>& indices, const Vec3b &color, std::shared_ptr<std::istream> & stream)
{
// Pass the absolute path, without the filename, to the stream writer
auto streamWriter = std::make_unique<StreamWriter>();
std::unique_ptr< Microsoft::glTF::ResourceWriter> resourceWriter;
// create a GLBResourceWriter. This class derives
// from GLTFResourceWriter and adds support for writing manifests to a GLB container's
// JSON chunk and resource data to the binary chunk.
resourceWriter = std::make_unique< Microsoft::glTF::GLBResourceWriter>(std::move(streamWriter));
// The Document instance represents the glTF JSON manifest
Microsoft::glTF::Document document;
std::string accessorIdIndices;
std::string accessorIdPositions;
std::string accessorIdNormals;
// Use the BufferBuilder helper class to simplify the process of
// constructing valid glTF Buffer, BufferView and Accessor entities
Microsoft::glTF::BufferBuilder bufferBuilder(std::move(resourceWriter));
Microsoft::glTF::Color4 glbColor((float)color[0] / 255.0f, (float)color[1] / 255.0f, (float)color[2] / 255.0f, 1.0f);
CreateTriangleResources(document, bufferBuilder, accessorIdIndices, accessorIdPositions, accessorIdNormals, points, normals, indices);
CreateTriangleEntities(document, accessorIdIndices, accessorIdPositions, accessorIdNormals, glbColor);
std::string manifest;
// Serialize the glTF Document into a JSON manifest
manifest = Serialize(document, Microsoft::glTF::SerializeFlags::Pretty);
auto glbResourceWriter = dynamic_cast<Microsoft::glTF::GLBResourceWriter*>(&bufferBuilder.GetResourceWriter());
glbResourceWriter->Flush(manifest, fileName); // A GLB container isn't created until the GLBResourceWriter::Flush member function is called
auto streamWriterNew = dynamic_cast<StreamWriter*>(&bufferBuilder.GetResourceWriter());
stream = streamWriterNew->GetInputStream(fileName);
}
So, what I don't understand is how to get access to GetInputStream() and get back pointer to string stream.
The original object is moved and empty now, and bufferBuilder or glbResourceWriter do not have access to this.
from gltf-sdk.
Related Issues (20)
- GLB 3D model fails to import correctly HOT 1
- Is it possible to write not interleaved buffers? HOT 1
- Exceptions necessary ? HOT 2
- Can it export quads into gltf ? HOT 2
- How to export data as ascii text in GLTF? HOT 1
- ByteOffset should be a multiple of 4 in Javascript HOT 3
- Changes - suggestion for the Serialization example HOT 4
- Procedure to upgrade for the support many Vertex Colors ? HOT 2
- Example for animation? HOT 3
- Buffer error when reaching 2GB (2.147.869.560) byteLength HOT 18
- about draco HOT 2
- clang/LLVM for Windows build failures HOT 3
- compile error, SchemaValidation HOT 1
- This repo is missing important files HOT 1
- GenerateSchemaJsonHeader.ps1 fails because D:\source\GLTFSDK does not exist
- Point size and Line width HOT 1
- googletest, POWERSHELL_PATH-NOTFOUND and other errors on Linux HOT 1
- Request for GLTF-SDK Support on Visual Studio 2022 HOT 2
- Add `ResourceWriter::Write` overload with a buffer id parameter instead of a buffer view
- Can a single vertex have multiple UV coordinates depending on how many faces it belongs to? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gltf-sdk.