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