* updates uservalue serialization (avoid creating multie UserDataContainer for a same object) * removes vec4ubarray specific serialization (serialization should not enforce the previous color transformation)
719 lines
26 KiB
C++
719 lines
26 KiB
C++
/* -*-c++-*- OpenSceneGraph - Copyright (C) 2012 Cedric Pinson */
|
|
#ifndef WRITE_VISITOR_H
|
|
#define WRITE_VISITOR_H
|
|
|
|
#include <osg/Image>
|
|
#include <osg/Notify>
|
|
#include <osg/Geode>
|
|
#include <osg/Geometry>
|
|
#include <osg/GL>
|
|
#include <osg/Version>
|
|
#include <osg/Endian>
|
|
#include <osg/Projection>
|
|
#include <osg/MatrixTransform>
|
|
#include <osg/PagedLOD>
|
|
#include <osg/PositionAttitudeTransform>
|
|
#include <osgAnimation/BasicAnimationManager>
|
|
#include <osgAnimation/Skeleton>
|
|
#include <osg/LightSource>
|
|
#include <osg/CullFace>
|
|
#include <osg/Material>
|
|
#include <osg/BlendColor>
|
|
#include <osg/BlendFunc>
|
|
#include <osg/ValueObject>
|
|
#include <osg/Array>
|
|
#include <osgDB/FileNameUtils>
|
|
|
|
#include <osgAnimation/RigGeometry>
|
|
#include <osgAnimation/MorphGeometry>
|
|
#include <osgAnimation/Bone>
|
|
#include <osgAnimation/UpdateBone>
|
|
|
|
#include <osgSim/ShapeAttribute>
|
|
|
|
#include <osgText/Text>
|
|
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <string>
|
|
#include <algorithm>
|
|
#include <sstream>
|
|
|
|
#include "JSON_Objects"
|
|
#include "Animation"
|
|
#include "json_stream"
|
|
|
|
|
|
#define WRITER_VERSION 9
|
|
|
|
|
|
class WriteVisitor;
|
|
|
|
osg::Array* getTangentSpaceArray(osg::Geometry& geometry);
|
|
void getStringifiedUserValue(osg::Object* o, std::string& name, std::string& value);
|
|
template<typename T>
|
|
bool getStringifiedUserValue(osg::Object* o, std::string& name, std::string& value);
|
|
|
|
|
|
class WriteVisitor : public osg::NodeVisitor
|
|
{
|
|
public:
|
|
typedef std::vector<osg::ref_ptr<osg::StateSet> > StateSetStack;
|
|
typedef std::pair<std::string, std::string> KeyValue;
|
|
typedef std::map<osg::ref_ptr<osg::Object>, osg::ref_ptr<JSONObject> > OsgObjectToJSONObject;
|
|
|
|
OsgObjectToJSONObject _maps;
|
|
std::vector<osg::ref_ptr<JSONObject> > _parents;
|
|
osg::ref_ptr<JSONObject> _root;
|
|
StateSetStack _stateset;
|
|
std::string _baseName;
|
|
std::string _baseLodURL;
|
|
bool _useExternalBinaryArray;
|
|
bool _mergeAllBinaryFiles;
|
|
bool _inlineImages;
|
|
int _maxTextureDimension;
|
|
bool _varint;
|
|
std::map<KeyValue, std::string> _specificBuffers;
|
|
std::map<std::string, std::ofstream*> _buffers;
|
|
|
|
JSONObject* getJSON(osg::Object* object) const {
|
|
OsgObjectToJSONObject::const_iterator lookup = _maps.find(object);
|
|
if(lookup != _maps.end()) {
|
|
return lookup->second->getShadowObject();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void setJSON(osg::Object* object, JSONObject* json) {
|
|
if(json) {
|
|
_maps[object] = json;
|
|
}
|
|
}
|
|
|
|
std::ofstream& getBufferFile(const std::string& name) {
|
|
if(_buffers.find(name) == _buffers.end()) {
|
|
_buffers[name] = new std::ofstream(name.c_str(), std::ios::binary);
|
|
}
|
|
return *_buffers[name];
|
|
}
|
|
|
|
WriteVisitor() :
|
|
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
|
_useExternalBinaryArray(false),
|
|
_mergeAllBinaryFiles(false),
|
|
_inlineImages(false),
|
|
_maxTextureDimension(0),
|
|
_varint(false)
|
|
{}
|
|
|
|
~WriteVisitor() {
|
|
for(std::map<std::string, std::ofstream*>::iterator buffer = _buffers.begin() ;
|
|
buffer != _buffers.end() ; ++ buffer) {
|
|
delete buffer->second;
|
|
}
|
|
}
|
|
|
|
std::string getBinaryFilename(KeyValue flag=KeyValue()) const {
|
|
std::string suffix,
|
|
prefix(_baseName);
|
|
std::map<KeyValue, std::string>::const_iterator it_buffer = _specificBuffers.find(flag);
|
|
if(it_buffer != _specificBuffers.end()) {
|
|
if(osgDB::isAbsolutePath(it_buffer->second)) {
|
|
// if output is explicit, do not change it
|
|
return it_buffer->second;
|
|
}
|
|
else {
|
|
suffix = "_" + it_buffer->second;
|
|
}
|
|
}
|
|
return prefix + suffix + ".bin";
|
|
}
|
|
|
|
void closeBuffers() {
|
|
for(std::map<std::string, std::ofstream*>::iterator buffer = _buffers.begin() ;
|
|
buffer != _buffers.end() ; ++ buffer) {
|
|
buffer->second->close();
|
|
}
|
|
}
|
|
|
|
unsigned int getBuffersSize() const {
|
|
unsigned int size = 0;
|
|
for(std::map<std::string, std::ofstream*>::const_iterator buffer = _buffers.begin() ;
|
|
buffer != _buffers.end() ; ++ buffer) {
|
|
size += buffer->second->tellp();
|
|
}
|
|
return size;
|
|
}
|
|
|
|
void write(json_stream& str) {
|
|
osg::ref_ptr<JSONObject> o = new JSONObject();
|
|
o->getMaps()["Version"] = new JSONValue<int>(WRITER_VERSION);
|
|
o->getMaps()["Generator"] = new JSONValue<std::string>("OpenSceneGraph " + std::string(osgGetVersion()) );
|
|
o->getMaps()["osg.Node"] = _root.get();
|
|
o->write(str, *this);
|
|
if (_mergeAllBinaryFiles) {
|
|
closeBuffers();
|
|
unsigned int size = getBuffersSize();
|
|
osg::notify(osg::NOTICE) << "Use a merged binary file ";
|
|
if (size/1024.0 < 1.0) {
|
|
osg::notify(osg::NOTICE) << size << " bytes" << std::endl;
|
|
} else if (size/(1024.0*1024.0) < 1.0) {
|
|
osg::notify(osg::NOTICE) << size/1024.0 << " kb" << std::endl;
|
|
} else {
|
|
osg::notify(osg::NOTICE) << size/(1024.0*1024.0) << " mb" << std::endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
void error() {
|
|
throw "Error occur";
|
|
}
|
|
|
|
void setBufferName(JSONObject *json, osg::Object* parent=0, osg::Object* object=0) const {
|
|
if(!_mergeAllBinaryFiles || _specificBuffers.empty())
|
|
return;
|
|
|
|
// try to fetch buffer name for object
|
|
std::string bufferName = getBufferName(object);
|
|
std::string defaultBufferName = getBinaryFilename();
|
|
std::string jsonBufferName = json->getBufferName();
|
|
|
|
if(bufferName == defaultBufferName) {
|
|
// in case none is set, fallback to parent buffer name
|
|
bufferName = getBufferName(parent);
|
|
}
|
|
// if the buffer is shared we will always favor dumping it in the default
|
|
// buffer and otherwise we keep the first buffer name set.
|
|
if(!jsonBufferName.empty()) {
|
|
if(jsonBufferName != defaultBufferName && bufferName == defaultBufferName) {
|
|
json->setBufferName(defaultBufferName);
|
|
}
|
|
}
|
|
else {
|
|
json->setBufferName(bufferName);
|
|
}
|
|
}
|
|
|
|
std::string getBufferName(osg::Object* object) const {
|
|
KeyValue flag;
|
|
if(object && object->getUserDataContainer() && object->getUserDataContainer()->getNumUserObjects()) {
|
|
for(std::map<KeyValue, std::string>::const_iterator it_flag = _specificBuffers.begin() ; it_flag != _specificBuffers.end() ; ++ it_flag) {
|
|
std::string key = it_flag->first.first,
|
|
value = it_flag->first.second;
|
|
|
|
// only looking for existence of user value
|
|
if(value.empty()) {
|
|
if(object->getUserDataContainer()->getUserObject(key)) {
|
|
flag = it_flag->first;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
std::set<std::string> uservalues;
|
|
|
|
bool boolValue;
|
|
int numberValue;
|
|
unsigned int uNumberValue;
|
|
std::string stringValue;
|
|
|
|
if(object->getUserValue(key, boolValue)) {
|
|
std::ostringstream oss;
|
|
if(boolValue) {
|
|
uservalues.insert("1");
|
|
uservalues.insert("true");
|
|
}
|
|
else {
|
|
uservalues.insert("0");
|
|
uservalues.insert("false");
|
|
}
|
|
}
|
|
|
|
if(object->getUserValue(key, numberValue)) {
|
|
std::ostringstream oss;
|
|
oss << numberValue;
|
|
uservalues.insert(oss.str());
|
|
}
|
|
|
|
if(object->getUserValue(key, uNumberValue)) {
|
|
std::ostringstream oss;
|
|
oss << uNumberValue;
|
|
uservalues.insert(oss.str());
|
|
}
|
|
|
|
if(object->getUserValue(key, stringValue)) {
|
|
uservalues.insert(stringValue);
|
|
}
|
|
|
|
if(uservalues.find(value) != uservalues.end()) {
|
|
flag = it_flag->first;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return getBinaryFilename(flag);
|
|
}
|
|
|
|
void translateObject(JSONObject* json, osg::Object* osg);
|
|
JSONObject* createJSONOsgSimUserData(osgSim::ShapeAttributeList*);
|
|
JSONObject* createJSONUserDataContainer(osg::UserDataContainer*);
|
|
|
|
JSONObject* createJSONPagedLOD(osg::PagedLOD* plod);
|
|
JSONObject* createJSONStateSet(osg::StateSet* ss);
|
|
JSONObject* createJSONTexture(osg::Texture* sa);
|
|
JSONObject* createJSONText(osgText::Text* text);
|
|
JSONObject* createJSONMaterial(osg::Material* sa);
|
|
JSONObject* createJSONLight(osg::Light* sa);
|
|
JSONObject* createJSONCullFace(osg::CullFace* sa);
|
|
JSONObject* createJSONBlendColor(osg::BlendColor* sa);
|
|
JSONObject* createJSONBlendFunc(osg::BlendFunc* sa);
|
|
|
|
JSONObject* createJSONBufferArray(osg::Array* array, osg::Object* parent = 0);
|
|
JSONObject* createJSONDrawElements(osg::DrawArrays* drawArray, osg::Object* parent = 0);
|
|
|
|
JSONObject* createJSONDrawElementsUInt(osg::DrawElementsUInt* de, osg::Object* parent = 0);
|
|
JSONObject* createJSONDrawElementsUShort(osg::DrawElementsUShort* de, osg::Object* parent = 0);
|
|
JSONObject* createJSONDrawElementsUByte(osg::DrawElementsUByte* de, osg::Object* parent = 0);
|
|
|
|
JSONObject* createJSONDrawArray(osg::DrawArrays* drawArray, osg::Object* parent = 0);
|
|
JSONObject* createJSONDrawArrayLengths(osg::DrawArrayLengths* drawArray, osg::Object* parent = 0);
|
|
|
|
JSONObject* createJSONGeometry(osg::Geometry* geometry, osg::Object* parent=0);
|
|
JSONObject* createJSONRigGeometry(osgAnimation::RigGeometry* rigGeometry);
|
|
JSONObject* createJSONMorphGeometry(osgAnimation::MorphGeometry* morphGeom, osg::Object* parent=0);
|
|
|
|
JSONObject* getParent() {
|
|
if (_parents.empty()) {
|
|
_root = new JSONObject;
|
|
_parents.push_back(_root.get());
|
|
}
|
|
return _parents.back().get();
|
|
}
|
|
|
|
void initJsonObjectFromNode(osg::Node& node, JSONObject& json) {
|
|
translateObject(&json, &node);
|
|
}
|
|
|
|
|
|
void createJSONStateSet(JSONObject* json, osg::StateSet* ss) {
|
|
JSONObject* json_stateset = createJSONStateSet(ss);
|
|
if (json_stateset) {
|
|
JSONObject* obj = new JSONObject;
|
|
obj->getMaps()["osg.StateSet"] = json_stateset;
|
|
json->getMaps()["StateSet"] = obj;
|
|
|
|
}
|
|
}
|
|
void createJSONStateSet(osg::Node& node, JSONObject* json) {
|
|
if (node.getStateSet()) {
|
|
createJSONStateSet(json, node.getStateSet());
|
|
}
|
|
}
|
|
|
|
void applyCallback(osg::Node& node, JSONObject* in_json) {
|
|
osg::ref_ptr<JSONArray> updateCallbacks = new JSONArray;
|
|
osg::ref_ptr<osg::Callback> nc = node.getUpdateCallback();
|
|
while (nc) {
|
|
if(osgAnimation::BasicAnimationManager* am = dynamic_cast<osgAnimation::BasicAnimationManager*>(nc.get())) {
|
|
osg::ref_ptr<JSONArray> array = new JSONArray;
|
|
osg::ref_ptr<JSONObject> bam = new JSONObject;
|
|
translateObject(bam.get(), am);
|
|
bam->getMaps()["Animations"] = array;
|
|
|
|
osg::ref_ptr<JSONObject> nodeCallbackObject = new JSONObject;
|
|
nodeCallbackObject->getMaps()["osgAnimation.BasicAnimationManager"] = bam;
|
|
updateCallbacks->getArray().push_back(nodeCallbackObject);
|
|
|
|
for ( unsigned int i = 0; i < am->getAnimationList().size(); i++) {
|
|
osgAnimation::Animation* animation = am->getAnimationList()[i].get();
|
|
osg::ref_ptr<JSONObject> jsonAnim = createJSONAnimation(animation, this);
|
|
if (jsonAnim) {
|
|
translateObject(jsonAnim.get(), animation);
|
|
osg::ref_ptr<JSONObject> obj = new JSONObject;
|
|
obj->getMaps()["osgAnimation.Animation"] = jsonAnim;
|
|
array->getArray().push_back(obj);
|
|
}
|
|
}
|
|
}
|
|
else if(osgAnimation::UpdateBone* upBone = dynamic_cast<osgAnimation::UpdateBone*>(nc.get())) {
|
|
osg::ref_ptr<JSONObject> jsonCallback = createJSONUpdateMatrixTransform(*upBone, this);
|
|
if (jsonCallback.valid()) {
|
|
osg::ref_ptr<JSONObject> jsonObject = new JSONObject;
|
|
jsonObject->getMaps()["osgAnimation.UpdateBone"] = jsonCallback;
|
|
updateCallbacks->getArray().push_back(jsonObject);
|
|
}
|
|
}
|
|
else if(osgAnimation::UpdateMatrixTransform* updateMT = dynamic_cast<osgAnimation::UpdateMatrixTransform*>(nc.get())) {
|
|
osg::ref_ptr<JSONObject> jsonCallback = createJSONUpdateMatrixTransform(*updateMT, this);
|
|
if (jsonCallback.valid()) {
|
|
osg::ref_ptr<JSONObject> jsonObject = new JSONObject;
|
|
jsonObject->getMaps()["osgAnimation.UpdateMatrixTransform"] = jsonCallback;
|
|
updateCallbacks->getArray().push_back(jsonObject);
|
|
}
|
|
}
|
|
else if(dynamic_cast<osgAnimation::Skeleton::UpdateSkeleton*>(nc.get())) {
|
|
osg::ref_ptr<JSONObject> json = new JSONNode;
|
|
osg::ref_ptr<JSONObject> jsonObject = new JSONObject;
|
|
_maps[&node] = json;
|
|
jsonObject->getMaps()["osgAnimation.UpdateSkeleton"] = json;
|
|
updateCallbacks->getArray().push_back(jsonObject);
|
|
}
|
|
else if(osgAnimation::UpdateMorph* updateMorph = dynamic_cast<osgAnimation::UpdateMorph*>(nc.get())) {
|
|
osg::ref_ptr<JSONObject> json = new JSONNode;
|
|
osg::ref_ptr<JSONObject> jsonObject = new JSONObject;
|
|
osg::ref_ptr<JSONObject> jsonTargetName = new JSONObject;
|
|
json->getMaps()["Name"] = new JSONValue<std::string>(updateMorph->getName());
|
|
|
|
unsigned int numTarget = updateMorph->getNumTarget();
|
|
for(unsigned int i = 0; i < numTarget; ++i) {
|
|
std::ostringstream oss;
|
|
oss << i;
|
|
jsonTargetName->getMaps()[ oss.str() ] = new JSONValue<std::string>(updateMorph->getTargetName(i));
|
|
}
|
|
json->getMaps()["TargetMap"] = jsonTargetName;
|
|
json->getMaps()["TargetMap"] = jsonTargetName;
|
|
|
|
_maps[&node] = json;
|
|
jsonObject->getMaps()["osgAnimation.UpdateMorph"] = json;
|
|
updateCallbacks->getArray().push_back(jsonObject);
|
|
}
|
|
nc = nc->getNestedCallback();
|
|
}
|
|
|
|
if (!updateCallbacks->getArray().empty()) {
|
|
in_json->getMaps()["UpdateCallbacks"] = updateCallbacks;
|
|
}
|
|
}
|
|
|
|
void apply(osg::Drawable& drawable) {
|
|
if(osgAnimation::RigGeometry * rigGeometry = dynamic_cast<osgAnimation::RigGeometry*>(&drawable)) {
|
|
JSONObject* json = createJSONRigGeometry(rigGeometry);
|
|
translateObject(json, rigGeometry);
|
|
JSONObject* parent = getParent();
|
|
parent->addChild("osgAnimation.RigGeometry", json);
|
|
}
|
|
else if(osgAnimation::MorphGeometry * morphGeometry = dynamic_cast<osgAnimation::MorphGeometry*>(&drawable)) {
|
|
JSONObject* json = createJSONMorphGeometry(morphGeometry);
|
|
JSONObject* parent = getParent();
|
|
parent->addChild("osgAnimation.MorphGeometry", json);
|
|
}
|
|
else if(osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(&drawable)) {
|
|
JSONObject* json = createJSONGeometry(geometry);
|
|
JSONObject* parent = getParent();
|
|
parent->addChild("osg.Geometry", json);
|
|
}
|
|
else if(osgText::Text* text = dynamic_cast<osgText::Text*>(&drawable)) {
|
|
JSONObject* json = createJSONText(text);
|
|
JSONObject* parent = getParent();
|
|
parent->addChild("osgText.Text", json);
|
|
}
|
|
}
|
|
|
|
void apply(osg::Geode& node) {
|
|
|
|
JSONObject* parent = getParent();
|
|
if (_maps.find(&node) != _maps.end()) {
|
|
parent->addChild("osg.Node", _maps[&node]->getShadowObject());
|
|
return;
|
|
}
|
|
|
|
osg::ref_ptr<JSONObject> json = new JSONNode;
|
|
_maps[&node] = json;
|
|
|
|
applyCallback(node, json.get());
|
|
createJSONStateSet(node, json.get());
|
|
|
|
parent->addChild("osg.Node", json.get());
|
|
initJsonObjectFromNode(node, *json);
|
|
_parents.push_back(json);
|
|
for (unsigned int i = 0; i < node.getNumDrawables(); ++i) {
|
|
if (node.getDrawable(i))
|
|
apply(*node.getDrawable(i));
|
|
}
|
|
_parents.pop_back();
|
|
}
|
|
|
|
void apply(osg::Group& node) {
|
|
|
|
JSONObject* parent = getParent();
|
|
if (_maps.find(&node) != _maps.end()) {
|
|
parent->addChild("osg.Node", _maps[&node]->getShadowObject());
|
|
return;
|
|
}
|
|
|
|
osg::ref_ptr<JSONObject> json = new JSONNode;
|
|
_maps[&node] = json;
|
|
parent->addChild("osg.Node", json.get());
|
|
|
|
applyCallback(node, json.get());
|
|
createJSONStateSet(node, json.get());
|
|
|
|
initJsonObjectFromNode(node, *json);
|
|
|
|
_parents.push_back(json);
|
|
traverse(node);
|
|
_parents.pop_back();
|
|
}
|
|
|
|
void apply(osg::PagedLOD& node)
|
|
{
|
|
JSONObject* parent = getParent();
|
|
if (_maps.find(&node) != _maps.end()) {
|
|
parent->addChild("osg.PagedLOD", _maps[&node]->getShadowObject());
|
|
return;
|
|
}
|
|
|
|
osg::ref_ptr<JSONObject> json = createJSONPagedLOD(&node);
|
|
json->addUniqueID();
|
|
_maps[&node] = json;
|
|
parent->addChild("osg.PagedLOD", json.get());
|
|
|
|
|
|
applyCallback(node, json.get());
|
|
|
|
|
|
createJSONStateSet(node, json.get());
|
|
|
|
initJsonObjectFromNode(node, *json);
|
|
_parents.push_back(json);
|
|
traverse(node);
|
|
_parents.pop_back();
|
|
}
|
|
|
|
void apply(osg::LightSource& node) {
|
|
|
|
JSONObject* parent = getParent();
|
|
if (_maps.find(&node) != _maps.end()) {
|
|
parent->addChild("osg.LightSource", _maps[&node]->getShadowObject());
|
|
return;
|
|
}
|
|
|
|
osg::ref_ptr<JSONObject> json = new JSONNode;
|
|
_maps[&node] = json;
|
|
|
|
applyCallback(node, json.get());
|
|
createJSONStateSet(node, json.get());
|
|
|
|
parent->addChild("osg.LightSource", json.get());
|
|
|
|
initJsonObjectFromNode(node, *json);
|
|
|
|
if (node.getLight()) {
|
|
JSONObject* obj = new JSONObject;
|
|
obj->getMaps()["osg.Light"] = createJSONLight(node.getLight());
|
|
json->getMaps()["Light"] = obj;
|
|
}
|
|
|
|
_parents.push_back(json);
|
|
traverse(node);
|
|
_parents.pop_back();
|
|
}
|
|
|
|
void apply(osg::Projection& node) {
|
|
JSONObject* parent = getParent();
|
|
if (_maps.find(&node) != _maps.end()) {
|
|
parent->addChild("osg.Projection", _maps[&node]->getShadowObject());
|
|
return;
|
|
}
|
|
|
|
osg::ref_ptr<JSONObject> json = new JSONNode;
|
|
_maps[&node] = json;
|
|
|
|
applyCallback(node, json.get());
|
|
createJSONStateSet(node, json.get());
|
|
|
|
parent->addChild("osg.Projection", json.get());
|
|
|
|
initJsonObjectFromNode(node, *json);
|
|
json->getMaps()["Matrix"] = new JSONMatrix(node.getMatrix());
|
|
_parents.push_back(json);
|
|
traverse(node);
|
|
_parents.pop_back();
|
|
}
|
|
|
|
void applyCommonMatrixTransform(const char * jsClassName, osg::ref_ptr<JSONObject> &json, osg::MatrixTransform &node, JSONObject* parent) {
|
|
json->addUniqueID();
|
|
_maps[&node] = json;
|
|
|
|
applyCallback(node, json.get());
|
|
createJSONStateSet(node, json.get());
|
|
|
|
parent->addChild(jsClassName, json.get());
|
|
|
|
initJsonObjectFromNode(node, *json);
|
|
json->getMaps()["Matrix"] = new JSONMatrix(node.getMatrix());
|
|
}
|
|
|
|
void apply(osgText::Text& node) {
|
|
JSONObject* parent = getParent();
|
|
if (_maps.find(&node) != _maps.end()) {
|
|
parent->addChild("osgText.Text", _maps[&node]->getShadowObject());
|
|
return;
|
|
}
|
|
|
|
osg::ref_ptr<JSONObject> json = createJSONText(&node);
|
|
json->addUniqueID();
|
|
_maps[&node] = json.get();
|
|
parent->addChild("osgText.Text", json.get());
|
|
applyCallback(node, json.get());
|
|
createJSONStateSet(node, json.get());
|
|
initJsonObjectFromNode(node, *json);
|
|
_parents.push_back(json);
|
|
traverse(node);
|
|
_parents.pop_back();
|
|
}
|
|
|
|
void apply(osg::MatrixTransform& node) {
|
|
if (dynamic_cast<osgAnimation::Skeleton*>(&node)) {
|
|
apply(static_cast<osgAnimation::Skeleton&>(node));
|
|
return;
|
|
}
|
|
if (dynamic_cast<osgAnimation::Bone*>(&node)) {
|
|
apply(static_cast<osgAnimation::Bone&>(node));
|
|
return;
|
|
}
|
|
|
|
JSONObject* parent = getParent();
|
|
if (_maps.find(&node) != _maps.end()) {
|
|
parent->addChild("osg.MatrixTransform", _maps[&node]->getShadowObject());
|
|
return;
|
|
}
|
|
osg::ref_ptr<JSONObject> json = new JSONNode;
|
|
_maps[&node] = json;
|
|
|
|
applyCallback(node, json.get());
|
|
createJSONStateSet(node, json.get());
|
|
|
|
parent->addChild("osg.MatrixTransform", json.get());
|
|
|
|
initJsonObjectFromNode(node, *json);
|
|
json->getMaps()["Matrix"] = new JSONMatrix(node.getMatrix());
|
|
|
|
_parents.push_back(json);
|
|
traverse(node);
|
|
_parents.pop_back();
|
|
|
|
}
|
|
|
|
void apply(osgAnimation::Skeleton& node) {
|
|
JSONObject* parent = getParent();
|
|
if (_maps.find(&node) != _maps.end()) {
|
|
parent->addChild("osgAnimation.Skeleton", _maps[&node]->getShadowObject());
|
|
return;
|
|
}
|
|
osg::ref_ptr<JSONObject> json = new JSONNode;
|
|
applyCommonMatrixTransform("osgAnimation.Skeleton", json, node, parent);
|
|
_parents.push_back(json);
|
|
traverse(node);
|
|
_parents.pop_back();
|
|
}
|
|
|
|
void apply(osgAnimation::Bone &node) {
|
|
JSONObject* parent = getParent();
|
|
if (_maps.find(&node) != _maps.end()) {
|
|
parent->addChild("osgAnimation.Bone", _maps[&node]->getShadowObject());
|
|
return;
|
|
}
|
|
|
|
osg::ref_ptr<JSONObject> json = new JSONNode;
|
|
|
|
osg::Vec3 min(0,0,0), max(0,0,0);
|
|
osg::ref_ptr<JSONObject> bboxData = new JSONObject;
|
|
bool hasBoundindBox = ( node.getUserValue("AABBonBone_min", min) && node.getUserValue("AABBonBone_max", max) );
|
|
|
|
if (hasBoundindBox) {
|
|
unsigned int idxmin = node.getUserDataContainer()->getUserObjectIndex("AABBonBone_min");
|
|
node.getUserDataContainer()->removeUserObject(idxmin);
|
|
unsigned int idxmax = node.getUserDataContainer()->getUserObjectIndex("AABBonBone_max");
|
|
node.getUserDataContainer()->removeUserObject(idxmax);
|
|
|
|
if(node.getUserDataContainer() && node.getUserDataContainer()->getNumUserObjects() == 0)
|
|
node.setUserDataContainer(NULL);
|
|
|
|
bboxData->getMaps()["min"] = new JSONVec3Array(min);
|
|
bboxData->getMaps()["max"] = new JSONVec3Array(max);
|
|
|
|
json->getMaps()["BoundingBox"] = bboxData;
|
|
}
|
|
|
|
json->getMaps()["InvBindMatrixInSkeletonSpace"] = new JSONMatrix(node.getInvBindMatrixInSkeletonSpace());
|
|
|
|
applyCommonMatrixTransform("osgAnimation.Bone", json, node, parent);
|
|
|
|
_parents.push_back(json);
|
|
traverse(node);
|
|
_parents.pop_back();
|
|
}
|
|
|
|
void apply(osg::PositionAttitudeTransform& node)
|
|
{
|
|
JSONObject* parent = getParent();
|
|
if (_maps.find(&node) != _maps.end()) {
|
|
parent->addChild("osg.MatrixTransform", _maps[&node]->getShadowObject());
|
|
return;
|
|
}
|
|
|
|
osg::ref_ptr<JSONObject> json = new JSONNode;
|
|
_maps[&node] = json;
|
|
|
|
applyCallback(node, json.get());
|
|
createJSONStateSet(node, json.get());
|
|
|
|
parent->addChild("osg.MatrixTransform", json.get());
|
|
|
|
initJsonObjectFromNode(node, *json);
|
|
osg::Matrix matrix = osg::Matrix::identity();
|
|
node.computeLocalToWorldMatrix(matrix,0);
|
|
json->getMaps()["Matrix"] = new JSONMatrix(matrix);
|
|
_parents.push_back(json);
|
|
traverse(node);
|
|
_parents.pop_back();
|
|
}
|
|
|
|
std::string getBaseName() const { return _baseName; }
|
|
bool getInlineImages() const { return _inlineImages; }
|
|
int getMaxTextureDimension() const { return _maxTextureDimension; }
|
|
|
|
void setBaseName(const std::string& basename) { _baseName = basename; }
|
|
void useExternalBinaryArray(bool use) { _useExternalBinaryArray = use; }
|
|
void mergeAllBinaryFiles(bool use) { _mergeAllBinaryFiles = use; }
|
|
void setInlineImages(bool use) { _inlineImages = use; }
|
|
void setVarint(bool use) { _varint = use; }
|
|
void setMaxTextureDimension(int use) { _maxTextureDimension = use; }
|
|
void addSpecificBuffer(const std::string& bufferFlag) {
|
|
if(bufferFlag.empty()) {
|
|
return;
|
|
}
|
|
|
|
std::string key, value, buffer;
|
|
size_t equal = bufferFlag.find("="),
|
|
colon = bufferFlag.find(":");
|
|
|
|
key = bufferFlag.substr(0, std::min(equal, colon));
|
|
if(equal != std::string::npos) {
|
|
if(colon == std::string::npos) {
|
|
value = bufferFlag.substr(equal + 1, std::string::npos);
|
|
}
|
|
else {
|
|
value = bufferFlag.substr(equal + 1, colon - equal - 1);
|
|
}
|
|
}
|
|
|
|
if(colon != std::string::npos) {
|
|
buffer = bufferFlag.substr(colon + 1, std::string::npos);
|
|
}
|
|
else {
|
|
buffer = key;
|
|
}
|
|
|
|
// buffer name should be lowercase
|
|
std::transform(buffer.begin(), buffer.end(), buffer.begin(), ::tolower);
|
|
_specificBuffers[KeyValue(key, value)] = buffer;
|
|
}
|
|
void setBaseLodURL(const std::string& baseLodURL) { _baseLodURL = baseLodURL; }
|
|
};
|
|
|
|
#endif
|