Merge pull request #102 from marchelbling/update_gles+osgjs
Update gles+osgjs. This PR cleans some gles coverity defects (remaining should only be false positive that need to be sorted out cleanly) updates osgjs plugin to support serialization; the history of changes is squashed; details can still be found on cedricpinson fork if needed As compressed animation channels are no longer part of the main repo, I added a compilation flag for the osgjs plugin. The commit is isolated and the flag is not activated by default. I am yet to find a better solution to make this plugin entirely free from our specific code. Note: this PR will not change the gles compilation issues. We only compile on OSX/ubuntu and did not encounter any issue with the plugin.
This commit is contained in:
commit
9cd52fc54e
@ -1,4 +1,4 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Cedric Pinson
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab
|
||||
*
|
||||
* This application is open source and may be redistributed and/or modified
|
||||
* freely and without restriction, both in commercial and non commercial
|
||||
@ -36,90 +36,6 @@ public:
|
||||
typedef std::vector<osgAnimation::RigGeometry*> RigGeometryList;
|
||||
|
||||
|
||||
osg::Geometry* createBox(const osg::BoundingBox &bb, const osg::Matrix &transform,
|
||||
float ratio=1.0, osg::Vec4 color=osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)) {
|
||||
osg::Geometry *cube = new osg::Geometry;
|
||||
|
||||
osg::Vec3 center = bb.center();
|
||||
double halfLenghtX = (bb._max.x() - bb._min.x()) * 0.50;
|
||||
double halfLenghtY = (bb._max.y() - bb._min.y()) * 0.50;
|
||||
double halfLenghtZ = (bb._max.z() - bb._min.z()) * 0.50;
|
||||
|
||||
halfLenghtX *= ratio;
|
||||
halfLenghtY *= ratio;
|
||||
halfLenghtZ *= ratio;
|
||||
|
||||
osg::Vec3Array *cubeVertices = new osg::Vec3Array;
|
||||
cubeVertices->push_back(osg::Vec3(center.x() - halfLenghtX, center.y() + halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
cubeVertices->push_back(osg::Vec3(center.x() - halfLenghtX, center.y() + halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
cubeVertices->push_back(osg::Vec3(center.x() - halfLenghtX, center.y() - halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
cubeVertices->push_back(osg::Vec3(center.x() - halfLenghtX, center.y() - halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
|
||||
cubeVertices->push_back(osg::Vec3(center.x() + halfLenghtX, center.y() + halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
cubeVertices->push_back(osg::Vec3(center.x() + halfLenghtX, center.y() + halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
cubeVertices->push_back(osg::Vec3(center.x() + halfLenghtX, center.y() - halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
cubeVertices->push_back(osg::Vec3(center.x() + halfLenghtX, center.y() - halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
|
||||
cube->setVertexArray(cubeVertices);
|
||||
|
||||
osg::DrawElementsUInt* up = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
||||
up->push_back(4);
|
||||
up->push_back(5);
|
||||
up->push_back(1);
|
||||
up->push_back(0);
|
||||
cube->addPrimitiveSet(up);
|
||||
|
||||
osg::DrawElementsUInt* down = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
||||
down->push_back(2);
|
||||
down->push_back(6);
|
||||
down->push_back(7);
|
||||
down->push_back(3);
|
||||
cube->addPrimitiveSet(down);
|
||||
|
||||
osg::DrawElementsUInt* left = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
||||
left->push_back(2);
|
||||
left->push_back(3);
|
||||
left->push_back(0);
|
||||
left->push_back(1);
|
||||
cube->addPrimitiveSet(left);
|
||||
|
||||
osg::DrawElementsUInt* right = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
||||
right->push_back(7);
|
||||
right->push_back(6);
|
||||
right->push_back(5);
|
||||
right->push_back(4);
|
||||
cube->addPrimitiveSet(right);
|
||||
|
||||
osg::DrawElementsUInt* front = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
||||
front->push_back(3);
|
||||
front->push_back(7);
|
||||
front->push_back(4);
|
||||
front->push_back(0);
|
||||
cube->addPrimitiveSet(front);
|
||||
|
||||
osg::DrawElementsUInt* back = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
||||
back->push_back(6);
|
||||
back->push_back(2);
|
||||
back->push_back(1);
|
||||
back->push_back(5);
|
||||
cube->addPrimitiveSet(back);
|
||||
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
|
||||
cube->setColorArray(colors);
|
||||
cube->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
return cube;
|
||||
}
|
||||
|
||||
ComputeAABBOnBoneVisitor(bool createGeometry):
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_root(0),
|
||||
@ -149,59 +65,28 @@ public:
|
||||
_rigGeometries.push_back(&rig);
|
||||
}
|
||||
|
||||
void serializeBoundingBox(const osg::BoundingBox &bb, const osg::Matrix &transform, osgAnimation::Bone &b, float ratio = 1.0) {
|
||||
osg::Vec3 center = bb.center();
|
||||
double halfLenghtX = (bb._max.x() - bb._min.x()) * 0.50;
|
||||
double halfLenghtY = (bb._max.y() - bb._min.y()) * 0.50;
|
||||
double halfLenghtZ = (bb._max.z() - bb._min.z()) * 0.50;
|
||||
|
||||
halfLenghtX *= ratio;
|
||||
halfLenghtY *= ratio;
|
||||
halfLenghtZ *= ratio;
|
||||
|
||||
osg::BoundingBox serializedBB;
|
||||
|
||||
serializedBB.expandBy(osg::Vec3(center.x() - halfLenghtX, center.y() + halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() - halfLenghtX, center.y() + halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() - halfLenghtX, center.y() - halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() - halfLenghtX, center.y() - halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() + halfLenghtX, center.y() + halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() + halfLenghtX, center.y() + halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() + halfLenghtX, center.y() - halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() + halfLenghtX, center.y() - halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
|
||||
b.setUserValue("AABBonBone_min", serializedBB._min);
|
||||
b.setUserValue("AABBonBone_max", serializedBB._max);
|
||||
}
|
||||
|
||||
void computeBoundingBoxOnBones() {
|
||||
//Perform Updates
|
||||
|
||||
//Update Bones
|
||||
osgUtil::UpdateVisitor up;
|
||||
_root->accept(up);
|
||||
|
||||
//Update rigGeometries
|
||||
for (unsigned int i = 0, size = _rigGeometries.size(); i < size; i++) {
|
||||
osgAnimation::RigGeometry * rig = _rigGeometries.at(i);
|
||||
osg::Drawable::UpdateCallback * up = dynamic_cast<osg::Drawable::UpdateCallback*>(rig->getUpdateCallback());
|
||||
if(up) up->update(0, rig);
|
||||
}
|
||||
updateBones();
|
||||
updateRigGeometries();
|
||||
|
||||
//We have our T pose, we can compute an AABB for each bone
|
||||
for (BoneList::iterator bone = _bones.begin(); bone != _bones.end(); ++ bone) {
|
||||
osg::BoundingBox bb;
|
||||
//For each geometry
|
||||
for (RigGeometryList::iterator rigGeometry = _rigGeometries.begin(); rigGeometry != _rigGeometries.end(); ++ rigGeometry) {
|
||||
osg::Matrix mtxLocalToSkl = (*rigGeometry)->getWorldMatrices(_root).at(0);
|
||||
for (RigGeometryList::iterator iterator = _rigGeometries.begin(); iterator != _rigGeometries.end(); ++ iterator) {
|
||||
osgAnimation::RigGeometry* rigGeometry = *iterator;
|
||||
if(!rigGeometry) continue;
|
||||
|
||||
osg::Matrix mtxLocalToSkl = rigGeometry->getWorldMatrices(_root).at(0);
|
||||
|
||||
//For each Vertex influence
|
||||
osgAnimation::VertexInfluenceMap * infMap = (*rigGeometry)->getInfluenceMap();
|
||||
osgAnimation::VertexInfluenceMap * infMap = rigGeometry->getInfluenceMap();
|
||||
osgAnimation::VertexInfluenceMap::iterator itMap = infMap->find((*bone)->getName());
|
||||
if(itMap == infMap->end()) continue;
|
||||
|
||||
osgAnimation::VertexInfluence vxtInf = (*itMap).second;
|
||||
osg::Vec3Array *vertices = dynamic_cast<osg::Vec3Array*>((*rigGeometry)->getVertexArray());
|
||||
osg::Vec3Array *vertices = dynamic_cast<osg::Vec3Array*>(rigGeometry->getVertexArray());
|
||||
|
||||
//Expand the boundingBox with each vertex
|
||||
for(unsigned int j = 0; j < vxtInf.size(); j++) {
|
||||
@ -230,14 +115,154 @@ public:
|
||||
}
|
||||
|
||||
//Clear geometries
|
||||
for (RigGeometryList::iterator rigGeometry = _rigGeometries.begin(); rigGeometry != _rigGeometries.end(); ++ rigGeometry) {
|
||||
(*rigGeometry)->copyFrom(*(*rigGeometry)->getSourceGeometry());
|
||||
(*rigGeometry)->setRigTransformImplementation(0);
|
||||
for (RigGeometryList::iterator iterator = _rigGeometries.begin(); iterator != _rigGeometries.end(); ++ iterator) {
|
||||
osgAnimation::RigGeometry* rigGeometry = *iterator;
|
||||
if(rigGeometry) {
|
||||
rigGeometry->copyFrom(*rigGeometry->getSourceGeometry());
|
||||
rigGeometry->setRigTransformImplementation(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<osgAnimation::Bone*> _bones;
|
||||
std::vector<osgAnimation::RigGeometry*> _rigGeometries;
|
||||
protected:
|
||||
osg::Geometry* createBox(const osg::BoundingBox &bb, const osg::Matrix &transform,
|
||||
float ratio=1.0, osg::Vec4 color=osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)) {
|
||||
osg::Geometry *cube = new osg::Geometry;
|
||||
|
||||
osg::Vec3 center = bb.center();
|
||||
double halfLenghtX = (bb._max.x() - bb._min.x()) * 0.50;
|
||||
double halfLenghtY = (bb._max.y() - bb._min.y()) * 0.50;
|
||||
double halfLenghtZ = (bb._max.z() - bb._min.z()) * 0.50;
|
||||
|
||||
halfLenghtX *= ratio;
|
||||
halfLenghtY *= ratio;
|
||||
halfLenghtZ *= ratio;
|
||||
|
||||
osg::Vec3Array *cubeVertices = new osg::Vec3Array;
|
||||
cubeVertices->push_back(osg::Vec3(center.x() - halfLenghtX, center.y() + halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
cubeVertices->push_back(osg::Vec3(center.x() - halfLenghtX, center.y() + halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
cubeVertices->push_back(osg::Vec3(center.x() - halfLenghtX, center.y() - halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
cubeVertices->push_back(osg::Vec3(center.x() - halfLenghtX, center.y() - halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
|
||||
cubeVertices->push_back(osg::Vec3(center.x() + halfLenghtX, center.y() + halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
cubeVertices->push_back(osg::Vec3(center.x() + halfLenghtX, center.y() + halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
cubeVertices->push_back(osg::Vec3(center.x() + halfLenghtX, center.y() - halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
cubeVertices->push_back(osg::Vec3(center.x() + halfLenghtX, center.y() - halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
|
||||
cube->setVertexArray(cubeVertices);
|
||||
|
||||
{
|
||||
osg::DrawElementsUInt* up = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
||||
up->push_back(4);
|
||||
up->push_back(5);
|
||||
up->push_back(1);
|
||||
up->push_back(0);
|
||||
cube->addPrimitiveSet(up);
|
||||
}
|
||||
|
||||
{
|
||||
osg::DrawElementsUInt* down = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
||||
down->push_back(2);
|
||||
down->push_back(6);
|
||||
down->push_back(7);
|
||||
down->push_back(3);
|
||||
cube->addPrimitiveSet(down);
|
||||
}
|
||||
|
||||
{
|
||||
osg::DrawElementsUInt* left = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
||||
left->push_back(2);
|
||||
left->push_back(3);
|
||||
left->push_back(0);
|
||||
left->push_back(1);
|
||||
cube->addPrimitiveSet(left);
|
||||
}
|
||||
|
||||
{
|
||||
osg::DrawElementsUInt* right = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
||||
right->push_back(7);
|
||||
right->push_back(6);
|
||||
right->push_back(5);
|
||||
right->push_back(4);
|
||||
cube->addPrimitiveSet(right);
|
||||
}
|
||||
|
||||
{
|
||||
osg::DrawElementsUInt* front = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
||||
front->push_back(3);
|
||||
front->push_back(7);
|
||||
front->push_back(4);
|
||||
front->push_back(0);
|
||||
cube->addPrimitiveSet(front);
|
||||
}
|
||||
|
||||
{
|
||||
osg::DrawElementsUInt* back = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
|
||||
back->push_back(6);
|
||||
back->push_back(2);
|
||||
back->push_back(1);
|
||||
back->push_back(5);
|
||||
cube->addPrimitiveSet(back);
|
||||
}
|
||||
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
|
||||
cube->setColorArray(colors);
|
||||
cube->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
return cube;
|
||||
}
|
||||
|
||||
void serializeBoundingBox(const osg::BoundingBox &bb, const osg::Matrix &transform, osgAnimation::Bone &b, float ratio = 1.0) {
|
||||
osg::Vec3 center = bb.center();
|
||||
double halfLenghtX = (bb._max.x() - bb._min.x()) * 0.50;
|
||||
double halfLenghtY = (bb._max.y() - bb._min.y()) * 0.50;
|
||||
double halfLenghtZ = (bb._max.z() - bb._min.z()) * 0.50;
|
||||
|
||||
halfLenghtX *= ratio;
|
||||
halfLenghtY *= ratio;
|
||||
halfLenghtZ *= ratio;
|
||||
|
||||
osg::BoundingBox serializedBB;
|
||||
|
||||
serializedBB.expandBy(osg::Vec3(center.x() - halfLenghtX, center.y() + halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() - halfLenghtX, center.y() + halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() - halfLenghtX, center.y() - halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() - halfLenghtX, center.y() - halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() + halfLenghtX, center.y() + halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() + halfLenghtX, center.y() + halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() + halfLenghtX, center.y() - halfLenghtY, center.z() - halfLenghtZ) * transform);
|
||||
serializedBB.expandBy(osg::Vec3(center.x() + halfLenghtX, center.y() - halfLenghtY, center.z() + halfLenghtZ) * transform);
|
||||
|
||||
b.setUserValue("AABBonBone_min", serializedBB._min);
|
||||
b.setUserValue("AABBonBone_max", serializedBB._max);
|
||||
}
|
||||
|
||||
void updateBones() {
|
||||
osgUtil::UpdateVisitor update;
|
||||
_root->accept(update);
|
||||
}
|
||||
|
||||
void updateRigGeometries() {
|
||||
for (unsigned int i = 0, size = _rigGeometries.size(); i < size; i++) {
|
||||
osgAnimation::RigGeometry * rig = _rigGeometries.at(i);
|
||||
osg::Drawable::UpdateCallback * callback = dynamic_cast<osg::Drawable::UpdateCallback*>(rig->getUpdateCallback());
|
||||
if(callback) {
|
||||
callback->update(0, rig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BoneList _bones;
|
||||
RigGeometryList _rigGeometries;
|
||||
osgAnimation::Skeleton *_root;
|
||||
bool _createGeometry;
|
||||
};
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
geometry(false)
|
||||
{}
|
||||
|
||||
void apply(osg::Geometry& object) {
|
||||
void apply(osg::Geometry& /*object*/) {
|
||||
geometry = true;
|
||||
}
|
||||
|
||||
@ -266,18 +266,16 @@ public:
|
||||
// Replace rig geometries by static geometries if:
|
||||
// * empty or inexistant vertex influence map
|
||||
// * no *strictly* positive influence coefficient
|
||||
|
||||
RigGeometryList::iterator rigGeometry = _rigGeometries.begin();
|
||||
while(rigGeometry != _rigGeometries.end()) {
|
||||
if(rigGeometry->valid()) {
|
||||
if(!hasPositiveWeights((*rigGeometry)->getSourceGeometry())) {
|
||||
OSG_WARN << "Monitor: animation.invalid_riggeometry" << std::endl;
|
||||
replaceRigGeometryBySource(*(rigGeometry->get()));
|
||||
_rigGeometries.erase(rigGeometry);
|
||||
continue; // skip iterator increment
|
||||
}
|
||||
for(RigGeometryList::iterator iterator = _rigGeometries.begin() ; iterator != _rigGeometries.end() ; ) {
|
||||
osg::ref_ptr<osgAnimation::RigGeometry> rigGeometry = *iterator;
|
||||
if(rigGeometry.valid() && !hasPositiveWeights(rigGeometry->getSourceGeometry())) {
|
||||
OSG_WARN << "Monitor: animation.invalid_riggeometry" << std::endl;
|
||||
replaceRigGeometryBySource(*rigGeometry.get());
|
||||
_rigGeometries.erase(iterator);
|
||||
}
|
||||
else {
|
||||
++ iterator;
|
||||
}
|
||||
++ rigGeometry;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* -*-c++-*- */
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Cedric Pinson */
|
||||
|
||||
#ifndef GEOMETRY_ARRAY_UTILS_H
|
||||
#define GEOMETRY_ARRAY_UTILS_H
|
||||
|
||||
@ -98,7 +99,7 @@ struct GeometryArrayList {
|
||||
template <class T> bool arrayAppendElement(osg::Array* src, unsigned int index, osg::Array* dst)
|
||||
{
|
||||
T* array = dynamic_cast<T*>(src);
|
||||
if (array) {
|
||||
if (array && dst) {
|
||||
T* arrayDst = dynamic_cast<T*>(dst);
|
||||
arrayDst->push_back((*array)[index]);
|
||||
return true;
|
||||
@ -140,15 +141,6 @@ struct GeometryArrayList {
|
||||
if (arrayAppendElement<osg::Vec4Array>(src, index, dst))
|
||||
return;
|
||||
|
||||
if (arrayAppendElement<osg::Vec2Array>(src, index, dst))
|
||||
return;
|
||||
|
||||
if (arrayAppendElement<osg::Vec3Array>(src, index, dst))
|
||||
return;
|
||||
|
||||
if (arrayAppendElement<osg::Vec4Array>(src, index, dst))
|
||||
return;
|
||||
|
||||
if (arrayAppendElement<osg::Vec2bArray>(src, index, dst))
|
||||
return;
|
||||
|
||||
@ -266,15 +258,6 @@ struct GeometryArrayList {
|
||||
if (arraySetNumElements<osg::Vec4Array>(array, numElements))
|
||||
return;
|
||||
|
||||
if (arraySetNumElements<osg::Vec2Array>(array, numElements))
|
||||
return;
|
||||
|
||||
if (arraySetNumElements<osg::Vec3Array>(array, numElements))
|
||||
return;
|
||||
|
||||
if (arraySetNumElements<osg::Vec4Array>(array, numElements))
|
||||
return;
|
||||
|
||||
if (arraySetNumElements<osg::Vec2bArray>(array, numElements))
|
||||
return;
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab */
|
||||
|
||||
#ifndef GEOMETRY_INSPECTOR
|
||||
#define GEOMETRY_INSPECTOR
|
||||
|
||||
@ -17,7 +19,8 @@
|
||||
|
||||
class GeometryInspector : public GeometryUniqueVisitor {
|
||||
public:
|
||||
void process(osg::Geometry& geometry) {}
|
||||
void process(osg::Geometry& /*geometry*/) {}
|
||||
|
||||
void process(osgAnimation::RigGeometry& rigGeometry) {
|
||||
osgAnimation::MorphGeometry* morph = dynamic_cast<osgAnimation::MorphGeometry*>(rigGeometry.getSourceGeometry());
|
||||
if(morph) {
|
||||
|
@ -133,7 +133,8 @@ public:
|
||||
setTriangleCluster(graph, cache.back(), cluster, clusters, cluster_vertices, remaining_triangles);
|
||||
|
||||
while(remaining_triangles && cluster_vertices.size() < _maxAllowedIndex) {
|
||||
unsigned int candidate;
|
||||
unsigned int candidate = std::numeric_limits<unsigned int>::max();
|
||||
|
||||
for(IndexCache::const_reverse_iterator cached = cache.rbegin() ; cached != cache.rend() ; ++ cached) {
|
||||
candidate = findCandidate(graph.triangleNeighbors(*cached), clusters);
|
||||
if(candidate != std::numeric_limits<unsigned int>::max()) break;
|
||||
|
@ -1,8 +1,8 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab */
|
||||
|
||||
#ifndef LIMIT_MORPH_TARGET_COUNT_VISITOR
|
||||
#define LIMIT_MORPH_TARGET_COUNT_VISITOR
|
||||
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab */
|
||||
|
||||
#include "GeometryUniqueVisitor"
|
||||
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab */
|
||||
|
||||
#ifndef GLES_LINE
|
||||
#define GLES_LINE
|
||||
|
||||
|
@ -49,6 +49,7 @@ public:
|
||||
_disableMergeTriStrip(false),
|
||||
_disablePreTransform(false),
|
||||
_disableAnimation(false),
|
||||
_disableAnimationCleaning(false),
|
||||
_enableAABBonBone(false),
|
||||
_triStripCacheSize(16),
|
||||
_triStripMinSize(2),
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab */
|
||||
|
||||
#ifndef PRIMITIVE_OPERATORS_H
|
||||
#define PRIMITIVE_OPERATORS_H
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Cedric Pinson
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab
|
||||
*
|
||||
* This application is open source and may be redistributed and/or modified
|
||||
* freely and without restriction, both in commercial and non commercial
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab */
|
||||
|
||||
#ifndef RIG_ATTRIBUTES_VISITOR
|
||||
#define RIG_ATTRIBUTES_VISITOR
|
||||
|
||||
@ -31,7 +33,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void process(osg::Geometry& geometry) {
|
||||
void process(osg::Geometry& /*geometry*/) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab */
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
@ -197,7 +199,16 @@ protected:
|
||||
bool flipped = false;
|
||||
|
||||
osg::Vec3Array* normals = dynamic_cast<osg::Vec3Array*>(_geometry.getNormalArray());
|
||||
for(unsigned int index = 0 ; index < _geometry.getVertexArray()->getNumElements() ; ++ index) {
|
||||
osg::Vec3Array* positions = dynamic_cast<osg::Vec3Array*>(_geometry.getVertexArray());
|
||||
|
||||
if(!positions || !normals || normals->getNumElements() != positions->getNumElements()) {
|
||||
OSG_WARN << std::endl
|
||||
<< "Warning: [smoothVertexNormals] [[normals]] Geometry '" << _geometry.getName()
|
||||
<< "' has invalid positions/normals";
|
||||
return;
|
||||
}
|
||||
|
||||
for(unsigned int index = 0 ; index < positions->getNumElements() ; ++ index) {
|
||||
std::vector<IndexVector> oneRing = _graph->vertexOneRing(_graph->unify(index), _creaseAngle);
|
||||
osg::Vec3f smoothedNormal(0.f, 0.f, 0.f);
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab */
|
||||
|
||||
#ifndef STAT_LOGGER
|
||||
#define STAT_LOGGER
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab */
|
||||
|
||||
#ifndef SUB_GEOMETRY
|
||||
#define SUB_GEOMETRY
|
||||
|
||||
@ -49,11 +51,14 @@ public:
|
||||
if(const osgAnimation::MorphGeometry* morphSource = dynamic_cast<const osgAnimation::MorphGeometry*>(&source)) {
|
||||
osgAnimation::MorphGeometry* morph = dynamic_cast<osgAnimation::MorphGeometry*>(_geometry.get());
|
||||
const osgAnimation::MorphGeometry::MorphTargetList& morphTargetList = morphSource->getMorphTargetList();
|
||||
for(osgAnimation::MorphGeometry::MorphTargetList::const_iterator targetSource = morphTargetList.begin() ;
|
||||
targetSource != morphTargetList.end() ; ++ targetSource) {
|
||||
osg::Geometry* target = new osg::Geometry;
|
||||
addSourceBuffers(target, *targetSource->getGeometry());
|
||||
morph->addMorphTarget(target, targetSource->getWeight());
|
||||
|
||||
osgAnimation::MorphGeometry::MorphTargetList::const_iterator targetSource;
|
||||
for(targetSource = morphTargetList.begin() ; targetSource != morphTargetList.end() ; ++ targetSource) {
|
||||
if(targetSource->getGeometry()) {
|
||||
osg::Geometry* target = new osg::Geometry;
|
||||
addSourceBuffers(target, *targetSource->getGeometry());
|
||||
morph->addMorphTarget(target, targetSource->getWeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab */
|
||||
|
||||
#ifndef MESH_GRAPH
|
||||
#define MESH_GRAPH
|
||||
|
||||
@ -171,10 +173,12 @@ public:
|
||||
_positions(dynamic_cast<const osg::Vec3Array*>(geometry.getVertexArray())),
|
||||
_comparePosition(comparePosition)
|
||||
{
|
||||
unsigned int nbVertex = _positions->getNumElements();
|
||||
_unique.resize(nbVertex, std::numeric_limits<unsigned int>::max());
|
||||
_vertexTriangles.resize(nbVertex, IndexVector());
|
||||
build();
|
||||
if(_positions) {
|
||||
unsigned int nbVertex = _positions->getNumElements();
|
||||
_unique.resize(nbVertex, std::numeric_limits<unsigned int>::max());
|
||||
_vertexTriangles.resize(nbVertex, IndexVector());
|
||||
build();
|
||||
}
|
||||
}
|
||||
|
||||
VertexIterator begin() const {
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab */
|
||||
|
||||
#ifndef GLES_UTIL
|
||||
#define GLES_UTIL
|
||||
|
||||
|
117
src/osgPlugins/osgjs/Adaptor
Normal file
117
src/osgPlugins/osgjs/Adaptor
Normal file
@ -0,0 +1,117 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2010 Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*
|
||||
* Authors:
|
||||
* Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*/
|
||||
|
||||
#include <osg/TriangleFunctor>
|
||||
|
||||
|
||||
struct DrawArrayLenghtAdaptor
|
||||
{
|
||||
unsigned int _normalArraySize;
|
||||
const Vec3* _normalArrayPtr;
|
||||
|
||||
unsigned int _colorArraySize;
|
||||
const Vec4* _colorArrayPtr;
|
||||
|
||||
std::vector<std::pair<unsigned int, const osg::Vec2*> > _uvs;
|
||||
|
||||
virtual void setNormalArray(unsigned int count,const Vec3* vertices) {
|
||||
_normalArraySize = count;
|
||||
_normalArrayPtr = vertices;
|
||||
}
|
||||
|
||||
virtual void setNormalArray(unsigned int count,const Vec4* colors) {
|
||||
_colorArraySize = count;
|
||||
_colorArrayPtr = colors;
|
||||
}
|
||||
|
||||
virtual void setTexCoordArray(int unit, unsigned int count,const Vec2* uvs) {
|
||||
if (_uvs.size() <= unit)
|
||||
_uvs.resize(unit+1);
|
||||
_uvs[i].first = count;
|
||||
_uvs[i].second = uvs;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct AdaptDraw : public osg::TriangleFunctor<DrawArrayLenghtAdaptor>
|
||||
{
|
||||
|
||||
virtual void drawArrays(GLenum mode,GLint first,GLsizei count)
|
||||
{
|
||||
if (_vertexArrayPtr==0 || count==0) return;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case(GL_TRIANGLES):
|
||||
{
|
||||
unsigned int last = first+count;
|
||||
for(unsigned int current = first; current<last ; current+=3) {
|
||||
this->operator()(current, current+1, current+2,_treatVertexDataAsTemporary);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(GL_TRIANGLE_STRIP):
|
||||
{
|
||||
unsigned int current = first;
|
||||
for(GLsizei i=2;i<count;++i, current+=1)
|
||||
{
|
||||
if ((i%2)) this->operator()(current, current+2, current+1,_treatVertexDataAsTemporary);
|
||||
else this->operator()(current, current+1, current+2,_treatVertexDataAsTemporary);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(GL_QUADS):
|
||||
{
|
||||
unsigned int current = first;
|
||||
for(GLsizei i=3;i<count;i+=4,current+=4)
|
||||
{
|
||||
this->operator()(current, current+1, current+2,_treatVertexDataAsTemporary);
|
||||
this->operator()(current, current+2, current+3,_treatVertexDataAsTemporary);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(GL_QUAD_STRIP):
|
||||
{
|
||||
unsigned int current = first;
|
||||
for(GLsizei i=3;i<count;i+=2,current+=2)
|
||||
{
|
||||
this->operator()(current, current+1, current+2,_treatVertexDataAsTemporary);
|
||||
this->operator()(current+1, current+3, current+2,_treatVertexDataAsTemporary);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
|
||||
case(GL_TRIANGLE_FAN):
|
||||
{
|
||||
unsigned int current = first + 1;
|
||||
for(GLsizei i=2;i<count;++i,++current)
|
||||
{
|
||||
this->operator()(first),current, current+1,_treatVertexDataAsTemporary);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(GL_POINTS):
|
||||
case(GL_LINES):
|
||||
case(GL_LINE_STRIP):
|
||||
case(GL_LINE_LOOP):
|
||||
default:
|
||||
// can't be converted into to triangles.
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
@ -6,7 +6,29 @@
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osgAnimation/UpdateMatrixTransform>
|
||||
|
||||
JSONObject* createJSONAnimation(osgAnimation::Animation* anim);
|
||||
JSONObject* createJSONUpdateMatrixTransform(osgAnimation::UpdateMatrixTransform& acb);
|
||||
struct WriteVisitor;
|
||||
|
||||
JSONObject* createJSONAnimation(osgAnimation::Animation* anim, WriteVisitor* writer);
|
||||
JSONObject* createJSONUpdateMatrixTransform(osgAnimation::UpdateMatrixTransform& acb, WriteVisitor* writer);
|
||||
|
||||
|
||||
// Remaps: [(u0, v0,..., w0), (u1, v1, ... w1), ..., (un, vn, ..., wn)]
|
||||
// into: [(u0, u1, ...), ..., (v0, v1, ...), ..., (w0, w1, ...), ...]
|
||||
template<typename In, typename Out>
|
||||
Out* pack(const In* array) {
|
||||
unsigned int inSize = array->getNumElements();
|
||||
unsigned int inDim = In::ElementDataType::num_components;
|
||||
unsigned int outDim = Out::ElementDataType::num_components;
|
||||
|
||||
Out* interleaved = new Out(static_cast<unsigned int>(.5 + (inSize * inDim) * 1. / outDim));
|
||||
|
||||
for(unsigned int i = 0 ; i < inSize ; ++ i) {
|
||||
for(unsigned int j = 0 ; j < inDim ; ++ j) {
|
||||
unsigned int index = j * inSize + i;
|
||||
(*interleaved)[index / outDim][index % outDim] = (*array)[i][j];
|
||||
}
|
||||
}
|
||||
return interleaved;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,66 +1,109 @@
|
||||
/* -*-c++-*-
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2011 Cedric Pinson <cedric.pinson@plopbyte.com>
|
||||
*/
|
||||
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osgAnimation/Channel>
|
||||
#include <osgAnimation/CubicBezier>
|
||||
#include <osgAnimation/Sampler>
|
||||
#include <osgAnimation/UpdateMatrixTransform>
|
||||
#include <osgAnimation/StackedTranslateElement>
|
||||
#include <osgAnimation/StackedQuaternionElement>
|
||||
#include <osgAnimation/StackedRotateAxisElement>
|
||||
#include <osgAnimation/StackedMatrixElement>
|
||||
#include <osgAnimation/StackedScaleElement>
|
||||
#include <osg/Array>
|
||||
#include "JSON_Objects"
|
||||
#include "WriteVisitor"
|
||||
|
||||
static bool addJSONChannelVec3(osgAnimation::Vec3LinearChannel* channel, JSONObject& anim)
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
struct osg_array
|
||||
{ typedef osg::Array array_type; };
|
||||
|
||||
#define ADD_ARRAY_TYPE(T, A)\
|
||||
template<> \
|
||||
struct osg_array<T> \
|
||||
{ typedef A array_type; }
|
||||
|
||||
ADD_ARRAY_TYPE(osg::Vec3f, osg::Vec3Array);
|
||||
ADD_ARRAY_TYPE(osg::Quat, osg::QuatArray);
|
||||
ADD_ARRAY_TYPE(osg::Vec3i, osg::Vec3iArray);
|
||||
ADD_ARRAY_TYPE(osg::Vec4i, osg::Vec4iArray);
|
||||
ADD_ARRAY_TYPE(osg::Vec3ui, osg::Vec3uiArray);
|
||||
ADD_ARRAY_TYPE(osg::Vec3us, osg::Vec3usArray);
|
||||
ADD_ARRAY_TYPE(float, osg::FloatArray);
|
||||
ADD_ARRAY_TYPE(double, osg::FloatArray);
|
||||
ADD_ARRAY_TYPE(int, osg::IntArray);
|
||||
ADD_ARRAY_TYPE(unsigned int, osg::UIntArray);
|
||||
ADD_ARRAY_TYPE(unsigned short, osg::UShortArray);
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool addJSONChannel(const std::string& channelType, T* channel, bool packByCoords, JSONObject& anim, WriteVisitor* writer, osg::Object* parent) {
|
||||
if (channel && channel->getSampler()) {
|
||||
osg::ref_ptr<JSONObject> json = new JSONObject;
|
||||
std::string jsonType = channelType + (packByCoords ? "Packed" : "");
|
||||
|
||||
translateObject(json.get(), channel);
|
||||
|
||||
json->getMaps()["Name"] = new JSONValue<std::string>(channel->getName());
|
||||
json->getMaps()["TargetName"] = new JSONValue<std::string>(channel->getTargetName());
|
||||
osgAnimation::Vec3KeyframeContainer* keys = channel->getSamplerTyped()->getKeyframeContainerTyped();
|
||||
JSONKeyframes* jsonKeys = new JSONKeyframes();
|
||||
//if (!keys->getName().empty()) {
|
||||
// jsonKeys->getMaps()["Name"] = new JSONValue<std::string>(keys->getName());
|
||||
//}
|
||||
|
||||
typename T::KeyframeContainerType* keys = channel->getSamplerTyped()->getKeyframeContainerTyped();
|
||||
typedef typename T::UsingType KeyframeType;
|
||||
typedef typename osg_array<KeyframeType>::array_type KeyframeArray;
|
||||
|
||||
osg::ref_ptr<JSONObject> jsKeys = new JSONObject;
|
||||
osg::ref_ptr<osg::FloatArray> timesArray = new osg::FloatArray;
|
||||
osg::ref_ptr<KeyframeArray> valuesArray = new KeyframeArray;
|
||||
|
||||
for (unsigned int i = 0; i < keys->size(); i++) {
|
||||
JSONVec4Array* kf = new JSONVec4Array(osg::Vec4((*keys)[i].getTime(),
|
||||
(*keys)[i].getValue()[0],
|
||||
(*keys)[i].getValue()[1],
|
||||
(*keys)[i].getValue()[2]));
|
||||
jsonKeys->getArray().push_back(kf);
|
||||
timesArray->push_back((*keys)[i].getTime());
|
||||
valuesArray->push_back((*keys)[i].getValue());
|
||||
}
|
||||
json->getMaps()["KeyFrames"] = jsonKeys;
|
||||
|
||||
|
||||
jsKeys->getMaps()["Time"] = writer->createJSONBufferArray(timesArray.get(), parent);
|
||||
|
||||
osg::ref_ptr<KeyframeArray> values;
|
||||
if(packByCoords) { // data channel packing
|
||||
values = pack<KeyframeArray, KeyframeArray>(valuesArray.get());
|
||||
}
|
||||
else {
|
||||
values = valuesArray;
|
||||
}
|
||||
|
||||
jsKeys->getMaps()["Key"] = writer->createJSONBufferArray(values.get(), parent);
|
||||
json->getMaps()["KeyFrames"] = jsKeys;
|
||||
|
||||
osg::ref_ptr<JSONObject> jsonChannel = new JSONObject();
|
||||
jsonChannel->getMaps()["osgAnimation.Vec3LerpChannel"] = json;
|
||||
jsonChannel->getMaps()[jsonType] = json;
|
||||
anim.getMaps()["Channels"]->asArray()->getArray().push_back(jsonChannel);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool addJSONChannelFloat(osgAnimation::FloatLinearChannel* channel, JSONObject& anim)
|
||||
static bool addJSONChannelFloat(osgAnimation::FloatLinearChannel* channel, JSONObject& anim, WriteVisitor* writer, osg::Object* parent=0)
|
||||
{
|
||||
if (channel->getSampler()) {
|
||||
osg::ref_ptr<JSONObject> json = new JSONObject;
|
||||
json->getMaps()["Name"] = new JSONValue<std::string>(channel->getName());
|
||||
json->getMaps()["TargetName"] = new JSONValue<std::string>(channel->getTargetName());
|
||||
osgAnimation::FloatKeyframeContainer* keys = channel->getSamplerTyped()->getKeyframeContainerTyped();
|
||||
JSONKeyframes* jsonKeys = new JSONKeyframes();
|
||||
//if (!keys->getName().empty()) {
|
||||
// jsonKeys->getMaps()["Name"] = new JSONValue<std::string>(keys->getName());
|
||||
//}
|
||||
osg::ref_ptr<JSONObject> jsKeys = new JSONObject;
|
||||
osg::ref_ptr<osg::FloatArray> timesArray = new osg::FloatArray;
|
||||
osg::ref_ptr<osg::FloatArray> keysArray = new osg::FloatArray;
|
||||
|
||||
for (unsigned int i = 0; i < keys->size(); i++) {
|
||||
JSONVec2Array* kf = new JSONVec2Array(osg::Vec2((*keys)[i].getTime(),
|
||||
(*keys)[i].getValue()));
|
||||
jsonKeys->getArray().push_back(kf);
|
||||
timesArray->push_back((*keys)[i].getTime());
|
||||
keysArray->push_back((*keys)[i].getValue());
|
||||
}
|
||||
json->getMaps()["KeyFrames"] = jsonKeys;
|
||||
|
||||
|
||||
jsKeys->getMaps()["Time"] = writer->createJSONBufferArray(timesArray.get(), parent);
|
||||
jsKeys->getMaps()["Key"] = writer->createJSONBufferArray(keysArray.get(), parent);
|
||||
json->getMaps()["KeyFrames"] = jsKeys;
|
||||
|
||||
osg::ref_ptr<JSONObject> jsonChannel = new JSONObject();
|
||||
jsonChannel->getMaps()["osgAnimation.FloatLerpChannel"] = json;
|
||||
anim.getMaps()["Channels"]->asArray()->getArray().push_back(jsonChannel);
|
||||
@ -69,82 +112,198 @@ static bool addJSONChannelFloat(osgAnimation::FloatLinearChannel* channel, JSONO
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool addJSONChannelQuaternion(osgAnimation::QuatSphericalLinearChannel* channel, JSONObject& anim)
|
||||
static bool addJSONChannelFloatCubicBezier(osgAnimation::FloatCubicBezierChannel* channel, JSONObject& anim, WriteVisitor* writer, osg::Object* parent=0)
|
||||
{
|
||||
if (channel->getSampler()) {
|
||||
if(channel->getSampler()) {
|
||||
osg::ref_ptr<JSONObject> json = new JSONObject;
|
||||
json->getMaps()["Name"] = new JSONValue<std::string>(channel->getName());
|
||||
json->getMaps()["TargetName"] = new JSONValue<std::string>(channel->getTargetName());
|
||||
osgAnimation::QuatKeyframeContainer* keys = channel->getSamplerTyped()->getKeyframeContainerTyped();
|
||||
JSONKeyframes* jsonKeys = new JSONKeyframes();
|
||||
|
||||
osgAnimation::FloatCubicBezierKeyframeContainer * keys = channel->getSamplerTyped()->getKeyframeContainerTyped();
|
||||
osg::ref_ptr<osg::FloatArray> timeArray = new osg::FloatArray,
|
||||
positionArray = new osg::FloatArray,
|
||||
controlPointInArray = new osg::FloatArray,
|
||||
controlPointOutArray = new osg::FloatArray;
|
||||
|
||||
for (unsigned int i = 0; i < keys->size(); i++) {
|
||||
JSONVec5Array* kf = new JSONVec5Array(Vec5((*keys)[i].getTime(),
|
||||
(*keys)[i].getValue()[0],
|
||||
(*keys)[i].getValue()[1],
|
||||
(*keys)[i].getValue()[2],
|
||||
(*keys)[i].getValue()[3]));
|
||||
jsonKeys->getArray().push_back(kf);
|
||||
timeArray->push_back((*keys)[i].getTime());
|
||||
positionArray->push_back((*keys)[i].getValue().getPosition());
|
||||
controlPointInArray->push_back((*keys)[i].getValue().getControlPointIn());
|
||||
controlPointOutArray->push_back((*keys)[i].getValue().getControlPointOut());
|
||||
}
|
||||
json->getMaps()["KeyFrames"] = jsonKeys;
|
||||
|
||||
osg::ref_ptr<JSONObject> jsKeys = new JSONObject;
|
||||
|
||||
jsKeys->getMaps()["ControlPointOut"] = writer->createJSONBufferArray(controlPointOutArray.get(), parent);
|
||||
|
||||
jsKeys->getMaps()["ControlPointIn"] = writer->createJSONBufferArray(controlPointInArray.get(), parent);
|
||||
|
||||
jsKeys->getMaps()["Position"] = writer->createJSONBufferArray(positionArray.get(), parent);
|
||||
|
||||
jsKeys->getMaps()["Time"] = writer->createJSONBufferArray(timeArray.get(), parent);
|
||||
|
||||
json->getMaps()["KeyFrames"] = jsKeys;
|
||||
|
||||
osg::ref_ptr<JSONObject> jsonChannel = new JSONObject();
|
||||
jsonChannel->getMaps()["osgAnimation.QuatSlerpChannel"] = json;
|
||||
jsonChannel->getMaps()["osgAnimation.FloatCubicBezierChannel"] = json;
|
||||
anim.getMaps()["Channels"]->asArray()->getArray().push_back(jsonChannel);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void addJSONChannel(osgAnimation::Channel* channel, JSONObject& anim)
|
||||
static bool addJSONChannelVec3CubicBezier(osgAnimation::Vec3CubicBezierChannel* channel, JSONObject& anim, WriteVisitor* writer, osg::Object* parent=0)
|
||||
{
|
||||
if(channel->getSampler()) {
|
||||
osg::ref_ptr<JSONObject> json = new JSONObject;
|
||||
json->getMaps()["Name"] = new JSONValue<std::string>(channel->getName());
|
||||
json->getMaps()["TargetName"] = new JSONValue<std::string>(channel->getTargetName());
|
||||
|
||||
osgAnimation::Vec3CubicBezierKeyframeContainer * keys = channel->getSamplerTyped()->getKeyframeContainerTyped();
|
||||
osg::ref_ptr<osg::FloatArray> timeArray = new osg::FloatArray,
|
||||
positionArrayX = new osg::FloatArray,
|
||||
positionArrayY = new osg::FloatArray,
|
||||
positionArrayZ = new osg::FloatArray,
|
||||
|
||||
controlPointInArrayX = new osg::FloatArray,
|
||||
controlPointInArrayY = new osg::FloatArray,
|
||||
controlPointInArrayZ = new osg::FloatArray,
|
||||
|
||||
controlPointOutArrayX = new osg::FloatArray,
|
||||
controlPointOutArrayY = new osg::FloatArray,
|
||||
controlPointOutArrayZ = new osg::FloatArray;
|
||||
|
||||
for (unsigned int i = 0; i < keys->size(); i++) {
|
||||
timeArray->push_back((*keys)[i].getTime());
|
||||
|
||||
positionArrayX->push_back((*keys)[i].getValue().getPosition().x());
|
||||
positionArrayY->push_back((*keys)[i].getValue().getPosition().y());
|
||||
positionArrayZ->push_back((*keys)[i].getValue().getPosition().z());
|
||||
|
||||
controlPointInArrayX->push_back((*keys)[i].getValue().getControlPointIn().x());
|
||||
controlPointInArrayY->push_back((*keys)[i].getValue().getControlPointIn().y());
|
||||
controlPointInArrayZ->push_back((*keys)[i].getValue().getControlPointIn().z());
|
||||
|
||||
controlPointOutArrayX->push_back((*keys)[i].getValue().getControlPointOut().x());
|
||||
controlPointOutArrayY->push_back((*keys)[i].getValue().getControlPointOut().y());
|
||||
controlPointOutArrayZ->push_back((*keys)[i].getValue().getControlPointOut().z());
|
||||
}
|
||||
osg::ref_ptr<JSONObject> jsKeys = new JSONObject;
|
||||
|
||||
osg::ref_ptr<JSONArray> jsControlPointOutArray = new JSONArray;
|
||||
jsControlPointOutArray->asArray()->getArray().push_back(writer->createJSONBufferArray(controlPointOutArrayX.get(), parent));
|
||||
jsControlPointOutArray->asArray()->getArray().push_back(writer->createJSONBufferArray(controlPointOutArrayY.get(), parent));
|
||||
jsControlPointOutArray->asArray()->getArray().push_back(writer->createJSONBufferArray(controlPointOutArrayZ.get(), parent));
|
||||
jsKeys->getMaps()["ControlPointOut"] = jsControlPointOutArray;
|
||||
|
||||
osg::ref_ptr<JSONArray> jsControlPointInArray = new JSONArray;
|
||||
jsControlPointInArray->asArray()->getArray().push_back(writer->createJSONBufferArray(controlPointInArrayX.get(), parent));
|
||||
jsControlPointInArray->asArray()->getArray().push_back(writer->createJSONBufferArray(controlPointInArrayY.get(), parent));
|
||||
jsControlPointInArray->asArray()->getArray().push_back(writer->createJSONBufferArray(controlPointInArrayZ.get(), parent));
|
||||
jsKeys->getMaps()["ControlPointIn"] = jsControlPointInArray;
|
||||
|
||||
osg::ref_ptr<JSONArray> jsPositionVertexArray = new JSONArray;
|
||||
jsPositionVertexArray->asArray()->getArray().push_back(writer->createJSONBufferArray(positionArrayX.get(), parent));
|
||||
jsPositionVertexArray->asArray()->getArray().push_back(writer->createJSONBufferArray(positionArrayY.get(), parent));
|
||||
jsPositionVertexArray->asArray()->getArray().push_back(writer->createJSONBufferArray(positionArrayZ.get(), parent));
|
||||
jsKeys->getMaps()["Position"] = jsPositionVertexArray;
|
||||
|
||||
jsKeys->getMaps()["Time"] = writer->createJSONBufferArray(timeArray.get(), parent);
|
||||
|
||||
json->getMaps()["KeyFrames"] = jsKeys;
|
||||
|
||||
osg::ref_ptr<JSONObject> jsonChannel = new JSONObject();
|
||||
jsonChannel->getMaps()["osgAnimation.Vec3CubicBezierChannel"] = json;
|
||||
anim.getMaps()["Channels"]->asArray()->getArray().push_back(jsonChannel);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void addJSONChannel(osgAnimation::Channel* channel, JSONObject& anim, WriteVisitor* writer, osg::Object* parent=0)
|
||||
{
|
||||
{
|
||||
osgAnimation::Vec3LinearChannel* c = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
|
||||
osgAnimation::FloatLinearChannel* c = dynamic_cast<osgAnimation::FloatLinearChannel*>(channel);
|
||||
if (c) {
|
||||
if (addJSONChannelVec3(c, anim))
|
||||
if (addJSONChannelFloat(c, anim, writer, parent))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
osgAnimation::FloatLinearChannel* c = dynamic_cast<osgAnimation::FloatLinearChannel*>(channel);
|
||||
osgAnimation::Vec3LinearChannel* c = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
|
||||
if (c) {
|
||||
if (addJSONChannelFloat(c, anim))
|
||||
if (addJSONChannel<osgAnimation::Vec3LinearChannel>("osgAnimation.Vec3LerpChannel", c, false, anim, writer, parent))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_COMPRESSED_CHANNELS
|
||||
{
|
||||
osgAnimation::Vec3usLinearChannel* c = dynamic_cast<osgAnimation::Vec3usLinearChannel*>(channel);
|
||||
if (c) {
|
||||
if (addJSONChannel<osgAnimation::Vec3usLinearChannel>("osgAnimation.Vec3LerpChannelCompressed", c, true, anim, writer, parent))
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
osgAnimation::QuatSphericalLinearChannel* c = dynamic_cast<osgAnimation::QuatSphericalLinearChannel*>(channel);
|
||||
if (c) {
|
||||
if (addJSONChannelQuaternion(c, anim))
|
||||
if (addJSONChannel<osgAnimation::QuatSphericalLinearChannel>("osgAnimation.QuatSlerpChannel", c, false, anim, writer, parent))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_COMPRESSED_CHANNELS
|
||||
{
|
||||
osgAnimation::Vec3usSphericalLinearChannel* c = dynamic_cast<osgAnimation::Vec3usSphericalLinearChannel*>(channel);
|
||||
if (c) {
|
||||
if (addJSONChannel<osgAnimation::Vec3usSphericalLinearChannel>("osgAnimation.QuatSlerpChannelCompressed", c, true, anim, writer, parent))
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
osgAnimation::FloatCubicBezierChannel* c = dynamic_cast<osgAnimation::FloatCubicBezierChannel*>(channel);
|
||||
if (c) {
|
||||
if (addJSONChannelFloatCubicBezier(c, anim, writer, parent))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
osgAnimation::Vec3CubicBezierChannel *c = dynamic_cast<osgAnimation::Vec3CubicBezierChannel*>(channel);
|
||||
if (c) {
|
||||
if (addJSONChannelVec3CubicBezier(c, anim, writer, parent))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
JSONObject* createJSONAnimation(osgAnimation::Animation* anim)
|
||||
JSONObject* createJSONAnimation(osgAnimation::Animation* anim, WriteVisitor* writer)
|
||||
{
|
||||
osg::ref_ptr<JSONObject> json = new JSONObject;
|
||||
json->addUniqueID();
|
||||
json->getMaps()["Channels"] = new JSONArray();
|
||||
json->getMaps()["Name"] = new JSONValue<std::string>(anim->getName());
|
||||
|
||||
for (unsigned int i = 0; i < anim->getChannels().size(); i++) {
|
||||
addJSONChannel(anim->getChannels()[i].get(), *json);
|
||||
addJSONChannel(anim->getChannels()[i].get(), *json, writer, anim);
|
||||
}
|
||||
return json.release();
|
||||
}
|
||||
|
||||
|
||||
|
||||
JSONObject* createJSONUpdateMatrixTransform(osgAnimation::UpdateMatrixTransform& acb)
|
||||
JSONObject* createJSONUpdateMatrixTransform(osgAnimation::UpdateMatrixTransform& acb, WriteVisitor* writer)
|
||||
{
|
||||
std::string name = acb.getName();
|
||||
osg::ref_ptr<JSONObject> json = new JSONObject;
|
||||
json->addUniqueID();
|
||||
json->getMaps()["Name"] = new JSONValue<std::string>(acb.getName());
|
||||
|
||||
|
||||
osg::ref_ptr<JSONArray> jsonStackedArray = new JSONArray();
|
||||
json->getMaps()["StackedTransforms"] = jsonStackedArray;
|
||||
|
||||
@ -194,8 +353,41 @@ JSONObject* createJSONUpdateMatrixTransform(osgAnimation::UpdateMatrixTransform&
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
osgAnimation::StackedMatrixElement * element = dynamic_cast<osgAnimation::StackedMatrixElement*>(st[i].get());
|
||||
if (element) {
|
||||
osg::ref_ptr<JSONObject> jsonElement = new JSONObject;
|
||||
jsonElement->getMaps()["Name"] = new JSONValue<std::string>(element->getName());
|
||||
jsonElement->getMaps()["Matrix"] = new JSONMatrix(element->getMatrix());
|
||||
|
||||
osg::ref_ptr<JSONObject> jsonElementObject = new JSONObject;
|
||||
jsonElementObject->getMaps()["osgAnimation.StackedMatrix"] = jsonElement;
|
||||
jsonStackedArray->getArray().push_back(jsonElementObject);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
osgAnimation::StackedScaleElement * element = dynamic_cast<osgAnimation::StackedScaleElement*>(st[i].get());
|
||||
if (element) {
|
||||
osg::ref_ptr<JSONObject> jsonElement = new JSONObject;
|
||||
jsonElement->getMaps()["Name"] = new JSONValue<std::string>(element->getName());
|
||||
jsonElement->getMaps()["Scale"] = new JSONVec3Array(element->getScale());
|
||||
|
||||
osg::ref_ptr<JSONObject> jsonElementObject = new JSONObject;
|
||||
jsonElementObject->getMaps()["osgAnimation.StackedScale"] = jsonElement;
|
||||
jsonStackedArray->getArray().push_back(jsonElementObject);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (jsonStackedArray->getArray().empty()) {
|
||||
|
||||
// In the case of a Bone, we serialize the UpdateBone element even if there are no stackedTransforms. The reason is
|
||||
// that for now, we use UpdateBone to compute the transforms from bone's parents, and for a bone without UpdateBone we
|
||||
// get a bad transform and the related geometries are messed up
|
||||
if (jsonStackedArray->getArray().empty() && !dynamic_cast<osgAnimation::UpdateBone*>(&acb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6,15 +6,20 @@ SET(TARGET_SRC
|
||||
WriteVisitor.cpp)
|
||||
|
||||
SET(TARGET_H
|
||||
Adaptator
|
||||
Adaptor
|
||||
Animation
|
||||
Base64
|
||||
CompactBufferVisitor
|
||||
JSON_Objects
|
||||
json_stream
|
||||
utf8_string
|
||||
WriteVisitor
|
||||
)
|
||||
|
||||
IF($ENV{SKETCHFAB_BUILD})
|
||||
ADD_DEFINITIONS(-DUSE_COMPRESSED_CHANNELS)
|
||||
ENDIF()
|
||||
|
||||
#### end var setup ###
|
||||
SET(TARGET_ADDED_LIBRARIES
|
||||
osgAnimation
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Geode>
|
||||
|
||||
#include <osgAnimation/RigGeometry>
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
@ -31,23 +33,17 @@ class CompactBufferVisitor : public osg::NodeVisitor {
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{}
|
||||
|
||||
void apply(osg::Geode& geode){
|
||||
for (unsigned int i = 0; i < geode.getNumDrawables(); i++) {
|
||||
apply(*geode.getDrawable(i));
|
||||
}
|
||||
}
|
||||
|
||||
void apply(osg::Drawable& drawable){
|
||||
osg::Geometry* geometry = drawable.asGeometry();
|
||||
if (!geometry || isProcessed(geometry)) {
|
||||
return;
|
||||
}
|
||||
apply(*geometry);
|
||||
}
|
||||
|
||||
void apply(osg::Geometry& geometry) {
|
||||
if(isProcessed(&geometry))
|
||||
return;
|
||||
|
||||
compactPrimitiveSets(geometry);
|
||||
setProcessed(&geometry);
|
||||
|
||||
osgAnimation::RigGeometry *rig = dynamic_cast<osgAnimation::RigGeometry*>(&geometry);
|
||||
if(rig && rig->getSourceGeometry()) {
|
||||
apply(*rig->getSourceGeometry());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,21 +21,6 @@
|
||||
|
||||
class WriteVisitor;
|
||||
|
||||
struct Vec5
|
||||
{
|
||||
float _v[5];
|
||||
Vec5() {}
|
||||
Vec5(float a0, float a1, float a2, float a3, float a4) {
|
||||
_v[0] = a0;
|
||||
_v[1] = a1;
|
||||
_v[2] = a2;
|
||||
_v[3] = a3;
|
||||
_v[4] = a4;
|
||||
};
|
||||
inline float& operator [] (int i) { return _v[i]; }
|
||||
inline float operator [] (int i) const { return _v[i]; }
|
||||
};
|
||||
|
||||
struct JSONObjectBase : public osg::Referenced
|
||||
{
|
||||
static int level;
|
||||
@ -50,8 +35,23 @@ struct JSONObject : public JSONObjectBase
|
||||
{
|
||||
typedef std::map<std::string, osg::ref_ptr<JSONObject> > JSONMap;
|
||||
typedef std::vector<std::string> OrderList;
|
||||
|
||||
static unsigned int uniqueID;
|
||||
std::string _bufferName;
|
||||
JSONMap _maps;
|
||||
|
||||
JSONObject() {}
|
||||
JSONObject(const unsigned int id, const std::string& bufferName = "");
|
||||
|
||||
void addUniqueID();
|
||||
unsigned int getUniqueID() const;
|
||||
JSONObject* getShadowObject() { return new JSONObject(getUniqueID(), _bufferName); }
|
||||
|
||||
virtual void setBufferName(const std::string& name) { _bufferName = name; }
|
||||
std::string getBufferName() { return _bufferName; }
|
||||
|
||||
JSONMap& getMaps() { return _maps; }
|
||||
|
||||
void writeOrder(json_stream& str, const OrderList& order, WriteVisitor& visitor);
|
||||
virtual void write(json_stream& str, WriteVisitor& visitor);
|
||||
void addChild(const std::string& type, JSONObject* child);
|
||||
@ -60,18 +60,6 @@ struct JSONObject : public JSONObjectBase
|
||||
return dynamic_cast<JSONValue<T> * > ( this);
|
||||
}
|
||||
|
||||
JSONObject(const unsigned int id, const std::string& bufferName = "");
|
||||
JSONObject();
|
||||
void addUniqueID();
|
||||
unsigned int getUniqueID() const { return _uniqueID; }
|
||||
JSONObject* getShadowObject() { return new JSONObject(_uniqueID, _bufferName); }
|
||||
|
||||
unsigned int _uniqueID;
|
||||
static unsigned int uniqueID;
|
||||
|
||||
std::string _bufferName;
|
||||
virtual void setBufferName(const std::string& name) { _bufferName = name; }
|
||||
std::string getBufferName() { return _bufferName; }
|
||||
bool isVarintableIntegerBuffer(osg::Array const*) const;
|
||||
void encodeArrayAsVarintBuffer(osg::Array const*, std::vector<uint8_t>&) const;
|
||||
template<typename T>
|
||||
@ -88,15 +76,16 @@ struct JSONObject : public JSONObjectBase
|
||||
|
||||
JSONObject* createLight(osg::Light* light);
|
||||
|
||||
struct JSONNode : public JSONObject
|
||||
struct JSONObjectWithUniqueID : public JSONObject
|
||||
{
|
||||
void write(json_stream& str, WriteVisitor& visitor);
|
||||
JSONObjectWithUniqueID()
|
||||
{ addUniqueID(); }
|
||||
};
|
||||
|
||||
typedef JSONObject JSONStateSet;
|
||||
typedef JSONObject JSONMaterial;
|
||||
typedef JSONObject JSONLight;
|
||||
|
||||
typedef JSONObjectWithUniqueID JSONNode;
|
||||
typedef JSONObjectWithUniqueID JSONStateSet;
|
||||
typedef JSONObjectWithUniqueID JSONMaterial;
|
||||
typedef JSONObjectWithUniqueID JSONLight;
|
||||
|
||||
struct JSONArray : public JSONObject
|
||||
{
|
||||
@ -108,11 +97,6 @@ struct JSONArray : public JSONObject
|
||||
JSONArray* asArray() { return this; }
|
||||
};
|
||||
|
||||
struct JSONKeyframes : public JSONArray
|
||||
{
|
||||
virtual void write(json_stream& str, WriteVisitor& visitor);
|
||||
};
|
||||
|
||||
|
||||
struct JSONVec3Array : public JSONArray
|
||||
{
|
||||
@ -126,11 +110,6 @@ struct JSONVec4Array : public JSONVec3Array
|
||||
JSONVec4Array(const osg::Vec4&);
|
||||
};
|
||||
|
||||
struct JSONVec5Array : public JSONVec3Array
|
||||
{
|
||||
JSONVec5Array(const Vec5&);
|
||||
};
|
||||
|
||||
struct JSONVec2Array : public JSONVec3Array
|
||||
{
|
||||
JSONVec2Array(const osg::Vec2&);
|
||||
@ -140,30 +119,20 @@ template <class T>
|
||||
struct JSONValue : public JSONObject
|
||||
{
|
||||
T _value;
|
||||
|
||||
JSONValue(const T& v) {
|
||||
_value = v;
|
||||
}
|
||||
|
||||
T& getValue() { return _value; }
|
||||
T getValue() const { return _value; }
|
||||
|
||||
virtual void write(json_stream& str, WriteVisitor& /*visitor*/) {
|
||||
str << _value ;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JSONValue<double> : public JSONObject
|
||||
{
|
||||
double _value;
|
||||
JSONValue(const double& v) {
|
||||
_value = v;
|
||||
}
|
||||
void write(json_stream& str, WriteVisitor& /*visitor*/) {
|
||||
if (osg::isNaN(_value)) {
|
||||
_value = 0.0;
|
||||
}
|
||||
str << _value;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JSONValue<std::string> : public JSONObject
|
||||
@ -171,35 +140,30 @@ struct JSONValue<std::string> : public JSONObject
|
||||
std::string _value;
|
||||
|
||||
JSONValue(const std::string& v) {
|
||||
_value = jsonEscape(v);
|
||||
_value = escape(v);
|
||||
}
|
||||
|
||||
void write(json_stream& str, WriteVisitor& /*visitor*/) {
|
||||
str << '"' << _value << '"';
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string jsonEscape(const std::string& input) {
|
||||
std::string value = input;
|
||||
replace(value, std::string("\\"), std::string("\\\\"));
|
||||
replace(value, std::string("\""), std::string("\\\""));
|
||||
replace(value, std::string("\b"), std::string("\\b"));
|
||||
replace(value, std::string("\f"), std::string("\\f"));
|
||||
replace(value, std::string("\n"), std::string("\\n"));
|
||||
replace(value, std::string("\r"), std::string("\\r"));
|
||||
replace(value, std::string("\t"), std::string("\\t"));
|
||||
return value;
|
||||
}
|
||||
protected:
|
||||
std::string escape(const std::string& input) {
|
||||
std::string value = input;
|
||||
replace(value, std::string("\\"), std::string("\\\\"));
|
||||
replace(value, std::string("\""), std::string("\\\""));
|
||||
return value;
|
||||
}
|
||||
|
||||
void replace(std::string& str, const std::string& from, const std::string& to) {
|
||||
if(from.empty())
|
||||
return;
|
||||
size_t start_pos = 0;
|
||||
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
|
||||
str.replace(start_pos, from.length(), to);
|
||||
start_pos += to.length();
|
||||
}
|
||||
void replace(std::string& str, const std::string& from, const std::string& to) {
|
||||
if(from.empty())
|
||||
return;
|
||||
size_t start_pos = 0;
|
||||
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
|
||||
str.replace(start_pos, from.length(), to);
|
||||
start_pos += to.length();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -273,9 +237,8 @@ struct JSONVertexArray : public JSONArray
|
||||
}
|
||||
};
|
||||
|
||||
struct JSONBufferArray : public JSONObject
|
||||
struct JSONBufferArray : public JSONObjectWithUniqueID
|
||||
{
|
||||
JSONBufferArray() {}
|
||||
JSONBufferArray(const osg::Array* array)
|
||||
{
|
||||
JSONVertexArray* b = new JSONVertexArray(array);
|
||||
@ -293,14 +256,29 @@ struct JSONBufferArray : public JSONObject
|
||||
|
||||
JSONObject* getDrawMode(GLenum mode);
|
||||
|
||||
struct JSONDrawArray : public JSONObject
|
||||
struct JSONDrawArray : public JSONObjectWithUniqueID
|
||||
{
|
||||
JSONDrawArray(osg::DrawArrays& array);
|
||||
JSONDrawArray(osg::DrawArrays& array)
|
||||
{
|
||||
getMaps()["First"] = new JSONValue<int>(array.getFirst());
|
||||
getMaps()["Count"] = new JSONValue<int>(array.getCount());
|
||||
getMaps()["Mode"] = getDrawMode(array.getMode());
|
||||
}
|
||||
};
|
||||
|
||||
struct JSONDrawArrayLengths : public JSONObject
|
||||
struct JSONDrawArrayLengths : public JSONObjectWithUniqueID
|
||||
{
|
||||
JSONDrawArrayLengths(osg::DrawArrayLengths& array);
|
||||
JSONDrawArrayLengths(osg::DrawArrayLengths& array)
|
||||
{
|
||||
getMaps()["First"] = new JSONValue<int>(array.getFirst());
|
||||
getMaps()["Mode"] = getDrawMode(array.getMode());
|
||||
|
||||
JSONArray* jsonArray = new JSONArray;
|
||||
for (unsigned int i = 0; i < array.size(); i++) {
|
||||
jsonArray->getArray().push_back(new JSONValue<int>(array[i]));
|
||||
}
|
||||
getMaps()["ArrayLengths"] = jsonArray;
|
||||
}
|
||||
|
||||
void setBufferName(const std::string& bufferName) {
|
||||
JSONObject::setBufferName(bufferName);
|
||||
@ -323,7 +301,7 @@ ADD_INDEX_BUFFER(osg::DrawElementsUByte, osg::UByteArray);
|
||||
|
||||
|
||||
template <class T>
|
||||
struct JSONDrawElements : public JSONObject
|
||||
struct JSONDrawElements : public JSONObjectWithUniqueID
|
||||
{
|
||||
JSONDrawElements(T& array) {
|
||||
typedef typename BufferArray<T>::type array_type;
|
||||
|
@ -19,6 +19,7 @@
|
||||
int JSONObjectBase::level = 0;
|
||||
unsigned int JSONObject::uniqueID = 0;
|
||||
|
||||
|
||||
std::string JSONObjectBase::indent()
|
||||
{
|
||||
std::string str;
|
||||
@ -41,34 +42,27 @@ void JSONMatrix::write(json_stream& str, WriteVisitor& visitor)
|
||||
}
|
||||
|
||||
|
||||
void JSONNode::write(json_stream& str, WriteVisitor& visitor)
|
||||
{
|
||||
std::vector<std::string> order;
|
||||
order.push_back("UniqueID");
|
||||
order.push_back("Name");
|
||||
order.push_back("TargetName");
|
||||
order.push_back("Matrix");
|
||||
order.push_back("UpdateCallbacks");
|
||||
order.push_back("StateSet");
|
||||
writeOrder(str, order, visitor);
|
||||
}
|
||||
|
||||
JSONObject::JSONObject(const unsigned int id, const std::string& bufferName)
|
||||
{
|
||||
_uniqueID = id;
|
||||
_bufferName = bufferName;
|
||||
_maps["UniqueID"] = new JSONValue<unsigned int>(id);
|
||||
}
|
||||
|
||||
JSONObject::JSONObject()
|
||||
{
|
||||
_uniqueID = 0xffffffff;
|
||||
}
|
||||
|
||||
void JSONObject::addUniqueID()
|
||||
{
|
||||
_uniqueID = JSONObject::uniqueID++;
|
||||
_maps["UniqueID"] = new JSONValue<unsigned int>(_uniqueID);
|
||||
if(_maps.find("UniqueID") == _maps.end()) {
|
||||
_maps["UniqueID"] = new JSONValue<unsigned int>(JSONObject::uniqueID ++);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int JSONObject::getUniqueID() const
|
||||
{
|
||||
JSONMap::const_iterator iterator = _maps.find("UniqueID");
|
||||
if(iterator == _maps.end()) {
|
||||
return 0xffffffff;
|
||||
}
|
||||
const JSONValue<unsigned int>* uid = dynamic_cast<JSONValue<unsigned int>*>(iterator->second.get());
|
||||
return uid->getValue();
|
||||
}
|
||||
|
||||
void JSONObject::addChild(const std::string& type, JSONObject* child)
|
||||
@ -267,16 +261,15 @@ static void writeEntry(json_stream& str, const std::string& key, JSONObject::JSO
|
||||
if (key.empty())
|
||||
return;
|
||||
|
||||
if ( map.find(key) != map.end() &&
|
||||
map[ key ].valid() ) {
|
||||
JSONObject::JSONMap::iterator keyValue = map.find(key);
|
||||
if ( keyValue != map.end() && keyValue->second.valid() ) {
|
||||
|
||||
str << JSONObjectBase::indent() << '"' << key << '"' << ": ";
|
||||
map[ key ]->write(str, visitor);
|
||||
map.erase(key);
|
||||
keyValue->second->write(str, visitor);
|
||||
map.erase(keyValue);
|
||||
|
||||
if (!map.empty()) {
|
||||
str << ", ";
|
||||
str << "\n";
|
||||
str << ",\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -359,7 +352,7 @@ void JSONVertexArray::write(json_stream& str, WriteVisitor& visitor)
|
||||
if (visitor._mergeAllBinaryFiles)
|
||||
url << bufferName;
|
||||
else
|
||||
url << basename << "_" << _uniqueID << ".bin";
|
||||
url << basename << "_" << getUniqueID() << ".bin";
|
||||
}
|
||||
|
||||
std::string type;
|
||||
@ -367,6 +360,20 @@ void JSONVertexArray::write(json_stream& str, WriteVisitor& visitor)
|
||||
osg::ref_ptr<const osg::Array> array = _arrayData;
|
||||
|
||||
switch (array->getType()) {
|
||||
case osg::Array::QuatArrayType:
|
||||
{
|
||||
osg::ref_ptr<osg::Vec4Array> converted = new osg::Vec4Array;
|
||||
converted->reserve(array->getNumElements());
|
||||
const osg::QuatArray* a = dynamic_cast<const osg::QuatArray*>(array.get());
|
||||
for (unsigned int i = 0; i < array->getNumElements(); ++i) {
|
||||
converted->push_back(osg::Vec4(static_cast<float>((*a)[i][0]),
|
||||
static_cast<float>((*a)[i][1]),
|
||||
static_cast<float>((*a)[i][2]),
|
||||
static_cast<float>((*a)[i][3])));
|
||||
}
|
||||
array = converted;
|
||||
type = "Float32Array";
|
||||
}
|
||||
case osg::Array::FloatArrayType:
|
||||
case osg::Array::Vec2ArrayType:
|
||||
case osg::Array::Vec3ArrayType:
|
||||
@ -456,6 +463,7 @@ void JSONVertexArray::write(json_stream& str, WriteVisitor& visitor)
|
||||
case osg::Array::Vec2dArrayType:
|
||||
case osg::Array::Vec3dArrayType:
|
||||
case osg::Array::Vec4dArrayType:
|
||||
case osg::Array::QuatArrayType:
|
||||
{
|
||||
const double* a = static_cast<const double*>(array->getDataPointer());
|
||||
unsigned int size = array->getNumElements() * array->getDataSize();
|
||||
@ -583,13 +591,6 @@ JSONVec4Array::JSONVec4Array(const osg::Vec4& v) : JSONVec3Array()
|
||||
}
|
||||
}
|
||||
|
||||
JSONVec5Array::JSONVec5Array(const Vec5& v) : JSONVec3Array()
|
||||
{
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
_array.push_back(new JSONValue<float>(v[i]));
|
||||
}
|
||||
}
|
||||
|
||||
JSONVec2Array::JSONVec2Array(const osg::Vec2& v) : JSONVec3Array()
|
||||
{
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
@ -619,26 +620,6 @@ void JSONVec3Array::write(json_stream& str,WriteVisitor& visitor)
|
||||
str << "]";
|
||||
}
|
||||
|
||||
void JSONKeyframes::write(json_stream& str,WriteVisitor& visitor)
|
||||
{
|
||||
JSONObjectBase::level++;
|
||||
str << "[" << std::endl << JSONObjectBase::indent();
|
||||
for (unsigned int i = 0; i < _array.size(); i++) {
|
||||
if (_array[i].valid()) {
|
||||
_array[i]->write(str, visitor);
|
||||
} else {
|
||||
str << "undefined";
|
||||
}
|
||||
if (i != _array.size() -1) {
|
||||
str << ",";
|
||||
str << "\n" << JSONObjectBase::indent();
|
||||
}
|
||||
}
|
||||
str << " ]";
|
||||
JSONObjectBase::level--;
|
||||
}
|
||||
|
||||
|
||||
void JSONArray::write(json_stream& str,WriteVisitor& visitor)
|
||||
{
|
||||
str << "[ ";
|
||||
@ -697,23 +678,3 @@ JSONObject* getDrawMode(GLenum mode)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
JSONDrawArray::JSONDrawArray(osg::DrawArrays& array)
|
||||
{
|
||||
getMaps()["First"] = new JSONValue<int>(array.getFirst());
|
||||
getMaps()["Count"] = new JSONValue<int>(array.getCount());
|
||||
getMaps()["Mode"] = getDrawMode(array.getMode());
|
||||
}
|
||||
|
||||
|
||||
JSONDrawArrayLengths::JSONDrawArrayLengths(osg::DrawArrayLengths& array)
|
||||
{
|
||||
getMaps()["First"] = new JSONValue<int>(array.getFirst());
|
||||
getMaps()["Mode"] = getDrawMode(array.getMode());
|
||||
|
||||
JSONArray* jsonArray = new JSONArray;
|
||||
for (unsigned int i = 0; i < array.size(); i++) {
|
||||
jsonArray->getArray().push_back(new JSONValue<int>(array[i]));
|
||||
}
|
||||
getMaps()["ArrayLengths"] = jsonArray;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
bool varint;
|
||||
bool strictJson;
|
||||
std::vector<std::string> useSpecificBuffer;
|
||||
|
||||
std::string baseLodURL;
|
||||
OptionsStruct() {
|
||||
resizeTextureUpToPowerOf2 = 0;
|
||||
useExternalBinaryArray = false;
|
||||
@ -69,7 +69,7 @@ public:
|
||||
supportsOption("mergeAllBinaryFiles","merge all binary files into one to avoid multi request on a server");
|
||||
supportsOption("inlineImages","insert base64 encoded images instead of referring to them");
|
||||
supportsOption("varint","Use varint encoding to serialize integer buffers");
|
||||
supportsOption("useSpecificBuffer=uservalue1,uservalue2","uses specific buffers for unshared buffers attached to geometries having a specified user value");
|
||||
supportsOption("useSpecificBuffer=userkey1[=uservalue1][:buffername1],userkey2[=uservalue2][:buffername2]","uses specific buffers for unshared buffers attached to geometries having a specified user key/value. Buffer name *may* be specificed after ':' and will be set to uservalue by default. If no value is set then only the existence of a uservalue with key string is performed.");
|
||||
supportsOption("disableCompactBuffer","keep source types and do not try to optimize buffers size");
|
||||
supportsOption("disableStrictJson","do not clean string (to utf8) or floating point (should be finite) values");
|
||||
}
|
||||
@ -85,6 +85,7 @@ public:
|
||||
std::string ext = osgDB::getFileExtension(fileName);
|
||||
if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
|
||||
|
||||
|
||||
OptionsStruct _options = parseOptions(options);
|
||||
json_stream fout(fileName, _options.strictJson);
|
||||
|
||||
@ -127,6 +128,7 @@ public:
|
||||
writer.inlineImages(options.inlineImages);
|
||||
writer.setMaxTextureDimension(options.resizeTextureUpToPowerOf2);
|
||||
writer.setVarint(options.varint);
|
||||
writer.setBaseLodURL(options.baseLodURL);
|
||||
for(std::vector<std::string>::const_iterator specificBuffer = options.useSpecificBuffer.begin() ;
|
||||
specificBuffer != options.useSpecificBuffer.end() ; ++ specificBuffer) {
|
||||
writer.addSpecificBuffer(*specificBuffer);
|
||||
@ -214,6 +216,11 @@ public:
|
||||
localOptions.useSpecificBuffer.push_back(post_equals.substr(start_pos,
|
||||
post_equals.length() - start_pos));
|
||||
}
|
||||
|
||||
}
|
||||
if (!options->getPluginStringData( std::string ("baseLodURL" )).empty())
|
||||
{
|
||||
localOptions.baseLodURL = options->getPluginStringData( std::string ("baseLodURL" ));
|
||||
}
|
||||
}
|
||||
return localOptions;
|
||||
|
@ -14,25 +14,37 @@
|
||||
#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 <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 7
|
||||
#define WRITER_VERSION 9
|
||||
|
||||
|
||||
osg::Array* getTangentSpaceArray(osg::Geometry& geometry);
|
||||
@ -46,18 +58,20 @@ class WriteVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
typedef std::vector<osg::ref_ptr<osg::StateSet> > StateSetStack;
|
||||
typedef std::pair<std::string, std::string> KeyValue;
|
||||
|
||||
std::map<osg::ref_ptr<osg::Object>, osg::ref_ptr<JSONObject> > _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;
|
||||
bool _varint;
|
||||
int _maxTextureDimension;
|
||||
std::vector<std::string> _specificBuffers;
|
||||
bool _varint;
|
||||
std::map<KeyValue, std::string> _specificBuffers;
|
||||
std::map<std::string, std::ofstream*> _buffers;
|
||||
|
||||
std::ofstream& getBufferFile(const std::string& name) {
|
||||
@ -67,13 +81,14 @@ public:
|
||||
return *_buffers[name];
|
||||
}
|
||||
|
||||
WriteVisitor(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {
|
||||
_mergeAllBinaryFiles = false;
|
||||
_useExternalBinaryArray = false;
|
||||
_inlineImages = false;
|
||||
_maxTextureDimension = 0;
|
||||
_varint = false;
|
||||
}
|
||||
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() ;
|
||||
@ -82,12 +97,20 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::string getBinaryFilename(const std::string& buffer = "") {
|
||||
std::string suffix;
|
||||
if(!buffer.empty()) {
|
||||
suffix = "_" + buffer;
|
||||
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 std::string(_baseName) + suffix + ".bin";
|
||||
return prefix + suffix + ".bin";
|
||||
}
|
||||
|
||||
void closeBuffers() {
|
||||
@ -97,9 +120,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int getBuffersSize() {
|
||||
unsigned int getBuffersSize() const {
|
||||
unsigned int size = 0;
|
||||
for(std::map<std::string, std::ofstream*>::iterator buffer = _buffers.begin() ;
|
||||
for(std::map<std::string, std::ofstream*>::const_iterator buffer = _buffers.begin() ;
|
||||
buffer != _buffers.end() ; ++ buffer) {
|
||||
size += buffer->second->tellp();
|
||||
}
|
||||
@ -130,12 +153,19 @@ public:
|
||||
throw "Error occur";
|
||||
}
|
||||
|
||||
void setBufferName(JSONObject *json, osg::Geometry* geometry) {
|
||||
void setBufferName(JSONObject *json, osg::Object* parent=0, osg::Object* object=0) const {
|
||||
if(!_mergeAllBinaryFiles || _specificBuffers.empty())
|
||||
return;
|
||||
std::string bufferName = getBufferName(geometry);
|
||||
|
||||
// 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()) {
|
||||
@ -148,39 +178,89 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::string getBufferName(osg::Geometry* geometry) {
|
||||
std::string name("");
|
||||
bool isSpecific = false;
|
||||
for(std::vector<std::string>::iterator it_flag = _specificBuffers.begin() ;
|
||||
it_flag != _specificBuffers.end() ; ++ it_flag) {
|
||||
if(geometry->getUserValue(*it_flag, isSpecific) && isSpecific) {
|
||||
name = *it_flag;
|
||||
break;
|
||||
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(name);
|
||||
return getBinaryFilename(flag);
|
||||
}
|
||||
|
||||
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::Geometry* geom = 0);
|
||||
JSONObject* createJSONDrawElements(osg::DrawArrays* drawArray, osg::Geometry* geom = 0);
|
||||
JSONObject* createJSONBufferArray(osg::Array* array, osg::Object* parent = 0);
|
||||
JSONObject* createJSONDrawElements(osg::DrawArrays* drawArray, osg::Object* parent = 0);
|
||||
|
||||
JSONObject* createJSONDrawElementsUInt(osg::DrawElementsUInt* de, osg::Geometry* geom = 0);
|
||||
JSONObject* createJSONDrawElementsUShort(osg::DrawElementsUShort* de, osg::Geometry* geom = 0);
|
||||
JSONObject* createJSONDrawElementsUByte(osg::DrawElementsUByte* de, osg::Geometry* geom = 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::Geometry* geom = 0);
|
||||
JSONObject* createJSONDrawArrayLengths(osg::DrawArrayLengths* drawArray, osg::Geometry* geom = 0);
|
||||
JSONObject* createJSONDrawArray(osg::DrawArrays* drawArray, osg::Object* parent = 0);
|
||||
JSONObject* createJSONDrawArrayLengths(osg::DrawArrayLengths* drawArray, osg::Object* parent = 0);
|
||||
|
||||
JSONObject* createJSONGeometry(osg::Geometry* geom);
|
||||
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()) {
|
||||
@ -214,39 +294,69 @@ public:
|
||||
osg::ref_ptr<JSONArray> updateCallbacks = new JSONArray;
|
||||
osg::ref_ptr<osg::Callback> nc = node.getUpdateCallback();
|
||||
while (nc) {
|
||||
osgAnimation::BasicAnimationManager* am = dynamic_cast<osgAnimation::BasicAnimationManager*>(nc.get());
|
||||
if (am) {
|
||||
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++) {
|
||||
osg::ref_ptr<JSONObject> jsonAnim = createJSONAnimation(am->getAnimationList()[i].get());
|
||||
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);
|
||||
//std::stringstream ss;
|
||||
//jsonAnim->write(ss);
|
||||
//std::cout << ss.str() << std::endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
osgAnimation::UpdateMatrixTransform* updateMT = dynamic_cast<osgAnimation::UpdateMatrixTransform*>(nc.get());
|
||||
if (updateMT) {
|
||||
osg::ref_ptr<JSONObject> jsonCallback = createJSONUpdateMatrixTransform(*updateMT);
|
||||
if (jsonCallback.valid()) {
|
||||
osg::ref_ptr<JSONObject> jsonObject = new JSONObject;
|
||||
jsonObject->getMaps()["osgAnimation.UpdateMatrixTransform"] = jsonCallback;
|
||||
updateCallbacks->getArray().push_back(jsonObject);
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
@ -255,13 +365,28 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void apply(osg::Drawable& drw) {
|
||||
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(&drw);
|
||||
if (geom) {
|
||||
JSONObject* json = createJSONGeometry(geom);
|
||||
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) {
|
||||
@ -273,7 +398,6 @@ public:
|
||||
}
|
||||
|
||||
osg::ref_ptr<JSONObject> json = new JSONNode;
|
||||
json->addUniqueID();
|
||||
_maps[&node] = json;
|
||||
|
||||
applyCallback(node, json.get());
|
||||
@ -298,7 +422,6 @@ public:
|
||||
}
|
||||
|
||||
osg::ref_ptr<JSONObject> json = new JSONNode;
|
||||
json->addUniqueID();
|
||||
_maps[&node] = json;
|
||||
parent->addChild("osg.Node", json.get());
|
||||
|
||||
@ -346,7 +469,6 @@ public:
|
||||
}
|
||||
|
||||
osg::ref_ptr<JSONObject> json = new JSONNode;
|
||||
json->addUniqueID();
|
||||
_maps[&node] = json;
|
||||
|
||||
applyCallback(node, json.get());
|
||||
@ -375,7 +497,6 @@ public:
|
||||
}
|
||||
|
||||
osg::ref_ptr<JSONObject> json = new JSONNode;
|
||||
json->addUniqueID();
|
||||
_maps[&node] = json;
|
||||
|
||||
applyCallback(node, json.get());
|
||||
@ -390,15 +511,54 @@ public:
|
||||
_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;
|
||||
json->addUniqueID();
|
||||
_maps[&node] = json;
|
||||
|
||||
applyCallback(node, json.get());
|
||||
@ -408,6 +568,58 @@ public:
|
||||
|
||||
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);
|
||||
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();
|
||||
@ -422,7 +634,6 @@ public:
|
||||
}
|
||||
|
||||
osg::ref_ptr<JSONObject> json = new JSONNode;
|
||||
json->addUniqueID();
|
||||
_maps[&node] = json;
|
||||
|
||||
applyCallback(node, json.get());
|
||||
@ -445,7 +656,37 @@ public:
|
||||
void inlineImages(bool use) { _inlineImages = use; }
|
||||
void setVarint(bool use) { _varint = use; }
|
||||
void setMaxTextureDimension(int use) { _maxTextureDimension = use; }
|
||||
void addSpecificBuffer(const std::string& bufferFlag) { _specificBuffers.push_back(bufferFlag); }
|
||||
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
|
||||
|
@ -10,10 +10,14 @@
|
||||
#include <osg/Types>
|
||||
#include <osg/Material>
|
||||
#include <osg/BlendFunc>
|
||||
|
||||
#include <osgSim/ShapeAttribute>
|
||||
|
||||
#include "Base64"
|
||||
#include <osgText/Text>
|
||||
|
||||
#include <osgAnimation/MorphGeometry>
|
||||
|
||||
#include "Base64"
|
||||
|
||||
|
||||
osg::Array* getTangentSpaceArray(osg::Geometry& geometry) {
|
||||
@ -27,6 +31,51 @@ osg::Array* getTangentSpaceArray(osg::Geometry& geometry) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
osg::Array* getAnimationBonesArray(osgAnimation::RigGeometry& rigGeometry) {
|
||||
for(unsigned int i = 0 ; i < rigGeometry.getNumVertexAttribArrays() ; ++ i) {
|
||||
osg::Array* attribute = rigGeometry.getVertexAttribArray(i);
|
||||
bool isBones = false;
|
||||
if(attribute && attribute->getUserValue("bones", isBones) && isBones) {
|
||||
return attribute;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
osg::Array* getAnimationWeightsArray(osgAnimation::RigGeometry& rigGeometry) {
|
||||
for(unsigned int i = 0 ; i < rigGeometry.getNumVertexAttribArrays() ; ++ i) {
|
||||
osg::Array* attribute = rigGeometry.getVertexAttribArray(i);
|
||||
bool isWeights = false;
|
||||
if(attribute && attribute->getUserValue("weights", isWeights) && isWeights) {
|
||||
return attribute;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
osg::ref_ptr<JSONObject> buildRigBoneMap(osgAnimation::RigGeometry& rigGeometry) {
|
||||
osg::Array* bones = getAnimationBonesArray(rigGeometry);
|
||||
osg::ref_ptr<JSONObject> boneMap = new JSONObject;
|
||||
|
||||
unsigned int paletteIndex = 0;
|
||||
while(true) {
|
||||
std::ostringstream oss;
|
||||
oss << "animationBone_" << paletteIndex;
|
||||
std::string boneName, palette = oss.str();
|
||||
if(!bones->getUserValue(palette, boneName)) {
|
||||
break;
|
||||
}
|
||||
boneMap->getMaps()[boneName] = new JSONValue<int>(paletteIndex);
|
||||
++ paletteIndex;
|
||||
}
|
||||
|
||||
return boneMap;
|
||||
}
|
||||
|
||||
|
||||
void translateObject(JSONObject* json, osg::Object* osg)
|
||||
{
|
||||
if (!osg->getName().empty()) {
|
||||
@ -150,6 +199,7 @@ static JSONValue<std::string>* getBlendFuncMode(GLenum mode) {
|
||||
default:
|
||||
return new JSONValue<std::string>("ONE");
|
||||
}
|
||||
return new JSONValue<std::string>("ONE");
|
||||
}
|
||||
|
||||
static JSONValue<std::string>* getJSONFilterMode(osg::Texture::FilterMode mode)
|
||||
@ -194,6 +244,44 @@ static JSONValue<std::string>* getJSONWrapMode(osg::Texture::WrapMode mode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static JSONValue<std::string>* getJSONAlignmentType(osgText::Text::AlignmentType type)
|
||||
{
|
||||
switch(type) {
|
||||
case osgText::Text::LEFT_TOP:
|
||||
return new JSONValue<std::string>("LEFT_TOP");
|
||||
case osgText::Text::LEFT_CENTER:
|
||||
return new JSONValue<std::string>("LEFT_CENTER");
|
||||
case osgText::Text::LEFT_BOTTOM:
|
||||
return new JSONValue<std::string>("LEFT_BOTTOM");
|
||||
case osgText::Text::CENTER_TOP:
|
||||
return new JSONValue<std::string>("CENTER_TOP");
|
||||
case osgText::Text::CENTER_CENTER:
|
||||
return new JSONValue<std::string>("CENTER_CENTER");
|
||||
case osgText::Text::CENTER_BOTTOM:
|
||||
return new JSONValue<std::string>("CENTER_BOTTOM");
|
||||
case osgText::Text::RIGHT_TOP:
|
||||
return new JSONValue<std::string>("RIGHT_TOP");
|
||||
case osgText::Text::RIGHT_CENTER:
|
||||
return new JSONValue<std::string>("RIGHT_CENTER");
|
||||
case osgText::Text::RIGHT_BOTTOM:
|
||||
return new JSONValue<std::string>("RIGHT_BOTTOM");
|
||||
case osgText::Text::LEFT_BASE_LINE:
|
||||
return new JSONValue<std::string>("LEFT_BASE_LINE");
|
||||
case osgText::Text::CENTER_BASE_LINE:
|
||||
return new JSONValue<std::string>("CENTER_BASE_LINE");
|
||||
case osgText::Text::RIGHT_BASE_LINE:
|
||||
return new JSONValue<std::string>("RIGHT_BASE_LINE");
|
||||
case osgText::Text::LEFT_BOTTOM_BASE_LINE:
|
||||
return new JSONValue<std::string>("LEFT_BOTTOM_BASE_LINE");
|
||||
case osgText::Text::CENTER_BOTTOM_BASE_LINE:
|
||||
return new JSONValue<std::string>("CENTER_BOTTOM_BASE_LINE");
|
||||
case osgText::Text::RIGHT_BOTTOM_BASE_LINE:
|
||||
return new JSONValue<std::string>("RIGHT_BOTTOM_BASE_LINE");
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
JSONObject* createImage(osg::Image* image, bool inlineImages, int maxTextureDimension, const std::string &baseName)
|
||||
{
|
||||
@ -224,7 +312,8 @@ JSONObject* createImage(osg::Image* image, bool inlineImages, int maxTextureDime
|
||||
} else {
|
||||
// no image file so use this inline name image and create a file
|
||||
std::stringstream ss;
|
||||
ss << osgDB::getFilePath(baseName) << osgDB::getNativePathSeparator();
|
||||
if ( !osgDB::getFilePath(baseName).empty())
|
||||
ss << osgDB::getFilePath(baseName) << osgDB::getNativePathSeparator();
|
||||
ss << (int64_t)image << ".inline_conv_generated.png"; // write the pointer location
|
||||
std::string filename = ss.str();
|
||||
if (osgDB::writeImageFile(*image, filename)) {
|
||||
@ -235,9 +324,18 @@ JSONObject* createImage(osg::Image* image, bool inlineImages, int maxTextureDime
|
||||
if (!image->getFileName().empty()) { // means that everything went ok
|
||||
if (inlineImages) {
|
||||
|
||||
std::ifstream in(osgDB::findDataFile(image->getFileName()).c_str());
|
||||
if (in.is_open())
|
||||
std::ifstream in(osgDB::findDataFile(image->getFileName()).c_str(), std::ifstream::in | std::ifstream::binary);
|
||||
if (in.is_open() && in.good())
|
||||
{
|
||||
// read file first to iterate
|
||||
in.seekg(0, std::ifstream::end);
|
||||
const std::ifstream::pos_type size = in.tellg();
|
||||
in.seekg(0, std::ifstream::beg);
|
||||
std::vector<unsigned char> rawData;
|
||||
rawData.resize(size);
|
||||
in.read(reinterpret_cast<char*>(rawData.data()),size);
|
||||
in.seekg(std::ios_base::beg);
|
||||
|
||||
std::stringstream out;
|
||||
out << "data:image/" << osgDB::getLowerCaseFileExtension(image->getFileName()) << ";base64,";
|
||||
base64::encode(std::istreambuf_iterator<char>(in),
|
||||
@ -255,64 +353,60 @@ JSONObject* createImage(osg::Image* image, bool inlineImages, int maxTextureDime
|
||||
}
|
||||
|
||||
|
||||
JSONObject* WriteVisitor::createJSONBufferArray(osg::Array* array, osg::Geometry* geom)
|
||||
JSONObject* WriteVisitor::createJSONBufferArray(osg::Array* array, osg::Object* parent)
|
||||
{
|
||||
if (_maps.find(array) != _maps.end())
|
||||
return _maps[array]->getShadowObject();
|
||||
|
||||
osg::ref_ptr<JSONBufferArray> json = new JSONBufferArray(array);
|
||||
json->addUniqueID();
|
||||
_maps[array] = json;
|
||||
if(geom && _mergeAllBinaryFiles) {
|
||||
setBufferName(json.get(), geom);
|
||||
if(_mergeAllBinaryFiles) {
|
||||
setBufferName(json.get(), parent, array);
|
||||
}
|
||||
return json.get();
|
||||
}
|
||||
|
||||
JSONObject* WriteVisitor::createJSONDrawElementsUInt(osg::DrawElementsUInt* de, osg::Geometry* geom)
|
||||
JSONObject* WriteVisitor::createJSONDrawElementsUInt(osg::DrawElementsUInt* de, osg::Object* parent)
|
||||
{
|
||||
if (_maps.find(de) != _maps.end())
|
||||
return _maps[de]->getShadowObject();
|
||||
|
||||
JSONDrawElements<osg::DrawElementsUInt>* json = new JSONDrawElements<osg::DrawElementsUInt>(*de);
|
||||
json->addUniqueID();
|
||||
_maps[de] = json;
|
||||
if(geom && _mergeAllBinaryFiles) {
|
||||
setBufferName(json, geom);
|
||||
if(_mergeAllBinaryFiles) {
|
||||
setBufferName(json, parent, de);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
JSONObject* WriteVisitor::createJSONDrawElementsUShort(osg::DrawElementsUShort* de, osg::Geometry* geom)
|
||||
JSONObject* WriteVisitor::createJSONDrawElementsUShort(osg::DrawElementsUShort* de, osg::Object* parent)
|
||||
{
|
||||
if (_maps.find(de) != _maps.end())
|
||||
return _maps[de]->getShadowObject();
|
||||
|
||||
JSONDrawElements<osg::DrawElementsUShort>* json = new JSONDrawElements<osg::DrawElementsUShort>(*de);
|
||||
json->addUniqueID();
|
||||
_maps[de] = json;
|
||||
if(geom && _mergeAllBinaryFiles) {
|
||||
setBufferName(json, geom);
|
||||
if(_mergeAllBinaryFiles) {
|
||||
setBufferName(json, parent, de);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
JSONObject* WriteVisitor::createJSONDrawElementsUByte(osg::DrawElementsUByte* de, osg::Geometry* geom)
|
||||
JSONObject* WriteVisitor::createJSONDrawElementsUByte(osg::DrawElementsUByte* de, osg::Object* parent)
|
||||
{
|
||||
if (_maps.find(de) != _maps.end())
|
||||
return _maps[de]->getShadowObject();
|
||||
|
||||
JSONDrawElements<osg::DrawElementsUByte>* json = new JSONDrawElements<osg::DrawElementsUByte>(*de);
|
||||
json->addUniqueID();
|
||||
_maps[de] = json;
|
||||
if(geom && _mergeAllBinaryFiles) {
|
||||
setBufferName(json, geom);
|
||||
if(_mergeAllBinaryFiles) {
|
||||
setBufferName(json, parent, de);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
// use to convert draw array quads to draw elements triangles
|
||||
JSONObject* WriteVisitor::createJSONDrawElements(osg::DrawArrays* drawArray, osg::Geometry* geom)
|
||||
JSONObject* WriteVisitor::createJSONDrawElements(osg::DrawArrays* drawArray, osg::Object* parent)
|
||||
{
|
||||
if (_maps.find(drawArray) != _maps.end())
|
||||
return _maps[drawArray]->getShadowObject();
|
||||
@ -335,79 +429,77 @@ JSONObject* WriteVisitor::createJSONDrawElements(osg::DrawArrays* drawArray, osg
|
||||
de->push_back(base + 3);
|
||||
}
|
||||
JSONDrawElements<osg::DrawElementsUShort>* json = new JSONDrawElements<osg::DrawElementsUShort>(*de);
|
||||
json->addUniqueID();
|
||||
_maps[drawArray] = json;
|
||||
if(geom && _mergeAllBinaryFiles) {
|
||||
setBufferName(json, geom);
|
||||
if(_mergeAllBinaryFiles) {
|
||||
setBufferName(json, parent, drawArray);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
JSONObject* WriteVisitor::createJSONDrawArray(osg::DrawArrays* da, osg::Geometry* geom)
|
||||
JSONObject* WriteVisitor::createJSONDrawArray(osg::DrawArrays* da, osg::Object* parent)
|
||||
{
|
||||
if (_maps.find(da) != _maps.end())
|
||||
return _maps[da]->getShadowObject();
|
||||
|
||||
osg::ref_ptr<JSONDrawArray> json = new JSONDrawArray(*da);
|
||||
json->addUniqueID();
|
||||
_maps[da] = json;
|
||||
if(geom && _mergeAllBinaryFiles) {
|
||||
setBufferName(json.get(), geom);
|
||||
if(_mergeAllBinaryFiles) {
|
||||
setBufferName(json.get(), parent, da);
|
||||
}
|
||||
return json.get();
|
||||
}
|
||||
|
||||
JSONObject* WriteVisitor::createJSONDrawArrayLengths(osg::DrawArrayLengths* da, osg::Geometry* geom)
|
||||
JSONObject* WriteVisitor::createJSONDrawArrayLengths(osg::DrawArrayLengths* da, osg::Object* parent)
|
||||
{
|
||||
if (_maps.find(da) != _maps.end())
|
||||
return _maps[da]->getShadowObject();
|
||||
|
||||
osg::ref_ptr<JSONDrawArrayLengths> json = new JSONDrawArrayLengths(*da);
|
||||
json->addUniqueID();
|
||||
_maps[da] = json;
|
||||
if(geom && _mergeAllBinaryFiles) {
|
||||
setBufferName(json.get(), geom);
|
||||
if(_mergeAllBinaryFiles) {
|
||||
setBufferName(json.get(), parent, da);
|
||||
}
|
||||
return json.get();
|
||||
}
|
||||
|
||||
|
||||
JSONObject* WriteVisitor::createJSONGeometry(osg::Geometry* geom)
|
||||
JSONObject* WriteVisitor::createJSONGeometry(osg::Geometry* geometry, osg::Object* parent)
|
||||
{
|
||||
if (_maps.find(geom) != _maps.end())
|
||||
return _maps[geom]->getShadowObject();
|
||||
if(!parent) {
|
||||
parent = geometry;
|
||||
}
|
||||
|
||||
//if (needToSplit(*geom))
|
||||
// error();
|
||||
if (_maps.find(geometry) != _maps.end())
|
||||
return _maps[geometry]->getShadowObject();
|
||||
|
||||
osg::ref_ptr<JSONObject> json = new JSONNode;
|
||||
osg::ref_ptr<JSONObject> json = new JSONObject;
|
||||
json->addUniqueID();
|
||||
_maps[geom] = json;
|
||||
_maps[geometry] = json;
|
||||
|
||||
if (geom->getStateSet())
|
||||
createJSONStateSet(json.get(), geom->getStateSet());
|
||||
if (geometry->getStateSet())
|
||||
createJSONStateSet(json.get(), geometry->getStateSet());
|
||||
|
||||
translateObject(json.get(), geom);
|
||||
translateObject(json.get(), geometry);
|
||||
|
||||
osg::ref_ptr<JSONObject> attributes = new JSONObject;
|
||||
|
||||
int nbVertexes = 0;
|
||||
|
||||
if (geom->getVertexArray()) {
|
||||
nbVertexes = geom->getVertexArray()->getNumElements();
|
||||
attributes->getMaps()["Vertex"] = createJSONBufferArray(geom->getVertexArray(), geom);
|
||||
if (geometry->getVertexArray()) {
|
||||
nbVertexes = geometry->getVertexArray()->getNumElements();
|
||||
attributes->getMaps()["Vertex"] = createJSONBufferArray(geometry->getVertexArray(), parent);
|
||||
}
|
||||
if (geom->getNormalArray()) {
|
||||
attributes->getMaps()["Normal"] = createJSONBufferArray(geom->getNormalArray(), geom);
|
||||
int nb = geom->getNormalArray()->getNumElements();
|
||||
if (geometry->getNormalArray()) {
|
||||
attributes->getMaps()["Normal"] = createJSONBufferArray(geometry->getNormalArray(), parent);
|
||||
int nb = geometry->getNormalArray()->getNumElements();
|
||||
if (nbVertexes != nb) {
|
||||
osg::notify(osg::FATAL) << "Fatal nb normals " << nb << " != " << nbVertexes << std::endl;
|
||||
error();
|
||||
}
|
||||
}
|
||||
if (geom->getColorArray()) {
|
||||
attributes->getMaps()["Color"] = createJSONBufferArray(geom->getColorArray(), geom);
|
||||
int nb = geom->getColorArray()->getNumElements();
|
||||
if (geometry->getColorArray()) {
|
||||
attributes->getMaps()["Color"] = createJSONBufferArray(geometry->getColorArray(), parent);
|
||||
int nb = geometry->getColorArray()->getNumElements();
|
||||
if (nbVertexes != nb) {
|
||||
osg::notify(osg::FATAL) << "Fatal nb colors " << nb << " != " << nbVertexes << std::endl;
|
||||
error();
|
||||
@ -419,9 +511,9 @@ JSONObject* WriteVisitor::createJSONGeometry(osg::Geometry* geom)
|
||||
ss.str("");
|
||||
ss << "TexCoord" << i;
|
||||
//osg::notify(osg::NOTICE) << ss.str() << std::endl;
|
||||
if (geom->getTexCoordArray(i)) {
|
||||
attributes->getMaps()[ss.str()] = createJSONBufferArray(geom->getTexCoordArray(i), geom);
|
||||
int nb = geom->getTexCoordArray(i)->getNumElements();
|
||||
if (geometry->getTexCoordArray(i)) {
|
||||
attributes->getMaps()[ss.str()] = createJSONBufferArray(geometry->getTexCoordArray(i), parent);
|
||||
int nb = geometry->getTexCoordArray(i)->getNumElements();
|
||||
if (nbVertexes != nb) {
|
||||
osg::notify(osg::FATAL) << "Fatal nb tex coord " << i << " " << nb << " != " << nbVertexes << std::endl;
|
||||
error();
|
||||
@ -429,9 +521,9 @@ JSONObject* WriteVisitor::createJSONGeometry(osg::Geometry* geom)
|
||||
}
|
||||
}
|
||||
|
||||
osg::Array* tangents = getTangentSpaceArray(*geom);
|
||||
osg::Array* tangents = getTangentSpaceArray(*geometry);
|
||||
if (tangents) {
|
||||
attributes->getMaps()["Tangent"] = createJSONBufferArray(tangents, geom);
|
||||
attributes->getMaps()["Tangent"] = createJSONBufferArray(tangents, parent);
|
||||
int nb = tangents->getNumElements();
|
||||
if (nbVertexes != nb) {
|
||||
osg::notify(osg::FATAL) << "Fatal nb tangent " << nb << " != " << nbVertexes << std::endl;
|
||||
@ -441,11 +533,11 @@ JSONObject* WriteVisitor::createJSONGeometry(osg::Geometry* geom)
|
||||
|
||||
json->getMaps()["VertexAttributeList"] = attributes;
|
||||
|
||||
if (!geom->getPrimitiveSetList().empty()) {
|
||||
if (!geometry->getPrimitiveSetList().empty()) {
|
||||
osg::ref_ptr<JSONArray> primitives = new JSONArray();
|
||||
for (unsigned int i = 0; i < geom->getNumPrimitiveSets(); ++i) {
|
||||
for (unsigned int i = 0; i < geometry->getNumPrimitiveSets(); ++i) {
|
||||
osg::ref_ptr<JSONObject> obj = new JSONObject;
|
||||
osg::PrimitiveSet* primitive = geom->getPrimitiveSet(i);
|
||||
osg::PrimitiveSet* primitive = geometry->getPrimitiveSet(i);
|
||||
if(!primitive) continue;
|
||||
|
||||
if (primitive->getType() == osg::PrimitiveSet::DrawArraysPrimitiveType) {
|
||||
@ -454,9 +546,9 @@ JSONObject* WriteVisitor::createJSONGeometry(osg::Geometry* geom)
|
||||
{
|
||||
primitives->getArray().push_back(obj);
|
||||
if (da->getMode() == GL_QUADS) {
|
||||
obj->getMaps()["DrawElementsUShort"] = createJSONDrawElements(da, geom);
|
||||
obj->getMaps()["DrawElementsUShort"] = createJSONDrawElements(da, parent);
|
||||
} else {
|
||||
obj->getMaps()["DrawArrays"] = createJSONDrawArray(da, geom);
|
||||
obj->getMaps()["DrawArrays"] = createJSONDrawArray(da, parent);
|
||||
}
|
||||
}
|
||||
} else if (primitive->getType() == osg::PrimitiveSet::DrawElementsUIntPrimitiveType) {
|
||||
@ -464,40 +556,114 @@ JSONObject* WriteVisitor::createJSONGeometry(osg::Geometry* geom)
|
||||
if (da)
|
||||
{
|
||||
primitives->getArray().push_back(obj);
|
||||
obj->getMaps()["DrawElementsUInt"] = createJSONDrawElementsUInt(da, geom);
|
||||
obj->getMaps()["DrawElementsUInt"] = createJSONDrawElementsUInt(da, parent);
|
||||
}
|
||||
|
||||
} else if (primitive->getType() == osg::PrimitiveSet::DrawElementsUShortPrimitiveType) {
|
||||
osg::DrawElementsUShort* da = dynamic_cast<osg::DrawElementsUShort*>((primitive));
|
||||
if (da)
|
||||
{
|
||||
primitives->getArray().push_back(obj);
|
||||
obj->getMaps()["DrawElementsUShort"] = createJSONDrawElementsUShort(da, geom);
|
||||
obj->getMaps()["DrawElementsUShort"] = createJSONDrawElementsUShort(da, parent);
|
||||
}
|
||||
} else if (primitive->getType() == osg::PrimitiveSet::DrawElementsUBytePrimitiveType) {
|
||||
osg::DrawElementsUByte* da = dynamic_cast<osg::DrawElementsUByte*>((primitive));
|
||||
if (da)
|
||||
{
|
||||
primitives->getArray().push_back(obj);
|
||||
obj->getMaps()["DrawElementsUByte"] = createJSONDrawElementsUByte(da, geom);
|
||||
obj->getMaps()["DrawElementsUByte"] = createJSONDrawElementsUByte(da, parent);
|
||||
}
|
||||
|
||||
} else if (primitive->getType() == osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) {
|
||||
osg::DrawArrayLengths* dal = dynamic_cast<osg::DrawArrayLengths*>((primitive));
|
||||
if (dal)
|
||||
{
|
||||
primitives->getArray().push_back(obj);
|
||||
obj->getMaps()["DrawArrayLengths"] = createJSONDrawArrayLengths(dal, geom);
|
||||
obj->getMaps()["DrawArrayLengths"] = createJSONDrawArrayLengths(dal, parent);
|
||||
}
|
||||
} else {
|
||||
osg::notify(osg::WARN) << "Primitive Type " << geom->getPrimitiveSetList()[i]->getType() << " not supported, skipping" << std::endl;
|
||||
osg::notify(osg::WARN) << "Primitive Type " << geometry->getPrimitiveSetList()[i]->getType() << " not supported, skipping" << std::endl;
|
||||
}
|
||||
}
|
||||
json->getMaps()["PrimitiveSetList"] = primitives;
|
||||
}
|
||||
if (geometry->getComputeBoundingBoxCallback()) {
|
||||
osg::ref_ptr<JSONObject> jsonObj = new JSONObject;
|
||||
jsonObj->addUniqueID();
|
||||
json->getMaps()["osg.ComputeBoundingBoxCallback"] = jsonObj;
|
||||
}
|
||||
return json.get();
|
||||
}
|
||||
|
||||
JSONObject* WriteVisitor::createJSONRigGeometry(osgAnimation::RigGeometry* rigGeometry)
|
||||
{
|
||||
//TODO : Convert data to JSONVertexArray "Float32Array"
|
||||
osg::ref_ptr<JSONObject> json = new JSONObject;
|
||||
json->addUniqueID();
|
||||
osg::ref_ptr<JSONObject> sourceGeometry = new JSONObject;
|
||||
|
||||
if(osgAnimation::MorphGeometry *morphGeometry = dynamic_cast<osgAnimation::MorphGeometry*>(rigGeometry->getSourceGeometry())) {
|
||||
sourceGeometry->getMaps()["osgAnimation.MorphGeometry"] = createJSONMorphGeometry(morphGeometry, rigGeometry);
|
||||
}
|
||||
else {
|
||||
osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(rigGeometry->getSourceGeometry());
|
||||
if(geometry) {
|
||||
sourceGeometry->getMaps()["osg.Geometry"] = createJSONGeometry(geometry, rigGeometry);
|
||||
}
|
||||
}
|
||||
|
||||
json->getMaps()["SourceGeometry"] = sourceGeometry.get();
|
||||
|
||||
osg::Array* bones = getAnimationBonesArray(*rigGeometry);
|
||||
osg::Array* weights = getAnimationWeightsArray(*rigGeometry);
|
||||
if (bones && weights) {
|
||||
json->getMaps()["BoneMap"] = buildRigBoneMap(*rigGeometry);
|
||||
|
||||
json->getMaps()["VertexAttributeList"] = new JSONObject;
|
||||
osg::ref_ptr<JSONObject> attributes = json->getMaps()["VertexAttributeList"];
|
||||
int nbVertexes = rigGeometry->getSourceGeometry()->getVertexArray()->getNumElements();
|
||||
|
||||
attributes->getMaps()["Bones"] = createJSONBufferArray(bones, rigGeometry);
|
||||
attributes->getMaps()["Weights"] = createJSONBufferArray(weights, rigGeometry);
|
||||
int nb = bones->getNumElements();
|
||||
if (nbVertexes != nb) {
|
||||
osg::notify(osg::FATAL) << "Fatal nb bones " << nb << " != " << nbVertexes << std::endl;
|
||||
error();
|
||||
}
|
||||
nb = weights->getNumElements();
|
||||
if (nbVertexes != nb) {
|
||||
osg::notify(osg::FATAL) << "Fatal nb weights " << nb << " != " << nbVertexes << std::endl;
|
||||
error();
|
||||
}
|
||||
}
|
||||
|
||||
return json.release();
|
||||
}
|
||||
|
||||
JSONObject* WriteVisitor::createJSONMorphGeometry(osgAnimation::MorphGeometry* morphGeometry, osg::Object* parent)
|
||||
{
|
||||
if(!parent) {
|
||||
parent = morphGeometry;
|
||||
}
|
||||
|
||||
JSONObject* jsonGeometry = createJSONGeometry(morphGeometry, parent);
|
||||
JSONArray* targetList = new JSONArray;
|
||||
|
||||
osgAnimation::MorphGeometry::MorphTargetList mTargetList = morphGeometry->getMorphTargetList();
|
||||
typedef osgAnimation::MorphGeometry::MorphTargetList::iterator TargetIterator;
|
||||
|
||||
for(TargetIterator ti = mTargetList.begin(); ti != mTargetList.end(); ti++) {
|
||||
osgAnimation::MorphGeometry::MorphTarget *morphTarget = &(*ti);
|
||||
JSONObject *jsonGeometryObject = new JSONObject;
|
||||
if(osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(morphTarget->getGeometry())) {
|
||||
geometry->setPrimitiveSetList(osg::Geometry::PrimitiveSetList()); //delete unused drawArray
|
||||
jsonGeometryObject->getMaps()["osg.Geometry"] = createJSONGeometry(geometry);
|
||||
targetList->asArray()->getArray().push_back(jsonGeometryObject);
|
||||
}
|
||||
}
|
||||
jsonGeometry->getMaps()["MorphTargets"] = targetList;
|
||||
|
||||
return jsonGeometry;
|
||||
}
|
||||
|
||||
JSONObject* WriteVisitor::createJSONBlendFunc(osg::BlendFunc* sa)
|
||||
{
|
||||
if (_maps.find(sa) != _maps.end())
|
||||
@ -544,7 +710,7 @@ JSONObject* WriteVisitor::createJSONCullFace(osg::CullFace* sa)
|
||||
|
||||
osg::ref_ptr<JSONValue<std::string> > mode = new JSONValue<std::string>("BACK");
|
||||
if (sa->getMode() == osg::CullFace::FRONT) {
|
||||
mode = new JSONValue<std::string>("BACK");
|
||||
mode = new JSONValue<std::string>("FRONT");
|
||||
}
|
||||
if (sa->getMode() == osg::CullFace::FRONT_AND_BACK) {
|
||||
mode = new JSONValue<std::string>("FRONT_AND_BACK");
|
||||
@ -555,14 +721,12 @@ JSONObject* WriteVisitor::createJSONCullFace(osg::CullFace* sa)
|
||||
|
||||
|
||||
|
||||
|
||||
JSONObject* WriteVisitor::createJSONMaterial(osg::Material* material)
|
||||
{
|
||||
if (_maps.find(material) != _maps.end())
|
||||
return _maps[material]->getShadowObject();
|
||||
|
||||
osg::ref_ptr<JSONObject> jsonMaterial = new JSONMaterial;
|
||||
jsonMaterial->addUniqueID();
|
||||
_maps[material] = jsonMaterial;
|
||||
|
||||
translateObject(jsonMaterial.get(), material);
|
||||
@ -583,7 +747,6 @@ JSONObject* WriteVisitor::createJSONLight(osg::Light* light)
|
||||
return _maps[light]->getShadowObject();
|
||||
|
||||
osg::ref_ptr<JSONObject> jsonLight = new JSONLight;
|
||||
jsonLight->addUniqueID();
|
||||
_maps[light] = jsonLight;
|
||||
|
||||
translateObject(jsonLight.get(), light);
|
||||
@ -617,6 +780,33 @@ template <class T> JSONObject* createImageFromTexture(osg::Texture* texture, JSO
|
||||
return 0;
|
||||
}
|
||||
|
||||
JSONObject* WriteVisitor::createJSONText(osgText::Text* text)
|
||||
{
|
||||
if (_maps.find(text) != _maps.end())
|
||||
return _maps[text]->getShadowObject();
|
||||
|
||||
osg::ref_ptr<JSONObject> jsonText = new JSONObject;
|
||||
jsonText->addUniqueID();
|
||||
_maps[text] = jsonText;
|
||||
jsonText->getMaps()["Text"] = new JSONValue<std::string>( text->getText().createUTF8EncodedString() );
|
||||
jsonText->getMaps()["Position"] = new JSONVec3Array(text->getPosition());
|
||||
jsonText->getMaps()["Color"] = new JSONVec4Array(osg::Vec4(text->getColor().x(),text->getColor().y(),text->getColor().z(), text->getColor().w() ));
|
||||
jsonText->getMaps()["CharacterSize"] = new JSONValue<float>(text->getCharacterHeight() );
|
||||
jsonText->getMaps()["AutoRotateToScreen"] = new JSONValue<int>(text->getAutoRotateToScreen() );
|
||||
jsonText->getMaps()["Alignment"] = getJSONAlignmentType(text->getAlignment());
|
||||
|
||||
osg::ref_ptr<JSONValue<std::string> > layout = new JSONValue<std::string>("LEFT_TO_RIGHT");
|
||||
if (text->getLayout() == osgText::Text::RIGHT_TO_LEFT) {
|
||||
layout = new JSONValue<std::string>("RIGHT_TO_LEFT");
|
||||
}
|
||||
if (text->getLayout() == osgText::Text::VERTICAL) {
|
||||
layout = new JSONValue<std::string>("VERTICAL");
|
||||
}
|
||||
jsonText->getMaps()["Layout"] = layout;
|
||||
return jsonText.release();
|
||||
}
|
||||
|
||||
|
||||
JSONObject* WriteVisitor::createJSONPagedLOD(osg::PagedLOD *plod)
|
||||
{
|
||||
if (!plod) { return 0; }
|
||||
@ -626,10 +816,8 @@ JSONObject* WriteVisitor::createJSONPagedLOD(osg::PagedLOD *plod)
|
||||
}
|
||||
|
||||
osg::ref_ptr<JSONObject> jsonPlod = new JSONNode;
|
||||
jsonPlod->addUniqueID();
|
||||
_maps[plod] = jsonPlod;
|
||||
|
||||
|
||||
// Center Mode
|
||||
osg::ref_ptr<JSONValue<std::string> > centerMode = new JSONValue<std::string>("USE_BOUNDING_SPHERE_CENTER");
|
||||
if (plod->getCenterMode() == osg::LOD::USER_DEFINED_CENTER) {
|
||||
@ -649,8 +837,7 @@ JSONObject* WriteVisitor::createJSONPagedLOD(osg::PagedLOD *plod)
|
||||
}
|
||||
jsonPlod->getMaps()["RangeMode"] = rangeMode;
|
||||
// Range List
|
||||
//osg::ref_ptr<JSONArray> rangeList = new JSONArray;
|
||||
JSONObject* rangeObject = new JSONObject;
|
||||
osg::ref_ptr<JSONObject> rangeObject = new JSONObject;
|
||||
for (unsigned int i =0; i< plod->getRangeList().size(); i++)
|
||||
{
|
||||
std::stringstream ss;
|
||||
@ -662,7 +849,7 @@ JSONObject* WriteVisitor::createJSONPagedLOD(osg::PagedLOD *plod)
|
||||
jsonPlod->getMaps()["RangeList"] = rangeObject;
|
||||
// File List
|
||||
|
||||
JSONObject* fileObject = new JSONObject;
|
||||
osg::ref_ptr<JSONObject> fileObject = new JSONObject;
|
||||
for (unsigned int i =0; i< plod->getNumFileNames(); i++)
|
||||
{
|
||||
std::stringstream ss;
|
||||
@ -670,19 +857,28 @@ JSONObject* WriteVisitor::createJSONPagedLOD(osg::PagedLOD *plod)
|
||||
ss << i;
|
||||
std::string str = ss.str();
|
||||
// We need to convert first from osg format to osgjs format.
|
||||
osg::ref_ptr<osg::Node> n = osgDB::readRefNodeFile(plod->getFileName(i)+".gles");
|
||||
osg::ref_ptr<osg::Node> n = osgDB::readRefNodeFile(plod->getDatabasePath() + plod->getFileName(i)+".gles");
|
||||
if (n)
|
||||
{
|
||||
std::string filename(osgDB::getStrippedName(plod->getFileName(i))+".osgjs");
|
||||
osgDB::writeNodeFile(*n,filename);
|
||||
fileObject->getMaps()[str] = new JSONValue<std::string>(filename);
|
||||
std::string filename(osgDB::getNameLessExtension(plod->getFileName(i))+".osgjs");
|
||||
|
||||
std::string fullFilePath(osgDB::getFilePath(_baseName) + osgDB::getNativePathSeparator() + filename);
|
||||
fileObject->getMaps()[str] = new JSONValue<std::string>(_baseLodURL + filename);
|
||||
osgDB::makeDirectoryForFile(fullFilePath);
|
||||
if (_baseLodURL.empty())
|
||||
_baseLodURL = osgDB::getFilePath(filename) + osgDB::getNativePathSeparator() ;
|
||||
osg::ref_ptr<osgDB::Options> options = osgDB::Registry::instance()->getOptions()->cloneOptions();
|
||||
options->setPluginStringData(std::string("baseLodURL"), _baseLodURL);
|
||||
|
||||
osgDB::writeNodeFile(*n, fullFilePath, options.get());
|
||||
|
||||
}
|
||||
else
|
||||
fileObject->getMaps()[str] = new JSONValue<std::string>("");
|
||||
}
|
||||
jsonPlod->getMaps()["RangeDataList"] = fileObject;
|
||||
|
||||
return jsonPlod.get();
|
||||
return jsonPlod.release();
|
||||
}
|
||||
|
||||
JSONObject* WriteVisitor::createJSONTexture(osg::Texture* texture)
|
||||
@ -742,7 +938,6 @@ JSONObject* WriteVisitor::createJSONStateSet(osg::StateSet* stateset)
|
||||
|
||||
osg::ref_ptr<JSONObject> jsonStateSet = new JSONStateSet;
|
||||
_maps[stateset] = jsonStateSet;
|
||||
jsonStateSet->addUniqueID();
|
||||
|
||||
translateObject(jsonStateSet.get(), stateset);
|
||||
|
||||
@ -826,17 +1021,10 @@ JSONObject* WriteVisitor::createJSONStateSet(osg::StateSet* stateset)
|
||||
attributeList->getArray().push_back(obj);
|
||||
}
|
||||
|
||||
|
||||
if (!attributeList->getArray().empty()) {
|
||||
jsonStateSet->getMaps()["AttributeList"] = attributeList;
|
||||
}
|
||||
|
||||
|
||||
osg::StateSet::ModeList modeList = stateset->getModeList();
|
||||
for (unsigned int i = 0; i < modeList.size(); ++i) {
|
||||
// add modes
|
||||
}
|
||||
|
||||
if (jsonStateSet->getMaps().empty())
|
||||
return 0;
|
||||
return jsonStateSet.release();
|
||||
|
@ -19,15 +19,15 @@
|
||||
#define JSON_STREAM
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cctype> // control characters
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include <osgDB/fstream>
|
||||
|
||||
#include "utf8_string"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
// A simple class wrapping ofstream calls to enable generic cleaning of json data.
|
||||
@ -117,182 +117,13 @@ class json_stream : public osgDB::ofstream {
|
||||
std::string to_json_utf8(const std::string& s) {
|
||||
// TODO: try to decode latin1 if string is not valid utf8
|
||||
// before actually fixing bad 'chars'
|
||||
return clean_invalid_utf8(s);
|
||||
return utf8_string::sanitize(s);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
std::ofstream _stream;
|
||||
bool _strict;
|
||||
|
||||
std::string json_encode_control_char(int ctrl) {
|
||||
// see http://json.org
|
||||
std::ostringstream oss;
|
||||
|
||||
if(ctrl == 8 || // \b
|
||||
ctrl == 9 || // \t
|
||||
ctrl == 10 || // \n
|
||||
ctrl == 12 || // \f
|
||||
ctrl == 13 || // \r
|
||||
ctrl == 27 || //
|
||||
ctrl == 34 || // \"
|
||||
ctrl == 47 // \/
|
||||
) {
|
||||
oss << static_cast<char>(ctrl);
|
||||
}
|
||||
else {
|
||||
oss.fill('0');
|
||||
oss << "\\u" << std::setw(4) << std::hex << ctrl;
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
inline bool is_valid_continuation_byte(unsigned int byte) {
|
||||
return ((byte & 0xC0) == 0x80);
|
||||
}
|
||||
|
||||
inline int get_next_byte(std::string::const_iterator& iterator, std::string::const_iterator end_iterator) {
|
||||
if(iterator != end_iterator) {
|
||||
return *(++ iterator);
|
||||
}
|
||||
else {
|
||||
return 0; // invalid continuation byte
|
||||
}
|
||||
}
|
||||
|
||||
// from http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
|
||||
std::string utf8_encode_codepoint(unsigned code_point)
|
||||
{
|
||||
std::string output;
|
||||
|
||||
if(code_point > 0x590 && code_point < 0x5F4) {
|
||||
return output;
|
||||
}
|
||||
|
||||
// out of range
|
||||
if(code_point > 1114112) {
|
||||
return utf8_encode_codepoint(0xfffd);
|
||||
}
|
||||
|
||||
if (code_point < 0x80) {
|
||||
output.push_back(code_point);
|
||||
}
|
||||
else if (code_point <= 0x7FF) {
|
||||
output.push_back((code_point >> 6) + 0xC0);
|
||||
output.push_back((code_point & 0x3F) + 0x80);
|
||||
}
|
||||
else if (code_point <= 0xFFFF) {
|
||||
output.push_back((code_point >> 12) + 0xE0);
|
||||
output.push_back(((code_point >> 6) & 0x3F) + 0x80);
|
||||
output.push_back((code_point & 0x3F) + 0x80);
|
||||
}
|
||||
else if (code_point <= 0x10FFFF) {
|
||||
output.push_back((code_point >> 18) + 0xF0);
|
||||
output.push_back(((code_point >> 12) & 0x3F) + 0x80);
|
||||
output.push_back(((code_point >> 6) & 0x3F) + 0x80);
|
||||
output.push_back((code_point & 0x3F) + 0x80);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// from http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
|
||||
std::string clean_invalid_utf8(const std::string& input,
|
||||
const int replacement_codepoint=0xfffd) {
|
||||
int code_unit1, code_unit2, code_unit3, code_unit4;
|
||||
std::string output, replacement = utf8_encode_codepoint(replacement_codepoint);
|
||||
|
||||
for(std::string::const_iterator iterator = input.begin() ; iterator != input.end() ; ++ iterator) {
|
||||
code_unit1 = *iterator;
|
||||
if (code_unit1 < 0x80) {
|
||||
if(std::iscntrl(code_unit1)) {
|
||||
output += json_encode_control_char(code_unit1);
|
||||
}
|
||||
else {
|
||||
output.push_back(code_unit1);
|
||||
}
|
||||
}
|
||||
else if (code_unit1 < 0xC2) {
|
||||
// continuation or overlong 2-byte sequence
|
||||
output += replacement;
|
||||
}
|
||||
else if (code_unit1 < 0xE0) {
|
||||
// 2-byte sequence
|
||||
code_unit2 = get_next_byte(iterator, input.end());
|
||||
|
||||
if (!is_valid_continuation_byte(code_unit2)) {
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
}
|
||||
else {
|
||||
output += utf8_encode_codepoint((code_unit1 << 6) + code_unit2 - 0x3080);
|
||||
}
|
||||
}
|
||||
else if (code_unit1 < 0xF0) {
|
||||
// 3-byte sequence
|
||||
code_unit2 = get_next_byte(iterator, input.end());
|
||||
|
||||
if (!is_valid_continuation_byte(code_unit2) ||
|
||||
(code_unit1 == 0xE0 && code_unit2 < 0xA0)) /* overlong */ {
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
}
|
||||
else {
|
||||
code_unit3 = get_next_byte(iterator, input.end());
|
||||
|
||||
if (!is_valid_continuation_byte(code_unit3)) {
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
}
|
||||
else {
|
||||
output += utf8_encode_codepoint((code_unit1 << 12) +
|
||||
(code_unit2 << 6) +
|
||||
code_unit3 - 0xE2080);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (code_unit1 < 0xF5) {
|
||||
// 4-byte sequence
|
||||
code_unit2 = get_next_byte(iterator, input.end());
|
||||
if(!is_valid_continuation_byte(code_unit2) ||
|
||||
(code_unit1 == 0xF0 && code_unit2 < 0x90) || /* overlong */
|
||||
(code_unit1 == 0xF4 && code_unit2 >= 0x90)) { /* > U+10FFFF */
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
}
|
||||
else {
|
||||
code_unit3 = get_next_byte(iterator, input.end());
|
||||
if(!is_valid_continuation_byte(code_unit3)) {
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
}
|
||||
else {
|
||||
code_unit4 = get_next_byte(iterator, input.end());
|
||||
if(!is_valid_continuation_byte(code_unit4)) {
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
}
|
||||
else {
|
||||
output += utf8_encode_codepoint((code_unit1 << 18) +
|
||||
(code_unit2 << 12) +
|
||||
(code_unit3 << 6) +
|
||||
code_unit4 - 0x3C82080);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* > U+10FFFF */
|
||||
output += replacement;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
187
src/osgPlugins/osgjs/utf8_string
Normal file
187
src/osgPlugins/osgjs/utf8_string
Normal file
@ -0,0 +1,187 @@
|
||||
#ifndef UTF8_STRING
|
||||
#define UTF8_STRING
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <cctype> // control characters
|
||||
|
||||
|
||||
namespace utf8_string {
|
||||
inline std::string encode_control_char(unsigned int ctrl) {
|
||||
// see http://json.org
|
||||
std::ostringstream oss;
|
||||
|
||||
if(ctrl == 8 || // \b
|
||||
ctrl == 9 || // \t
|
||||
ctrl == 10 || // \n
|
||||
ctrl == 12 || // \f
|
||||
ctrl == 13 || // \r
|
||||
ctrl == 27 || //
|
||||
ctrl == 34 || // \"
|
||||
ctrl == 47 // \/
|
||||
) {
|
||||
oss << static_cast<unsigned char>(ctrl);
|
||||
}
|
||||
else {
|
||||
oss.fill('0');
|
||||
oss << "\\u" << std::setw(4) << std::hex << ctrl;
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
inline bool is_valid_continuation_byte(unsigned int byte) {
|
||||
return ((byte & 0xC0) == 0x80);
|
||||
}
|
||||
|
||||
|
||||
inline int get_next_byte(std::string::const_iterator& iterator, std::string::const_iterator end_iterator) {
|
||||
if(iterator != end_iterator) {
|
||||
return *(++ iterator);
|
||||
}
|
||||
else {
|
||||
return 0; // invalid continuation byte
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// from http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
|
||||
inline std::string encode_codepoint(unsigned code_point)
|
||||
{
|
||||
std::string output;
|
||||
|
||||
if(code_point > 0x590 && code_point < 0x5F4) {
|
||||
return output;
|
||||
}
|
||||
|
||||
// out of range
|
||||
if(code_point > 1114112) {
|
||||
return encode_codepoint(0xfffd);
|
||||
}
|
||||
|
||||
if (code_point < 0x80) {
|
||||
output.push_back(code_point);
|
||||
}
|
||||
else if (code_point <= 0x7FF) {
|
||||
output.push_back((code_point >> 6) + 0xC0);
|
||||
output.push_back((code_point & 0x3F) + 0x80);
|
||||
}
|
||||
else if (code_point <= 0xFFFF) {
|
||||
output.push_back((code_point >> 12) + 0xE0);
|
||||
output.push_back(((code_point >> 6) & 0x3F) + 0x80);
|
||||
output.push_back((code_point & 0x3F) + 0x80);
|
||||
}
|
||||
else if (code_point <= 0x10FFFF) {
|
||||
output.push_back((code_point >> 18) + 0xF0);
|
||||
output.push_back(((code_point >> 12) & 0x3F) + 0x80);
|
||||
output.push_back(((code_point >> 6) & 0x3F) + 0x80);
|
||||
output.push_back((code_point & 0x3F) + 0x80);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// from http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
|
||||
inline std::string clean_invalid(const std::string& input, const int replacement_codepoint=0xfffd) {
|
||||
unsigned int code_unit1, code_unit2, code_unit3, code_unit4;
|
||||
std::string output, replacement = encode_codepoint(replacement_codepoint);
|
||||
|
||||
for(std::string::const_iterator iterator = input.begin() ; iterator != input.end() ; ++ iterator) {
|
||||
code_unit1 = *iterator;
|
||||
if (code_unit1 < 0x80) {
|
||||
if(std::iscntrl(code_unit1)) {
|
||||
output += encode_control_char(code_unit1);
|
||||
}
|
||||
else {
|
||||
output.push_back(code_unit1);
|
||||
}
|
||||
}
|
||||
else if (code_unit1 < 0xC2) {
|
||||
// continuation or overlong 2-byte sequence
|
||||
output += replacement;
|
||||
}
|
||||
else if (code_unit1 < 0xE0) {
|
||||
// 2-byte sequence
|
||||
code_unit2 = get_next_byte(iterator, input.end());
|
||||
|
||||
if (!is_valid_continuation_byte(code_unit2)) {
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
}
|
||||
else {
|
||||
output += encode_codepoint((code_unit1 << 6) + code_unit2 - 0x3080);
|
||||
}
|
||||
}
|
||||
else if (code_unit1 < 0xF0) {
|
||||
// 3-byte sequence
|
||||
code_unit2 = get_next_byte(iterator, input.end());
|
||||
|
||||
if (!is_valid_continuation_byte(code_unit2) ||
|
||||
(code_unit1 == 0xE0 && code_unit2 < 0xA0)) /* overlong */ {
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
}
|
||||
else {
|
||||
code_unit3 = get_next_byte(iterator, input.end());
|
||||
|
||||
if (!is_valid_continuation_byte(code_unit3)) {
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
}
|
||||
else {
|
||||
output += encode_codepoint((code_unit1 << 12) +
|
||||
(code_unit2 << 6) +
|
||||
code_unit3 - 0xE2080);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (code_unit1 < 0xF5) {
|
||||
// 4-byte sequence
|
||||
code_unit2 = get_next_byte(iterator, input.end());
|
||||
if(!is_valid_continuation_byte(code_unit2) ||
|
||||
(code_unit1 == 0xF0 && code_unit2 < 0x90) || /* overlong */
|
||||
(code_unit1 == 0xF4 && code_unit2 >= 0x90)) { /* > U+10FFFF */
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
}
|
||||
else {
|
||||
code_unit3 = get_next_byte(iterator, input.end());
|
||||
if(!is_valid_continuation_byte(code_unit3)) {
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
}
|
||||
else {
|
||||
code_unit4 = get_next_byte(iterator, input.end());
|
||||
if(!is_valid_continuation_byte(code_unit4)) {
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
output += replacement;
|
||||
}
|
||||
else {
|
||||
output += encode_codepoint((code_unit1 << 18) +
|
||||
(code_unit2 << 12) +
|
||||
(code_unit3 << 6) +
|
||||
code_unit4 - 0x3C82080);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* > U+10FFFF */
|
||||
output += replacement;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
inline std::string sanitize(const std::string& input) {
|
||||
return clean_invalid(input);
|
||||
}
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user