OSG法线收集

CollectNormalsVisitor.hpp

#include <osg/NodeVisitor>

namespace ose {

  /**
   * Compute a representation of normals from children geometries.
   *
   * Normals are bound to vertices.
   * The length of each normal is controlled with the magniture parameter.
   */
  struct CollectNormalsVisitor : public osg::NodeVisitor
  {
    /** Vector of normal lines: [normal1-begin, normal1-end, ...] */
    std::vector<osg::Vec3> normalList;
    float                  magnitude;

    CollectNormalsVisitor(const float magnitude = 2.0f);

    void apply(osg::Geode& geode) override;
    osg::ref_ptr<osg::Geode> toNormalsGeomtery(
      osg::Vec4 color = osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
  };

} // ose

CollectNormalsVisitor.cpp

#include "CollectNormalsVisitor.hpp"

#include <cassert>

#include <osg/Geode>
#include <osg/Geometry>

namespace ose {

  CollectNormalsVisitor::CollectNormalsVisitor(const float magnitude)
    : NodeVisitor(osg::NodeVisitor::TraversalMode::TRAVERSE_ACTIVE_CHILDREN)
    , magnitude(magnitude)
  {
  }

  void CollectNormalsVisitor::apply(osg::Geode& geode)
  {
    for (unsigned int it = 0; it < geode.getNumDrawables(); ++it) {
      const osg::Drawable* childDrawable = geode.getDrawable(it);
      assert(childDrawable);

      const osg::Geometry* geometry = childDrawable->asGeometry();
      /* We only support geometry */
      if (geometry) {
        const osg::Vec3Array* normals =
          dynamic_cast<const osg::Vec3Array*>(geometry->getNormalArray());
        assert(normals);
        const osg::Vec3Array* vertices =
          dynamic_cast<const osg::Vec3Array*>(geometry->getVertexArray());
        assert(vertices);

        assert(normals->getBinding() == osg::Array::Binding::BIND_PER_VERTEX &&
               "// TODO: Support other binding mods");

        osg::Matrix world = osg::computeWorldToLocal(this->getNodePath());
        for (unsigned int it = 0; it < vertices->size(); ++it) {
          const osg::Vec3& lineBegin = world * (*vertices)[it];
          const osg::Vec3& lineEnd   = lineBegin + (*normals)[it] * magnitude;

          normalList.push_back(lineBegin);
          normalList.push_back(lineEnd);
        }
      } else {
        osg::notify() << "Skipping non-geometry Drawable:"
                      << childDrawable->getName() << "\n";
      }
    }
    traverse(geode);
  }

  osg::ref_ptr<osg::Geode> CollectNormalsVisitor::toNormalsGeomtery(
    osg::Vec4 color)
  {
    osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
    vertices->insert(vertices->begin(), normalList.begin(), normalList.end());

    osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
    colors->push_back(color);

    osg::ref_ptr<osg::Geometry> norms = new osg::Geometry;
    norms->setVertexArray(vertices);
    norms->setColorArray(colors);
    norms->setColorBinding(osg::Geometry::BIND_OVERALL);

    norms->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, vertices->size()));

    osg::ref_ptr<osg::Geode> leaf = new osg::Geode;
    // Make sure to deactivate the lighting
    leaf->getOrCreateStateSet()->setMode(
      GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
    leaf->addDrawable(norms);
    return leaf;
  }

} // ose

调用

#include "CollectNormalsVisitor.hpp"

int
main(int argc, char** argv)
{
  // Load your model
  osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(fileToOpen);
  
  // Collect all the geometries normals from parent to children
  ose::CollectNormalsVisitor c;
  model->accept(c);
  
  // Generate the new geometry (a list of gl_lines) and add them to the root
  osg::ref_ptr<osg::MatrixTransform> root = new osg::MatrixTransform;
  root->addChild(c.toNormalsGeomtery(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)));
  
  /* Add the root to the viewer ... */
  
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值