Files
OpenSceneGraph/src/osgPlugins/gles/GeometryCleaner
2017-11-02 18:43:05 +00:00

142 lines
5.0 KiB
C++

/* -*-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
* applications, as long as this copyright notice is maintained.
*
* This application 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.
*
*/
#ifndef GEOMETRY_CLEANER
#define GEOMETRY_CLEANER
#include <osg/Geometry>
#include <osgAnimation/RigGeometry>
#include <osgAnimation/MorphGeometry>
#include "GeometryMapper"
#include "SubGeometry"
class GeometryCleaner : public GeometryMapper
{
public:
const GeometryList& process(osg::Geometry& geometry) {
_clean.clear();
if(dynamic_cast<osgAnimation::MorphGeometry*>(&geometry)) {
// a morph geometry may have a degenerated primitive in one target but not all targets
// let's leave them unmodified
_clean.push_back(&geometry);
}
else if(dynamic_cast<osgAnimation::RigGeometry*>(&geometry)) {
// skipping rigged geometry for now
_clean.push_back(&geometry);
}
else {
osg::Vec3Array* positions = dynamic_cast<osg::Vec3Array*>(geometry.getVertexArray());
if (positions)
{
SubGeometry cleaned(geometry,
clean(*positions, getTriangles(geometry), 3),
clean(*positions, getLines(geometry), 2),
clean(*positions, getWireframe(geometry), 2),
clean(*positions, getPoints(geometry), 1));
_clean.push_back(cleaned.geometry());
}
}
return _clean;
}
osg::DrawElements* getTriangles(osg::Geometry& geometry) {
for(unsigned int i = 0 ; i < geometry.getNumPrimitiveSets() ; ++ i) {
osg::DrawElements* primitive = geometry.getPrimitiveSet(i)->getDrawElements();
if(primitive && primitive->getMode() == osg::PrimitiveSet::TRIANGLES) {
return primitive;
}
}
return 0;
}
osg::DrawElements* getLines(osg::Geometry& geometry) {
for(unsigned int i = 0 ; i < geometry.getNumPrimitiveSets() ; ++ i) {
osg::DrawElements* primitive = geometry.getPrimitiveSet(i)->getDrawElements();
if(primitive && primitive->getMode() == osg::PrimitiveSet::LINES) {
bool wireframe(false);
if(!primitive->getUserValue("wireframe", wireframe) || !wireframe)
return primitive;
}
}
return 0;
}
osg::DrawElements* getWireframe(osg::Geometry& geometry) {
for(unsigned int i = 0 ; i < geometry.getNumPrimitiveSets() ; ++ i) {
osg::DrawElements* primitive = geometry.getPrimitiveSet(i)->getDrawElements();
if(primitive && primitive->getMode() == osg::PrimitiveSet::LINES) {
bool wireframe(false);
if(primitive->getUserValue("wireframe", wireframe) && wireframe)
return primitive;
}
}
return 0;
}
osg::DrawElements* getPoints(osg::Geometry& geometry) {
for(unsigned int i = 0 ; i < geometry.getNumPrimitiveSets() ; ++ i) {
osg::DrawElements* primitive = geometry.getPrimitiveSet(i)->getDrawElements();
if(primitive && primitive->getMode() == osg::PrimitiveSet::POINTS) {
return primitive;
}
}
return 0;
}
std::vector<unsigned int> clean(const osg::Vec3Array& positions, osg::DrawElements* elements, const unsigned int size) {
std::vector<unsigned int> indices;
if(!elements) return indices;
for(unsigned int i = 0 ; i < elements->getNumIndices() ; i += size) {
if(size == 3) {
unsigned int v1 = elements->index(i),
v2 = elements->index(i + 1),
v3 = elements->index(i + 2);
osg::Vec3 p1 = positions[v1],
p2 = positions[v2],
p3 = positions[v3];
osg::Vec3f cross = (p2 - p1) ^ (p3 - p1);
if(cross.length()) {
indices.push_back(v1);
indices.push_back(v2);
indices.push_back(v3);
}
}
else if (size == 2) {
unsigned int v1 = elements->index(i),
v2 = elements->index(i + 1);
if(!(positions[v1] == positions[v2])) {
indices.push_back(v1);
indices.push_back(v2);
}
}
else {
indices.push_back(elements->index(i));
}
}
return indices;
}
GeometryList _clean;
};
#endif