Files
OpenSceneGraph/src/osgUtil/SceneGraphBuilder.cpp
Robert Osfield aefd1513f4 Ported osg::Geometry across to supporting the aliasing of vertex, color and normal etc. calls to Vertex Attributes.
Added support for automatic aliasing of vertex, normal, color etc. arrays to Vertex Attribute equivelants.

Added new osg::GLBeginEndAdapter class for runtime conversion from glBegin/glEnd codes to vertex arrray equivelants.

Added automatic shader source conversion from gl_ to osg_ builtins.
2009-10-16 16:26:27 +00:00

538 lines
15 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.
*/
#include <osgUtil/SceneGraphBuilder>
#include <osg/Notify>
#include <osg/io_utils>
#include <osg/PrimitiveSet>
#include <osg/Texture>
#include <osg/AlphaFunc>
#include <osg/BlendFunc>
#include <osg/LineStipple>
#include <osg/Depth>
#include <osg/CullFace>
#include <osg/FrontFace>
#include <osg/LineWidth>
#include <osg/Point>
#include <osg/PolygonMode>
#include <osg/PolygonOffset>
#include <osg/PolygonStipple>
#include <osg/ShadeModel>
#include <osg/ShapeDrawable>
using namespace osgUtil;
SceneGraphBuilder::SceneGraphBuilder():
_statesetAssigned(false),
_normalSet(false),
_normal(0.0f,0.0f,1.0f),
_colorSet(false),
_color(1.0f,1.0f,1.0f,1.0f),
_maxNumTexCoordComponents(0),
_texCoord(0.f,0.0f,0.0f,1.0f)
{
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// OpenGL 1.0 building methods
//
void SceneGraphBuilder::PushMatrix()
{
if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
else _matrixStack.push_back(_matrixStack.back());
}
void SceneGraphBuilder::PopMatrix()
{
if (!_matrixStack.empty()) _matrixStack.pop_back();
matrixChanged();
}
void SceneGraphBuilder::LoadIdentity()
{
if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
_matrixStack.back().makeIdentity();
matrixChanged();
}
void SceneGraphBuilder::LoadMatrixd(const GLdouble* m)
{
if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
_matrixStack.back().set(m);
matrixChanged();
}
void SceneGraphBuilder::MultMatrixd(const GLdouble* m)
{
if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
_matrixStack.back().preMult(osg::Matrixd(m));
matrixChanged();
}
void SceneGraphBuilder::Translated(GLdouble x, GLdouble y, GLdouble z)
{
if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
_matrixStack.back().preMultTranslate(osg::Vec3d(x,y,z));
matrixChanged();
}
void SceneGraphBuilder::Scaled(GLdouble x, GLdouble y, GLdouble z)
{
if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
_matrixStack.back().preMultScale(osg::Vec3d(x,y,z));
matrixChanged();
}
void SceneGraphBuilder::Rotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
{
if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
_matrixStack.back().preMultRotate(osg::Quat(osg::inDegrees(angle),osg::Vec3d(x,y,z)));
matrixChanged();
}
void SceneGraphBuilder::BlendFunc(GLenum srcFactor, GLenum dstFactor)
{
addAttribute(new osg::BlendFunc(srcFactor, dstFactor));
}
void SceneGraphBuilder::CullFace(GLenum mode)
{
addAttribute(new osg::CullFace(osg::CullFace::Mode(mode)));
}
void SceneGraphBuilder::DepthFunc(GLenum mode)
{
addAttribute(new osg::Depth(osg::Depth::Function(mode)));
}
void SceneGraphBuilder::FrontFace(GLenum mode)
{
addAttribute(new osg::FrontFace(osg::FrontFace::Mode(mode)));
}
void SceneGraphBuilder::LineStipple(GLint factor, GLushort pattern)
{
addAttribute(new osg::LineStipple(factor, pattern));
}
void SceneGraphBuilder::LineWidth(GLfloat lineWidth)
{
addAttribute(new osg::LineWidth(lineWidth));
}
void SceneGraphBuilder::PointSize(GLfloat pointSize)
{
addAttribute(new osg::Point(pointSize));
}
void SceneGraphBuilder::PolygonMode(GLenum face, GLenum mode)
{
addAttribute(new osg::PolygonMode(osg::PolygonMode::Face(face),osg::PolygonMode::Mode(mode)));
}
void SceneGraphBuilder::PolygonOffset(GLfloat factor, GLfloat units)
{
addAttribute(new osg::PolygonOffset(factor,units));
}
void SceneGraphBuilder::PolygonStipple(const GLubyte* mask)
{
addAttribute(new osg::PolygonStipple(mask));
}
void SceneGraphBuilder::ShadeModel(GLenum mode)
{
addAttribute(new osg::ShadeModel(osg::ShadeModel::Mode(mode)));
}
void SceneGraphBuilder::Enable(GLenum mode)
{
addMode(mode, true);
}
void SceneGraphBuilder::Disable(GLenum mode)
{
addMode(mode, false);
}
void SceneGraphBuilder::Color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
{
_normalSet = true;
_color.set(red,green,blue,alpha);
}
void SceneGraphBuilder::Normal3f(GLfloat x, GLfloat y, GLfloat z)
{
_normalSet = true;
_normal.set(x,y,z);
}
void SceneGraphBuilder::TexCoord1f(GLfloat x)
{
_maxNumTexCoordComponents = 1;
_texCoord.set(x,0.0f,0.0f,1.0f);
}
void SceneGraphBuilder::TexCoord2f(GLfloat x, GLfloat y)
{
_maxNumTexCoordComponents = 2;
_texCoord.set(x,y,0.0f,1.0f);
}
void SceneGraphBuilder::TexCoord3f(GLfloat x, GLfloat y, GLfloat z)
{
_maxNumTexCoordComponents = 3;
_texCoord.set(x,y,z,1.0);
}
void SceneGraphBuilder::TexCoord4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
_maxNumTexCoordComponents = 4;
_texCoord.set(x,y,z,w);
}
void SceneGraphBuilder::Vertex3f(GLfloat x, GLfloat y, GLfloat z)
{
osg::Vec3 vertex(x,y,z);
vertex = vertex * _matrixStack.back();
if (_vertices.valid()) _vertices->push_back(vertex);
if (_normal.valid()) _normals->push_back(_normal);
if (_colors.valid()) _colors->push_back(_color);
if (_texCoords.valid()) _texCoords->push_back(_texCoord);
}
void SceneGraphBuilder::Begin(GLenum mode)
{
// reset geometry
_primitiveMode = mode;
_vertices = new osg::Vec3Array;
_normalSet = false;
_normals = new osg::Vec3Array;
_colorSet = false;
_colors = new osg::Vec4Array;
_maxNumTexCoordComponents = 0;
_texCoords = new osg::Vec4Array;
}
void SceneGraphBuilder::End()
{
allocateGeometry();
_geometry->setVertexArray(_vertices.get());
if (_colorSet)
{
_geometry->setColorArray(_colors.get());
_geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
}
else
{
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(_color);
_geometry->setColorArray(colors);
_geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
}
if (_normalSet)
{
_geometry->setNormalArray(_normals.get());
_geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
}
else
{
_geometry->setNormalBinding(osg::Geometry::BIND_OFF);
}
if (_maxNumTexCoordComponents==1)
{
// convert Vec4Array into FloatArray
osg::FloatArray* texCoords = new osg::FloatArray;
for(osg::Vec4Array::iterator itr = _texCoords->begin();
itr != _texCoords->end();
++itr)
{
texCoords->push_back(itr->x());
}
_geometry->setTexCoordArray(0, texCoords);
}
if (_maxNumTexCoordComponents==2)
{
// convert Vec4Array into FloatArray
osg::Vec2Array* texCoords = new osg::Vec2Array;
for(osg::Vec4Array::iterator itr = _texCoords->begin();
itr != _texCoords->end();
++itr)
{
texCoords->push_back(osg::Vec2(itr->x(),itr->y()));
}
_geometry->setTexCoordArray(0, texCoords);
}
if (_maxNumTexCoordComponents==3)
{
// convert Vec4Array into FloatArray
osg::Vec3Array* texCoords = new osg::Vec3Array;
for(osg::Vec4Array::iterator itr = _texCoords->begin();
itr != _texCoords->end();
++itr)
{
texCoords->push_back(osg::Vec3(itr->x(),itr->y(), itr->z()));
}
_geometry->setTexCoordArray(0, texCoords);
}
else if (_maxNumTexCoordComponents==4)
{
_geometry->setTexCoordArray(0, _texCoords.get());
}
_geometry->addPrimitiveSet(new osg::DrawArrays(_primitiveMode, 0, _vertices->size()));
completeGeometry();
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// GLU style building methods
//
void SceneGraphBuilder::QuadricDrawStyle(GLenum aDrawStyle)
{
_quadricState._drawStyle = aDrawStyle;
}
void SceneGraphBuilder::QuadricNormals(GLenum aNormals)
{
_quadricState._normals = aNormals;
}
void SceneGraphBuilder::QuadricOrientation(GLenum aOrientation)
{
_quadricState._orientation = aOrientation;
}
void SceneGraphBuilder::QuadricTexture(GLboolean aTexture)
{
_quadricState._texture = aTexture;
}
void SceneGraphBuilder::Cylinder(GLfloat aBase,
GLfloat aTop,
GLfloat aHeight,
GLint aSlices,
GLint aStacks)
{
osg::notify(osg::NOTICE)<<"SceneGraphBuilder::Cylinder("<<aBase<<", "<<aTop<<", "<<aHeight<<", "<<aSlices<<", "<<aStacks<<") not implemented yet"<<std::endl;
}
void SceneGraphBuilder::Disk(GLfloat inner,
GLfloat outer,
GLint slices,
GLint /*loops*/)
{
double angle = 0.0;
double delta = 2.0*osg::PI/double(slices-1);
if (_quadricState._normals!=GLU_NONE) Normal3f(0.0f,0.0f,1.0f);
switch(_quadricState._drawStyle)
{
case(GLU_POINT):
{
Begin(GL_POINTS);
if (_quadricState._texture) TexCoord2f(0.5f,0.5f);
Vertex3f(0.0f, 0.0f, 0.0f);
for(GLint i=0; i<slices; ++i, angle += delta)
{
if (_quadricState._texture) TexCoord2f(GLfloat(sin(angle)*0.5+0.5), GLfloat(cos(angle)*0.5+0.5));
Vertex3f(outer*GLfloat(sin(angle)), outer*GLfloat(cos(angle)), 0.0f);
}
End();
break;
}
case(GLU_LINE):
{
Begin(GL_LINE_LOOP);
for(GLint i=0; i<slices; ++i, angle += delta)
{
if (_quadricState._texture) TexCoord2f(GLfloat(sin(angle)*0.5+0.5), GLfloat(cos(angle)*0.5+0.5));
Vertex3f(outer*GLfloat(sin(angle)), outer*GLfloat(cos(angle)), 0.0f);
}
End();
break;
}
case(GLU_FILL):
{
Begin(GL_TRIANGLE_FAN);
if (_quadricState._texture) TexCoord2f(0.5f,0.5f);
Vertex3f(0.0f, 0.0f, 0.0f);
for(GLint i=0; i<slices; ++i, angle += delta)
{
if (_quadricState._texture) TexCoord2f(GLfloat(sin(angle)*0.5+0.5), GLfloat(cos(angle)*0.5+0.5));
Vertex3f(outer*GLfloat(sin(angle)), outer*GLfloat(cos(angle)), 0.0f);
}
End();
break;
}
case(GLU_SILHOUETTE):
{
Begin(GL_LINE_LOOP);
for(GLint i=0; i<slices; ++i, angle += delta)
{
if (_quadricState._texture) TexCoord2f(GLfloat(sin(angle)*0.5+0.5), GLfloat(cos(angle)*0.5+0.5));
Vertex3f(outer*GLfloat(sin(angle)), outer*GLfloat(cos(angle)), 0.0f);
}
End();
break;
}
}
}
void SceneGraphBuilder::PartialDisk(GLfloat inner,
GLfloat outer,
GLint slices,
GLint loops,
GLfloat start,
GLfloat sweep)
{
osg::notify(osg::NOTICE)<<"SceneGraphBuilder::PartialDisk("<<inner<<", "<<outer<<", "<<slices<<", "<<loops<<", "<<start<<", "<<sweep<<") not implemented yet."<<std::endl;
osg::notify(osg::NOTICE)<<" quadric("<<_quadricState._drawStyle<<", "<<_quadricState._normals<<", "<<_quadricState._orientation<<", "<<_quadricState._texture<<std::endl;
}
void SceneGraphBuilder::Sphere(GLfloat radius,
GLint /*slices*/,
GLint /*stacks*/)
{
addShape(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f), radius));
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// General scene graph building methods
//
osg::Node* SceneGraphBuilder::getScene()
{
if (_group.valid() && _group->getNumChildren()>0) return _group.get();
else if (_transform.valid() && _transform->getNumChildren()>0) return _transform.get();
else if (_geode.valid() && _geode->getNumDrawables()>0) return _geode.get();
return 0;
}
osg::Node* SceneGraphBuilder::takeScene()
{
osg::ref_ptr<osg::Node> node;
if (_group.valid() && _group->getNumChildren()>0) node = _group.get();
else if (_transform.valid() && _transform->getNumChildren()>0) node = _transform.get();
else if (_geode.valid() && _geode->getNumDrawables()>0) node = _geode.get();
// reset all the pointers to properly release the scene graph
_geometry = 0;
_geode = 0;
_transform = 0;
_group = 0;
return node.release();
}
void SceneGraphBuilder::matrixChanged()
{
}
void SceneGraphBuilder::addAttribute(osg::StateAttribute* attribute)
{
allocateStateSet();
_stateset->setAttribute(attribute);
}
void SceneGraphBuilder::addMode(GLenum mode, bool enabled)
{
allocateStateSet();
_stateset->setMode(mode, enabled ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
}
void SceneGraphBuilder::addTextureAttribute(unsigned int unit, osg::StateAttribute* attribute)
{
allocateStateSet();
_stateset->setTextureAttribute(unit, attribute);
}
void SceneGraphBuilder::addTextureMode(unsigned int unit, GLenum mode, bool enabled)
{
allocateStateSet();
_stateset->setTextureMode(unit, mode, enabled ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
}
void SceneGraphBuilder::addShape(osg::Shape* shape)
{
osg::ShapeDrawable* sd = new osg::ShapeDrawable(shape);
sd->setColor(_color);
addDrawable(sd);
}
void SceneGraphBuilder::addDrawable(osg::Drawable* drawable)
{
if (!_geode) _geode = new osg::Geode;
if (_stateset.valid())
{
drawable->setStateSet(_stateset.get());
_statesetAssigned = true;
}
_geode->addDrawable(drawable);
}
void SceneGraphBuilder::allocateStateSet()
{
if (_statesetAssigned)
{
_stateset = dynamic_cast<osg::StateSet*>(_stateset->clone(osg::CopyOp::SHALLOW_COPY));
_statesetAssigned = false;
}
if (!_stateset) _stateset = new osg::StateSet;
}
void SceneGraphBuilder::allocateGeometry()
{
if (!_geometry)
{
_geometry = new osg::Geometry;
}
}
void SceneGraphBuilder::completeGeometry()
{
if (_geometry.valid()) addDrawable(_geometry.get());
_geometry = 0;
}