osgSim::SphereSegment分析

osgSphereSegment分析

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * 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.
*/

#ifndef OSGSIM_SPHERESEGMENT
#define OSGSIM_SPHERESEGMENT 1

#include <osgSim/Export>

#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Geode>
#include <osg/Matrixd>
#include <osg/BlendFunc>

namespace osgSim{

/**
A SphereSegment是Geode节点 来展示球体一部分( 也可能是全部). 球面是对齐的,这样穿过两级的直线与z轴平行。球面段通过不同组件开关进行渲染或关闭。

    - 球面指定区域.
<p class="ordinary-output target-output" style="margin-top: 0px; margin-bottom: 5px; padding-top: 0px; padding-bottom: 0px; line-height: 22px; font-size: 14px; color: rgb(51, 51, 51); font-family: arial;"><span left-pos="33|21,20|3" right-pos="33|21,20|3" space="" class="high-light-bg" style="border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; cursor: pointer; background: yellow;">--球体表面指定区域的</span><span left-pos="24|8,13|6" right-pos="24|8,13|6" space="">边界周围</span><span left-pos="0|12" right-pos="0|12" space="1|">的边缘线</span></p>

    -四个辐条r <i>spokes</i>, 辐条是一条线,这条线从球面中心到渲染区域的一角.


    - 四个平面区域 planar,平面区域由辐条之间的空间构成.

警告:

    -, and specifying areas where the centre of
      the rendered area <i>is</i> the Z axis may lead to unexpected
      geometry.<p class="ordinary-output target-output" style="margin-top: 0px; margin-bottom: 5px; padding-top: 0px; padding-bottom: 0px; line-height: 22px; font-size: 14px; color: rgb(51, 51, 51); font-family: arial;"><span left-pos="0|22" right-pos="0|22" space="">      -值得注意的是,</span><span left-pos="23|20" right-pos="23|20" space="">通过</span><span left-pos="44|6" right-pos="44|6" space="">球</span><span left-pos="50|11" right-pos="50|11" space="1|">的两个极点的线</span><span left-pos="62|30" right-pos="0|30" space="">平行于z轴。</span><span left-pos="92|21" right-pos="30|21" space="">这意味着</span><span left-pos="114|19" right-pos="52|19" space="1|">当指定</span><span left-pos="145|14" right-pos="11|14" space="">要渲染的区域</span><span left-pos="159|1" right-pos="25|1" space="">,指定区域的渲染区域的中心是Z轴将导致</span>导致不可知的<span left-pos="276|8" right-pos="6|8" space="">几何体geometry</span><span left-pos="284|1" right-pos="14|1" space="1|">。</span></p>

    - 也可以渲染整个球。通过指定 elevation
      and azimuth ranges round the full 360 degrees. When doing
      so 考虑转换平面、辐条线、边沿设为off关闭状态, to avoid rendering artefacts, e.g. the upper and lower
      planes will be coincident.

*/
class OSGSIM_EXPORT SphereSegment: public osg::Geode
{
public:

    /**
    DrawMask represents a bit field, the values of which may be OR'ed together
    指定哪一部分绘制. E.g.
    \code
    sphereSegment->setDrawMask(SphereSegment::DrawMask(SphereSegment::SURFACE|SphereSegment::SPOKES));
    \endcode
    */
    enum DrawMask{
        SURFACE =   0x00000001, ///< Draw the specified area on the sphere's surface
        SPOKES =    0x00000002, ///< Draw the spokes from the sphere's centre to the surface's corners
        EDGELINE =  0x00000008, ///< Draw the line round the edge of the area on the sphere's surface
        SIDES =     0x00000010, ///< Draw the planes from the sphere's centre to the edge of the sphere's surface
        ALL =       0x7fffffff  ///< Draw every part of the sphere segment
    };


    /** 构造函数. */
    SphereSegment():osg::Geode(),
                    _centre(0.0f,0.0f,0.0f), _radius(1.0f),
                    _azMin(0.0f), _azMax(osg::PI/2.0f),
                    _elevMin(0.0f), _elevMax(osg::PI/2.0f),
                    _density(10),
                    _drawMask(DrawMask(ALL))
    {
        init();
    }

    /**
    Construct by angle ranges. Note that the azimuth 'zero' is the Y axis; specifying
    an azimuth range from azMin -osg::PI/2.0f to azMax osg::PI/2.0f will cover the
    'top half' of the circle in the XY plane. The elev angles are 'out' of the 'zero'
    XY plane with +ve angles above the plane, and -ve angles below.
    @param centre       sphere centre
    @param radius       radius of sphere
    @param azMin        azimuth minimum
    @param azMax        azimuth maximum
    @param elevMin      elevation minimum
    @param elevMax      elevation maximum
    @param density      number of units to divide the azimuth and elevation ranges into
    */
    SphereSegment(const osg::Vec3& centre, float radius, float azMin, float azMax,
                    float elevMin, float elevMax, int density):
        osg::Geode(),
        _centre(centre), _radius(radius),
        _azMin(azMin), _azMax(azMax),
        _elevMin(elevMin), _elevMax(elevMax),
        _density(density),
        _drawMask(DrawMask(ALL))
    {
        init();
    }
//方位角又称地平经度(Azimuth (angle)缩写Az),是在平面上量度物体之间的角度差的方法之一。是从某点的指北方向线起,依顺时针方向到目标方向线之间的水平夹角。
//elev 高处,高地,高度,海拔,(枪炮的)仰角,射角;升级,上进,向上;
//density n.<span style="white-space:pre">	</span>密度;稠密,浓厚;[物]浓度,比重;愚钝
    /**
    Construct by vector.
    @param centre      球中心
    @param radius       球半径
    @param vec          vector 指向从球心到绘制区域球表面的中心
    @param azRange      azimuth range in radians (中心沿 along vec)
    @param elevRange    elevation range in radians (中心沿 along vec)
    @param density      number of units to divide the azimuth and elevation ranges into
    */
    SphereSegment(const osg::Vec3& centre, float radius, const osg::Vec3& vec, float azRange,
                    float elevRange, int density);

    /** Copy constructor */
    SphereSegment(const SphereSegment& rhs, const osg::CopyOp& co):
        osg::Geode(rhs,co),
        _centre(rhs._centre), _radius(rhs._radius),
        _azMin(rhs._azMin), _azMax(rhs._azMax),
        _elevMin(rhs._elevMin), _elevMax(rhs._elevMax),
        _density(rhs._density),
        _drawMask(rhs._drawMask)
    {
        init();
    }

    /** Set the centre point of the SphereSegment */
    void setCentre(const osg::Vec3& c);

    /** Get the centre point of the SphereSegment */
    const osg::Vec3& getCentre() const;

    /** Set the radius of the SphereSegment */
    void setRadius(float r);

    /** Get the radius of the SphereSegment */
    float getRadius() const;

    /** Set the area of the sphere segment

    @param vec          vector pointing from sphere centre to centre point
                        of rendered area on sphere surface
    @param azRange      azimuth range in radians (with centre along vec)
    @param elevRange    elevation range in radians (with centre along vec)
    */
    void setArea(const osg::Vec3& vec, float azRange, float elevRange);

    /** Get the area of the sphere segment

    @param vec          vector pointing from sphere centre to centre point
                        of rendered area on sphere surface (normalized)
    @param azRange     方位角范围 range in radians (with centre along vec)
    @param elevRange   仰角范围(与XY平面夹角,弧度0-2pi) (with centre along vec)
    */
    void getArea(osg::Vec3& vec, float& azRange, float& elevRange) const;

    /** Set the area of the sphere segment
    @param azMin        azimuth minimum
    @param azMax        azimuth maximum
    @param elevMin      elevation minimum
    @param elevMax      elevation maximum
    */
    void setArea(float azMin, float azMax, float elevMin, float elevMax);

    /** Get the area of the sphere segment
    @param azMin        azimuth minimum
    @param azMax        azimuth maximum
    @param elevMin      elevation minimum
    @param elevMax      elevation maximum
    */
    void getArea(float &azMin, float &azMax, float &elevMin, float &elevMax) const;

    /** Set the density of the sphere segment */
    void setDensity(int d);

    /** Get the density of the sphere segment */
    int getDensity() const;

    /**
    Specify the DrawMask.
    @param dm   Bitmask specifying which parts of the sphere segment should be drawn.
    @see DrawMask
    */
    void setDrawMask(int dm);

    /** Get the DrawMask */
    int getDrawMask() const { return _drawMask; }

    /** Set the color of the surface. */
    void setSurfaceColor(const osg::Vec4& c);

    /** Get the color of the surface. */
    const osg::Vec4& getSurfaceColor() const { return _surfaceColor; }

    /** Set the color of the spokes. */
    void setSpokeColor(const osg::Vec4& c);

    /** Get the color of the spokes. */
    const osg::Vec4& getSpokeColor() const { return _spokeColor; }

    /** Set the color of the edge line. */
    void setEdgeLineColor(const osg::Vec4& c);

    /** Get the color of the edge line. */
    const osg::Vec4& getEdgeLineColor() const { return _edgeLineColor; }

    /** Set the color of the planes. */
    void setSideColor(const osg::Vec4& c);

    /** Get the color of the planes. */
    const osg::Vec4& getSideColor() const { return _planeColor; }

    /** Set color of all components. */
    void setAllColors(const osg::Vec4& c);

    META_Node(osgSim, SphereSegment);

    /** A list of vertex arrays representing a list of lines.*/
    typedef std::vector< osg::ref_ptr<osg::Vec3Array> > LineList;

    /** Compute the interesection lines between subgraph and this sphere segment.
      * The matrix is the transform that takes the subgraph into the same coordiante frame as the sphere segment.
      * The resulting intersections are in the coordinate frame of the sphere segment. */
    LineList computeIntersection(const osg::Matrixd& matrix, osg::Node* subgraph);

    /** Compute the interesection lines between specified drawable and this sphere segment.
      * The matrix is the transform that takes the subgraph into the same coordiante frame as the sphere segment.
      * The resulting intersections are in the coordinate frame of the sphere segment. */
    LineList computeIntersection(const osg::Matrixd& matrix, osg::Drawable* drawable);

    /** Compute the interesection lines between subgraph and this sphere segment.
      * The matrix is the transform that takes the subgraph into the same coordiante frame as the sphere segment.
      * The resulting intersections are in the coordinate frame of the sphere segment. */
    osg::Node* computeIntersectionSubgraph(const osg::Matrixd& matrix, osg::Node* subgraph);

    /** Compute the interesection lines between specified drawable and this sphere segment.
      * The matrix is the transform that takes the subgraph into the same coordiante frame as the sphere segment.
      * The resulting intersections are in the coordinate frame of the sphere segment. */
    osg::Node* computeIntersectionSubgraph(const osg::Matrixd& matrix, osg::Drawable* drawable);


private:

    void init();    // Shared constructor code, generates the drawables

    void dirtyAllDrawableDisplayLists();    // Force re-calling of gl functions
    void dirtyAllDrawableBounds();          // Force recalculation of bound geometry

    // SphereSegment is actually made up of a number of Drawable classes,
    // all of which are nested private classes, as declared below. These
    // classes are defined in the .cpp for minimum visibility and physical
    // coupling. (Reduces time spent compiling! :-)
    //
    // Each of the nested classes holds a pointer to the SphereSegment
    // 'parent', which stores the geometry details, and performs any
    // work required. The nested classes are lightweight objects which
    // just pass the work on.
    //
    // Why are things done with these sub-Drawables? Alpha-blended
    // Drawables need to be drawn last, depth sorted, and the various
    // components of a SphereSegment also need to be depth sorted
    // against one another (they may all be drawn with alpha blending).
    // Making these Drawables allows us to get the OSG to depth sort
    // for us.

    class Surface;
    friend class Surface;
    bool Surface_computeBound(osg::BoundingBox&) const;
    void Surface_drawImplementation(osg::State&) const;

    class EdgeLine;
    friend class EdgeLine;
    bool EdgeLine_computeBound(osg::BoundingBox&) const;
    void EdgeLine_drawImplementation(osg::State&) const;

    enum BoundaryAngle{MIN,MAX};        // Why here and not in Side class? Because we can't forward
    enum SideOrientation{AZIM,ELEV};   // declare enums, Side is in the .cpp, and this is tidier...
    class Side;
    friend class Side;
    bool Side_computeBound(osg::BoundingBox&, SideOrientation, BoundaryAngle) const;
    void Side_drawImplementation(osg::State&, SideOrientation, BoundaryAngle) const;

    class Spoke;
    friend class Spoke;
    bool Spoke_computeBound(osg::BoundingBox&, BoundaryAngle, BoundaryAngle) const;
    void Spoke_drawImplementation(osg::State&, BoundaryAngle, BoundaryAngle) const;

    // Sphere segment geometry details
    osg::Vec3 _centre;
    float _radius;
    float _azMin, _azMax, _elevMin, _elevMax;
    int _density;

    // Draw details
    int         _drawMask;
    osg::Vec4   _surfaceColor;
    osg::Vec4   _spokeColor;
    osg::Vec4   _edgeLineColor;
    osg::Vec4   _planeColor;
};

}

#endif



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值