This example is part of OpenSceneGraph cross-platform examples.
In this example we embed box.osgt
model (a binary resource) into application.
Embedding binary resources unifies data loading for platforms with different file
system requirements and constraints like desktop, Android, iOS, and web.
xxd
can represent any binary file as unsigned char[]
, a C array that you
can use as is in C/C++ applications.
Generate box.osgt.h
C header from box.osgt
model by running the following command:
xxd -i box.osgt > box.osgt.h
Generated box.osgt.h
file looks like this:
unsigned char box_osgt[] = {
0x23, 0x41, 0x73, 0x63, 0x69, 0x69, 0x20, 0x53, 0x63, 0x65, 0x6e, 0x65,
0x0a, 0x23, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x39, 0x32,
0x0a, 0x23, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20,
0x6f, 0x73, 0x67, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x30, 0x2e,
0x31, 0x33, 0x2e, 0x30, 0x0a, 0x0a, 0x6f, 0x73, 0x67, 0x3a, 0x3a, 0x47,
- - - - trimmed for brevity - - - -
0x20, 0x20, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x30, 0x2e,
0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30,
0x30, 0x20, 0x31, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a,
0x20, 0x20, 0x7d, 0x0a, 0x7d, 0x0a
};
unsigned int box_osgt_len = 32058;
As you can see, xxd
created two variables:
unsigned char box_osgt[]
, an array of raw bytesunsigned int box_osgt_len
, size of the array
Both variables start with box_osgt
, which is derived from box.osgt
filename.
First, reference box.osgt.h
(source code):
#include "box.osgt.h"
Second, make sure CMakeLists.txt
includes the directory with box.osgt.h
(source code):
INCLUDE_DIRECTORIES(${OSGCPE_DIR}/data)
In order to let OpenSceneGraph access the data from a C array, we have to
represent it as std::istream
.
To simplify resource management in code, we introduce two classes:
- Resource to hold generated contents
- ResourceStreamBuffer to provide C array contents as
std::streambuf
, which can be converted tostd::istream
Note: ResourceStreamBuffer::seekoff()
implementation is crucial for
OpenSceneGraph plugins to correctly load resources.
First, create Resource
instance to work with (source code):
resource::Resource box("models", "box.osgt", box_osgt, box_osgt_len);
Second, load the model. To load the model from std::istream
, we:
- find a reader that is capable of reading the model (such a reader can be located by providing file extension)
- let the reader create a node with the model
Here's how the crucial part of the implementation looks like (source code):
- - - -
auto reader = osgDB::Registry::instance()->getReaderWriterForExtension(extension);
if (reader)
{
ResourceStreamBuffer buf(box);
std::istream in(&buf);
auto result = reader->readNode(in, 0);
if (result.success())
{
node = result.getNode();
}
- - - -
Third, reference plugin capable of loading .osgt
(source code):
USE_OSGPLUGIN(osg2)
USE_SERIALIZER_WRAPPER_LIBRARY(osg)
Here's a web build of the example.