285 lines
11 KiB
C++
285 lines
11 KiB
C++
/* -*-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>
|
|
#include <osg/Geometry>
|
|
|
|
namespace osgSim{
|
|
|
|
/**
|
|
A SphereSegment is a Geode to represent an portion of a sphere (potentially
|
|
the whole sphere). The sphere is aligned such that the line through the
|
|
sphere's poles is parallel to the z axis. The sphere segment
|
|
may be rendered various components switched on or off:
|
|
|
|
- The specified area of the sphere surface.
|
|
|
|
- An edge line around the boundary of the specified area
|
|
of the sphere surface.
|
|
|
|
- Four <i>spokes</i>, where a spoke is the line from
|
|
the sphere's centre to a corner of the rendered area.
|
|
|
|
- Four planar areas, where the planar areas are formed
|
|
between the spokes.
|
|
|
|
Caveats:
|
|
|
|
- It's worth noting that the line through the sphere's poles is
|
|
parallel to the z axis. This has implications when specifying the
|
|
area to be rendered, and specifying areas where the centre of
|
|
the rendered area <i>is</i> the Z axis may lead to unexpected
|
|
geometry.
|
|
|
|
- It's possible to render the whole sphere by specifying elevation
|
|
and azimuth ranges round the full 360 degrees. When doing
|
|
so you may consider switching the planes, spokes, and edge lines
|
|
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
|
|
to specify which parts of the sphere segment should be drawn. 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
|
|
};
|
|
|
|
|
|
/** Default constructor. */
|
|
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 -PI/2.0f to azMax 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);
|
|
|
|
/**
|
|
Construct by vector.
|
|
@param centre sphere centre
|
|
@param radius radius of sphere
|
|
@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)
|
|
@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);
|
|
|
|
void traverse(osg::NodeVisitor& nv);
|
|
|
|
/** 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 azimuth range in radians (with centre along vec)
|
|
@param elevRange elevation range in radians (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)[0]; }
|
|
|
|
/** 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)[0]; }
|
|
|
|
/** 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)[0]; }
|
|
|
|
/** Set the color of the planes. */
|
|
void setSideColor(const osg::Vec4& c);
|
|
|
|
/** Get the color of the planes. */
|
|
const osg::Vec4& getSideColor() const { return (*_sideColor)[0]; }
|
|
|
|
/** 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);
|
|
|
|
/** recompute the vertex positions of the rendering meshes/lines thtat represent the sphere segment.*/
|
|
void updatePositions();
|
|
|
|
/** recompute the primitives rendering meshes/lines thtat represent the sphere segment.*/
|
|
void updatePrimitives();
|
|
|
|
virtual osg::BoundingSphere computeBound() const;
|
|
|
|
private:
|
|
|
|
void init(); // Shared constructor code, generates the drawables
|
|
|
|
void dirty(); // Force re-calling of gl functions and bounding boxes
|
|
|
|
// Sphere segment geometry details
|
|
osg::Vec3 _centre;
|
|
float _radius;
|
|
float _azMin, _azMax, _elevMin, _elevMax;
|
|
int _density;
|
|
|
|
// Draw details
|
|
int _drawMask;
|
|
osg::ref_ptr<osg::Vec4Array> _surfaceColor;
|
|
osg::ref_ptr<osg::Vec4Array> _spokeColor;
|
|
osg::ref_ptr<osg::Vec4Array> _edgeLineColor;
|
|
osg::ref_ptr<osg::Vec4Array> _sideColor;
|
|
|
|
osg::ref_ptr<osg::Vec3Array> _vertices;
|
|
osg::ref_ptr<osg::Vec3Array> _normals;
|
|
|
|
osg::ref_ptr<osg::Geometry> _surfaceGeometry;
|
|
osg::ref_ptr<osg::Geometry> _spokesGeometry;
|
|
osg::ref_ptr<osg::Geometry> _edgeLineGeometry;
|
|
osg::ref_ptr<osg::Geometry> _sidesGeometry;
|
|
|
|
osg::ref_ptr<osg::StateSet> _litOpaqueState;
|
|
osg::ref_ptr<osg::StateSet> _unlitOpaqueState;
|
|
osg::ref_ptr<osg::StateSet> _litTransparentState;
|
|
osg::ref_ptr<osg::StateSet> _unlitTransparentState;
|
|
|
|
osg::StateSet* getLitStateSet(const osg::Vec4& color) { return (color.a()<1.0) ? _litTransparentState.get() : _litOpaqueState.get(); }
|
|
osg::StateSet* getUnlitStateSet(const osg::Vec4& color) { return (color.a()<1.0) ? _unlitTransparentState.get() : _unlitOpaqueState.get(); }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|