1/* -*-c++-*- OpenSceneGraph - Copyright (C) Sketchfab */
2
3#include <osg/Geometry>
4#include <osgAnimation/MorphGeometry>
5
6#include "GeometryUniqueVisitor"
7#include "TriangleMeshSmoother"
8#include "glesUtil"
9
10
11class SmoothNormalVisitor : public GeometryUniqueVisitor {
12public:
13    SmoothNormalVisitor(float creaseAngle, bool comparePosition=false):
14        GeometryUniqueVisitor("SmoothNormalVisitor"),
15        _creaseAngle(creaseAngle),
16        _comparePosition(comparePosition)
17    {}
18
19    void process(osg::Geometry& geometry) {
20        if(!geometry.getNormalArray()) {
21            TriangleMeshSmoother(geometry, _creaseAngle, _comparePosition, TriangleMeshSmoother::recompute);
22        }
23        else {
24            TriangleMeshSmoother(geometry, _creaseAngle, _comparePosition, TriangleMeshSmoother::diagnose);
25        }
26    }
27
28    void process(osgAnimation::MorphGeometry& morphGeometry) {
29        bool needSmoothing = needMorphGeometrySmoothing(morphGeometry);
30
31        if(needSmoothing) {
32            TriangleMeshSmoother(morphGeometry, 0, true, TriangleMeshSmoother::smooth_all);
33
34            osgAnimation::MorphGeometry::MorphTargetList targets = morphGeometry.getMorphTargetList();
35            for(osgAnimation::MorphGeometry::MorphTargetList::iterator target = targets.begin() ; target != targets.end() ; ++ target) {
36                // check normal orientation using the same primitives as parent geometry
37                glesUtil::TargetGeometry geometry(*target, morphGeometry);
38                if(geometry && !geometry->getNormalArray()) {
39                    TriangleMeshSmoother(*geometry, 0, true, TriangleMeshSmoother::smooth_all);
40                }
41            }
42        }
43    }
44
45protected:
46    bool needMorphGeometrySmoothing(osgAnimation::MorphGeometry& morphGeometry) {
47        if(!morphGeometry.getNormalArray()) {
48            return true;
49        }
50
51        osgAnimation::MorphGeometry::MorphTargetList targets = morphGeometry.getMorphTargetList();
52
53        for(osgAnimation::MorphGeometry::MorphTargetList::iterator target = targets.begin() ; target != targets.end() ; ++ target) {
54            osg::Geometry* geometry = target->getGeometry();
55            if(geometry && !geometry->getNormalArray()) {
56                return true;
57            }
58        }
59
60        return false;
61    }
62
63
64    float _creaseAngle;
65    bool _comparePosition;
66};
67