From Gino van den Bergen, "I've refactored the single ReadedWriterVRML2.cpp into multiple files. The reason for doing this was to break up the horribly long function
osg::ref_ptr<osg::Node> ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) The fixes are: * Added the source's parent directory as search directory for image files. * The material properties are now set in the stateset of the Geode rather than the Geometry. This will allow geometries to be reused with different material properties in future updates. NB: I planned for a caching scheme in which multiple occurences of the same primitive (e.g., Cylinders with radius 0.8 and height 1.2), would use the same Geometry object. Unfortunately, my planning moved me to other areas, but I might still finish the caching scheme in a quiet hour. For the time being I decided it would be a good thing to already submit my current changes. "
This commit is contained in:
@@ -11,7 +11,15 @@ ELSE(WIN32)
|
||||
SET(TARGET_LIBRARIES_VARS OPENVRML_LIBRARY)
|
||||
ENDIF(WIN32)
|
||||
|
||||
SET(TARGET_SRC ReaderWriterVRML2.cpp )
|
||||
SET(TARGET_SRC
|
||||
IndexedFaceSet.cpp
|
||||
Primitives.cpp
|
||||
ReaderWriterVRML2.cpp
|
||||
)
|
||||
|
||||
SET(TARGET_H
|
||||
ReaderWriterVRML2.h
|
||||
)
|
||||
|
||||
#### end var setup ###
|
||||
SETUP_PLUGIN(vrml)
|
||||
|
||||
329
src/osgPlugins/vrml/IndexedFaceSet.cpp
Normal file
329
src/osgPlugins/vrml/IndexedFaceSet.cpp
Normal file
@@ -0,0 +1,329 @@
|
||||
// -*-c++-*-
|
||||
|
||||
#include "ReaderWriterVRML2.h"
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable: 4250)
|
||||
# pragma warning(disable: 4290)
|
||||
# pragma warning(disable: 4800)
|
||||
#endif
|
||||
|
||||
#include <openvrml/vrml97node.h>
|
||||
#include <openvrml/common.h>
|
||||
#include <openvrml/node.h>
|
||||
#include <openvrml/node_ptr.h>
|
||||
#include <openvrml/field.h>
|
||||
|
||||
#include <osg/CullFace>
|
||||
|
||||
|
||||
osg::ref_ptr<osg::Geometry> ReaderWriterVRML2::convertVRML97IndexedFaceSet(openvrml::vrml97_node::indexed_face_set_node *vrml_ifs)
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> osg_geom = new osg::Geometry();
|
||||
|
||||
osg_geom->addPrimitiveSet(new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON));
|
||||
osg::StateSet *osg_stateset = osg_geom->getOrCreateStateSet();
|
||||
|
||||
// get array of vertex coordinate_nodes
|
||||
{
|
||||
const openvrml::field_value& fv = vrml_ifs->field("coord");
|
||||
const openvrml::sfnode& sfn = dynamic_cast<const openvrml::sfnode&>(fv);
|
||||
openvrml::vrml97_node::coordinate_node* vrml_coord_node = dynamic_cast<openvrml::vrml97_node::coordinate_node*>(sfn.value.get());
|
||||
|
||||
const std::vector<openvrml::vec3f>& vrml_coord = vrml_coord_node->point();
|
||||
osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < vrml_coord.size(); i++)
|
||||
{
|
||||
openvrml::vec3f vec = vrml_coord[i];
|
||||
osg_vertices->push_back(osg::Vec3(vec[0], vec[1], vec[2]));
|
||||
}
|
||||
|
||||
osg_geom->setVertexArray(osg_vertices.get());
|
||||
|
||||
// get array of vertex indices
|
||||
const openvrml::field_value &fv2 = vrml_ifs->field("coordIndex");
|
||||
const openvrml::mfint32 &vrml_coord_index = dynamic_cast<const openvrml::mfint32 &>(fv2);
|
||||
|
||||
osg::ref_ptr<osg::IntArray> osg_vert_index = new osg::IntArray();
|
||||
|
||||
int num_vert = 0;
|
||||
for (i = 0; i < vrml_coord_index.value.size(); i++)
|
||||
{
|
||||
int index = vrml_coord_index.value[i];
|
||||
if (index == -1)
|
||||
{
|
||||
static_cast<osg::DrawArrayLengths*>(osg_geom->getPrimitiveSet(0))->push_back(num_vert);
|
||||
num_vert = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
osg_vert_index->push_back(index);
|
||||
++num_vert;
|
||||
}
|
||||
}
|
||||
if (num_vert)
|
||||
{
|
||||
//GvdB: Last coordIndex wasn't -1
|
||||
static_cast<osg::DrawArrayLengths*>(osg_geom->getPrimitiveSet(0))->push_back(num_vert);
|
||||
}
|
||||
|
||||
osg_geom->setVertexIndices(osg_vert_index.get());
|
||||
}
|
||||
|
||||
{
|
||||
// get texture coordinate_nodes
|
||||
const openvrml::field_value &fv = vrml_ifs->field("texCoord");
|
||||
const openvrml::sfnode &sfn = dynamic_cast<const openvrml::sfnode &>(fv);
|
||||
openvrml::vrml97_node::texture_coordinate_node *vrml_tex_coord_node =
|
||||
dynamic_cast<openvrml::vrml97_node::texture_coordinate_node *>(sfn.value.get());
|
||||
|
||||
if (vrml_tex_coord_node != 0) // if no texture, node is NULL pointer
|
||||
{
|
||||
const std::vector<openvrml::vec2f> &vrml_tex_coord = vrml_tex_coord_node->point();
|
||||
osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < vrml_tex_coord.size(); i++)
|
||||
{
|
||||
openvrml::vec2f vec = vrml_tex_coord[i];
|
||||
osg_texcoords->push_back(osg::Vec2(vec[0], vec[1]));
|
||||
}
|
||||
|
||||
osg_geom->setTexCoordArray(0, osg_texcoords.get());
|
||||
|
||||
// get array of texture indices
|
||||
const openvrml::field_value &fv2 = vrml_ifs->field("texCoordIndex");
|
||||
const openvrml::mfint32 &vrml_tex_coord_index = dynamic_cast<const openvrml::mfint32 &>(fv2);
|
||||
|
||||
osg::ref_ptr<osg::IntArray> osg_tex_coord_index = new osg::IntArray();
|
||||
|
||||
if(vrml_tex_coord_index.value.size() > 0)
|
||||
{
|
||||
for (i = 0; i < vrml_tex_coord_index.value.size(); i++)
|
||||
{
|
||||
int index = vrml_tex_coord_index.value[i];
|
||||
if (index != -1) {
|
||||
osg_tex_coord_index->push_back(index);
|
||||
}
|
||||
}
|
||||
osg_geom->setTexCoordIndices(0, osg_tex_coord_index.get());
|
||||
} else
|
||||
// no indices defined, use coordIndex
|
||||
osg_geom->setTexCoordIndices(0, osg_geom->getVertexIndices());
|
||||
}
|
||||
}
|
||||
|
||||
// get array of normals per vertex (if specified)
|
||||
{
|
||||
const openvrml::field_value& fv = vrml_ifs->field("normal");
|
||||
const openvrml::sfnode& sfn = dynamic_cast<const openvrml::sfnode&>(fv);
|
||||
openvrml::vrml97_node::normal_node* vrml_normal_node = dynamic_cast<openvrml::vrml97_node::normal_node*>(sfn.value.get());
|
||||
|
||||
if (vrml_normal_node != 0) // if no normals, node is NULL pointer
|
||||
{
|
||||
const std::vector<openvrml::vec3f>& vrml_normal_coord = vrml_normal_node->vector();
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osg_normalcoords = new osg::Vec3Array();
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < vrml_normal_coord.size(); i++)
|
||||
{
|
||||
const openvrml::vec3f vec = vrml_normal_coord[i];
|
||||
osg_normalcoords->push_back(osg::Vec3(vec[0], vec[1], vec[2]));
|
||||
}
|
||||
osg_geom->setNormalArray(osg_normalcoords.get());
|
||||
|
||||
// get array of normal indices
|
||||
const openvrml::field_value& fv2 = vrml_ifs->field("normalIndex");
|
||||
const openvrml::mfint32& vrml_normal_index = dynamic_cast<const openvrml::mfint32&>(fv2);
|
||||
|
||||
osg::ref_ptr<osg::IntArray> osg_normal_index = new osg::IntArray();
|
||||
|
||||
if (vrml_normal_index.value.size() > 0)
|
||||
{
|
||||
for (i = 0; i < vrml_normal_index.value.size(); i++)
|
||||
{
|
||||
int index = vrml_normal_index.value[i];
|
||||
if (index != -1)
|
||||
{
|
||||
osg_normal_index->push_back(index);
|
||||
}
|
||||
}
|
||||
osg_geom->setNormalIndices(osg_normal_index.get());
|
||||
}
|
||||
else
|
||||
// unspecified, use the coordIndex field
|
||||
osg_geom->setNormalIndices(osg_geom->getVertexIndices());
|
||||
|
||||
// get normal binding
|
||||
const openvrml::field_value &fv3 = vrml_ifs->field("normalPerVertex");
|
||||
const openvrml::sfbool &vrml_norm_per_vertex = dynamic_cast<const openvrml::sfbool &>(fv3);
|
||||
|
||||
if (vrml_norm_per_vertex.value)
|
||||
{
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
} else
|
||||
{
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get array of colours per vertex (if specified)
|
||||
{
|
||||
const openvrml::field_value &fv = vrml_ifs->field("color");
|
||||
const openvrml::sfnode &sfn = dynamic_cast<const openvrml::sfnode &>(fv);
|
||||
openvrml::vrml97_node::color_node *vrml_color_node =
|
||||
dynamic_cast<openvrml::vrml97_node::color_node *>(sfn.value.get());
|
||||
|
||||
if (vrml_color_node != 0) // if no colors, node is NULL pointer
|
||||
{
|
||||
const std::vector<openvrml::color> &vrml_colors = vrml_color_node->color();
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osg_colors = new osg::Vec3Array();
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < vrml_colors.size(); i++)
|
||||
{
|
||||
const openvrml::color color = vrml_colors[i];
|
||||
osg_colors->push_back(osg::Vec3(color.r(), color.g(), color.b()));
|
||||
}
|
||||
osg_geom->setColorArray(osg_colors.get());
|
||||
|
||||
// get array of color indices
|
||||
const openvrml::field_value &fv2 = vrml_ifs->field("colorIndex");
|
||||
const openvrml::mfint32 &vrml_color_index = dynamic_cast<const openvrml::mfint32 &>(fv2);
|
||||
|
||||
osg::ref_ptr<osg::IntArray> osg_color_index = new osg::IntArray();
|
||||
|
||||
if(vrml_color_index.value.size() > 0)
|
||||
{
|
||||
for (i = 0; i < vrml_color_index.value.size(); i++)
|
||||
{
|
||||
int index = vrml_color_index.value[i];
|
||||
if (index != -1) {
|
||||
osg_color_index->push_back(index);
|
||||
}
|
||||
}
|
||||
osg_geom->setColorIndices(osg_color_index.get());
|
||||
} else
|
||||
// unspecified, use coordIndices field
|
||||
osg_geom->setColorIndices(osg_geom->getVertexIndices());
|
||||
|
||||
// get color binding
|
||||
const openvrml::field_value &fv3 = vrml_ifs->field("colorPerVertex");
|
||||
const openvrml::sfbool &vrml_color_per_vertex = dynamic_cast<const openvrml::sfbool &>(fv3);
|
||||
|
||||
if (vrml_color_per_vertex.value)
|
||||
{
|
||||
osg_geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
} else
|
||||
{
|
||||
osg_geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (static_cast<const openvrml::sfbool&>(vrml_ifs->field("solid")).value)
|
||||
{
|
||||
osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
||||
}
|
||||
|
||||
if (!osg_geom->getNormalArray())
|
||||
{
|
||||
#if 0
|
||||
// GvdB: This is what I wanted to do, but got zero normals since the triangles were considered temporaries (?)
|
||||
osgUtil::SmoothingVisitor().smooth(*osg_geom);
|
||||
#else
|
||||
// GvdB: So I ended up computing the smoothing normals myself. Also, I might add support for "creaseAngle" if a big need for it rises.
|
||||
// However, for now I can perfectly live with the fact that all edges are smoothed despite the use of a crease angle.
|
||||
osg::Vec3Array& coords = *static_cast<osg::Vec3Array*>(osg_geom->getVertexArray());
|
||||
assert(coords.size());
|
||||
|
||||
osg::Vec3Array* normals = new osg::Vec3Array(coords.size());
|
||||
|
||||
for (osg::Vec3Array::iterator it = normals->begin(); it != normals->end(); ++it)
|
||||
{
|
||||
(*it).set(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
osg::IntArray& indices = *static_cast<osg::IntArray*>(osg_geom->getVertexIndices());
|
||||
osg::DrawArrayLengths& lengths = *static_cast<osg::DrawArrayLengths*>(osg_geom->getPrimitiveSet(0));
|
||||
int index = 0;
|
||||
|
||||
for (osg::DrawArrayLengths::iterator it = lengths.begin(); it != lengths.end(); ++it)
|
||||
{
|
||||
assert(*it >= 3);
|
||||
const osg::Vec3& v0 = coords[indices[index]];
|
||||
const osg::Vec3& v1 = coords[indices[index + 1]];
|
||||
const osg::Vec3& v2 = coords[indices[index + 2]];
|
||||
|
||||
osg::Vec3 normal = (v1 - v0) ^ (v2 - v0);
|
||||
normal.normalize();
|
||||
|
||||
for (int i = 0; i != *it; ++i)
|
||||
{
|
||||
(*normals)[indices[index + i]] += normal;
|
||||
}
|
||||
|
||||
index += *it;
|
||||
}
|
||||
|
||||
assert(index == indices.size());
|
||||
|
||||
for(osg::Vec3Array::iterator it = normals->begin(); it != normals->end(); ++it)
|
||||
{
|
||||
(*it).normalize();
|
||||
}
|
||||
|
||||
osg_geom->setNormalArray(normals);
|
||||
osg_geom->setNormalIndices(osg_geom->getVertexIndices());
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
osg::DrawArrayLengths& lengths = *static_cast<osg::DrawArrayLengths*>(osg_geom->getPrimitiveSet(0));
|
||||
|
||||
osg::DrawArrayLengths::iterator it = lengths.begin();
|
||||
if (it != lengths.end())
|
||||
{
|
||||
switch (*it)
|
||||
{
|
||||
case 3:
|
||||
while (++it != lengths.end() && *it == 3)
|
||||
;
|
||||
|
||||
if (it == lengths.end())
|
||||
{
|
||||
// All polys are triangles
|
||||
osg::ref_ptr<osg::DrawArrays> mesh = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES);
|
||||
mesh->setCount(lengths.size() * 3);
|
||||
osg_geom->removePrimitiveSet(0);
|
||||
osg_geom->addPrimitiveSet(mesh.get());
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
while (++it != lengths.end() && *it == 4)
|
||||
;
|
||||
|
||||
if (it == lengths.end())
|
||||
{
|
||||
// All polys are quads
|
||||
osg::ref_ptr<osg::DrawArrays> mesh = new osg::DrawArrays(osg::PrimitiveSet::QUADS);
|
||||
mesh->setCount(lengths.size() * 4);
|
||||
osg_geom->removePrimitiveSet(0);
|
||||
osg_geom->addPrimitiveSet(mesh.get());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return osg_geom.get();
|
||||
}
|
||||
395
src/osgPlugins/vrml/Primitives.cpp
Normal file
395
src/osgPlugins/vrml/Primitives.cpp
Normal file
@@ -0,0 +1,395 @@
|
||||
// -*-c++-*-
|
||||
|
||||
#include "ReaderWriterVRML2.h"
|
||||
|
||||
#include <complex>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable: 4250)
|
||||
# pragma warning(disable: 4290)
|
||||
# pragma warning(disable: 4800)
|
||||
#endif
|
||||
|
||||
#include <openvrml/vrml97node.h>
|
||||
#include <openvrml/common.h>
|
||||
#include <openvrml/node.h>
|
||||
#include <openvrml/node_ptr.h>
|
||||
#include <openvrml/field.h>
|
||||
|
||||
#include <osg/CullFace>
|
||||
|
||||
osg::ref_ptr<osg::Geometry> ReaderWriterVRML2::convertVRML97Box(openvrml::vrml97_node::box_node* vrml_box)
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> osg_geom = new osg::Geometry();
|
||||
|
||||
const openvrml::vec3f& size = static_cast<const openvrml::sfvec3f&>(vrml_box->field("size")).value;
|
||||
|
||||
osg::Vec3 halfSize(size[0] * 0.5f, size[1] * 0.5f, size[2] * 0.5f);
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
|
||||
osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
|
||||
osg::ref_ptr<osg::Vec3Array> osg_normals = new osg::Vec3Array();
|
||||
|
||||
osg::ref_ptr<osg::DrawArrays> box = new osg::DrawArrays(osg::PrimitiveSet::QUADS);
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2]));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2]));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2]));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2]));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2]));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2]));
|
||||
|
||||
for (int i = 0; i != 6; ++i)
|
||||
{
|
||||
osg_texcoords->push_back(osg::Vec2(0.0f, 1.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f));
|
||||
}
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
|
||||
osg_normals->push_back(osg::Vec3(0.0f, 0.0f, -1.0f));
|
||||
osg_normals->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));
|
||||
osg_normals->push_back(osg::Vec3(-1.0f, 0.0f, 0.0f));
|
||||
osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));
|
||||
osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
|
||||
|
||||
box->setCount(osg_vertices->size());
|
||||
|
||||
osg_geom->addPrimitiveSet(box.get());
|
||||
|
||||
osg_geom->setVertexArray(osg_vertices.get());
|
||||
osg_geom->setTexCoordArray(0, osg_texcoords.get());
|
||||
osg_geom->setNormalArray(osg_normals.get());
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
|
||||
|
||||
osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
||||
|
||||
return osg_geom.get();
|
||||
}
|
||||
|
||||
|
||||
osg::ref_ptr<osg::Geometry> ReaderWriterVRML2::convertVRML97Sphere(openvrml::vrml97_node::sphere_node* vrml_sphere)
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> osg_geom = new osg::Geometry();
|
||||
|
||||
float radius = static_cast<const openvrml::sffloat&>(vrml_sphere->field("radius")).value;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
|
||||
osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
|
||||
osg::ref_ptr<osg::Vec3Array> osg_normals = new osg::Vec3Array();
|
||||
|
||||
unsigned int numSegments = 40;
|
||||
unsigned int numRows = 20;
|
||||
|
||||
const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments);
|
||||
const float texCoordSDelta = 1.0f / float(numSegments);
|
||||
const float phiDelta = float(osg::PI) / float(numRows);
|
||||
const float texCoordTDelta = 1.0f / float(numRows);
|
||||
|
||||
float phi = -0.5f * float(osg::PI);
|
||||
float texCoordT = 0.0f;
|
||||
|
||||
osg::ref_ptr<osg::DrawArrayLengths> sphere = new osg::DrawArrayLengths(osg::PrimitiveSet::QUAD_STRIP);
|
||||
|
||||
for (unsigned int i = 0; i < numRows; ++i, phi += phiDelta, texCoordT += texCoordTDelta)
|
||||
{
|
||||
std::complex<float> latBottom = std::polar(1.0f, phi);
|
||||
std::complex<float> latTop = std::polar(1.0f, phi + phiDelta);
|
||||
std::complex<float> eBottom = latBottom * radius;
|
||||
std::complex<float> eTop = latTop * radius;
|
||||
|
||||
float theta = 0.0f;
|
||||
float texCoordS = 0.0f;
|
||||
|
||||
for (unsigned int j = 0; j < numSegments; ++j, theta += thetaDelta, texCoordS += texCoordSDelta)
|
||||
{
|
||||
std::complex<float> n = -std::polar(1.0f, theta);
|
||||
|
||||
osg_normals->push_back(osg::Vec3(latTop.real() * n.imag(), latTop.imag(), latTop.real() * n.real()));
|
||||
osg_normals->push_back(osg::Vec3(latBottom.real() * n.imag(), latBottom.imag(), latBottom.real() * n.real()));
|
||||
|
||||
osg_texcoords->push_back(osg::Vec2(texCoordS, texCoordT + texCoordTDelta));
|
||||
osg_texcoords->push_back(osg::Vec2(texCoordS, texCoordT));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(eTop.real() * n.imag(), eTop.imag(), eTop.real() * n.real()));
|
||||
osg_vertices->push_back(osg::Vec3(eBottom.real() * n.imag(), eBottom.imag(), eBottom.real() * n.real()));
|
||||
}
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, latTop.imag(), -latTop.real()));
|
||||
osg_normals->push_back(osg::Vec3(0.0f, latBottom.imag(), -latBottom.real()));
|
||||
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, texCoordT + texCoordTDelta));
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, texCoordT));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, eTop.imag(), -eTop.real()));
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, eBottom.imag(), -eBottom.real()));
|
||||
|
||||
sphere->push_back(numSegments * 2 + 2);
|
||||
}
|
||||
|
||||
osg_geom->addPrimitiveSet(sphere.get());
|
||||
|
||||
osg_geom->setVertexArray(osg_vertices.get());
|
||||
osg_geom->setTexCoordArray(0, osg_texcoords.get());
|
||||
osg_geom->setNormalArray(osg_normals.get());
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
||||
|
||||
return osg_geom.get();
|
||||
}
|
||||
|
||||
|
||||
osg::ref_ptr<osg::Geometry> ReaderWriterVRML2::convertVRML97Cone(openvrml::vrml97_node::cone_node* vrml_cone)
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> osg_geom = new osg::Geometry();
|
||||
|
||||
float height = static_cast<const openvrml::sffloat&>(vrml_cone->field("height")).value;
|
||||
float radius = static_cast<const openvrml::sffloat&>(vrml_cone->field("bottomRadius")).value;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
|
||||
osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
|
||||
osg::ref_ptr<osg::Vec3Array> osg_normals = new osg::Vec3Array();
|
||||
|
||||
unsigned int numSegments = 40;
|
||||
|
||||
const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments);
|
||||
|
||||
float topY = height * 0.5f;
|
||||
float bottomY = height * -0.5f;
|
||||
|
||||
if (static_cast<const openvrml::sfbool&>(vrml_cone->field("side")).value)
|
||||
{
|
||||
osg::ref_ptr<osg::DrawArrays> side = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP);
|
||||
|
||||
const float texCoordDelta = 1.0f / float(numSegments);
|
||||
float theta = 0.0f;
|
||||
float texCoord = 0.0f;
|
||||
|
||||
for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta, texCoord += texCoordDelta)
|
||||
{
|
||||
std::complex<float> n = -std::polar(1.0f, theta);
|
||||
std::complex<float> e = n * radius;
|
||||
|
||||
osg::Vec3 normal(n.imag() * height, radius, n.real() * height);
|
||||
normal.normalize();
|
||||
|
||||
osg_normals->push_back(normal);
|
||||
osg_normals->push_back(normal);
|
||||
|
||||
osg_texcoords->push_back(osg::Vec2(texCoord, 1.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(texCoord, 0.0f));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, topY, 0.0f));
|
||||
osg_vertices->push_back(osg::Vec3(e.imag(), bottomY, e.real()));
|
||||
}
|
||||
|
||||
// do last point by hand to ensure no round off errors.
|
||||
|
||||
osg::Vec3 normal(0.0f, radius, -height);
|
||||
normal.normalize();
|
||||
|
||||
osg_normals->push_back(normal);
|
||||
osg_normals->push_back(normal);
|
||||
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, topY, 0.0f));
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius));
|
||||
|
||||
side->setCount(osg_vertices->size());
|
||||
osg_geom->addPrimitiveSet(side.get());
|
||||
}
|
||||
|
||||
if (static_cast<const openvrml::sfbool&>(vrml_cone->field("bottom")).value)
|
||||
{
|
||||
osg::ref_ptr<osg::DrawArrays> bottom = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN);
|
||||
|
||||
|
||||
size_t first = osg_vertices->size();
|
||||
bottom->setFirst(first);
|
||||
|
||||
float theta = 0.0f;
|
||||
|
||||
for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta)
|
||||
{
|
||||
std::complex<float> n = -std::polar(1.0f, theta);
|
||||
std::complex<float> e = n * radius;
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.5f - 0.5f * n.imag(), 0.5f + 0.5f * n.real()));
|
||||
osg_vertices->push_back(osg::Vec3(-e.imag(), bottomY, e.real()));
|
||||
}
|
||||
|
||||
// do last point by hand to ensure no round off errors.
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.5f, 0.0f));
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius));
|
||||
|
||||
bottom->setCount(osg_vertices->size() - first);
|
||||
osg_geom->addPrimitiveSet(bottom.get());
|
||||
}
|
||||
|
||||
osg_geom->setVertexArray(osg_vertices.get());
|
||||
osg_geom->setTexCoordArray(0, osg_texcoords.get());
|
||||
osg_geom->setNormalArray(osg_normals.get());
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
||||
|
||||
return osg_geom.get();
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Geometry> ReaderWriterVRML2::convertVRML97Cylinder(openvrml::vrml97_node::cylinder_node* vrml_cylinder)
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> osg_geom = new osg::Geometry();
|
||||
|
||||
float height = static_cast<const openvrml::sffloat&>(vrml_cylinder->field("height")).value;
|
||||
float radius = static_cast<const openvrml::sffloat&>(vrml_cylinder->field("radius")).value;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
|
||||
osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
|
||||
osg::ref_ptr<osg::Vec3Array> osg_normals = new osg::Vec3Array();
|
||||
|
||||
unsigned int numSegments = 40;
|
||||
|
||||
const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments);
|
||||
|
||||
|
||||
float topY = height * 0.5f;
|
||||
float bottomY = height * -0.5f;
|
||||
|
||||
if (static_cast<const openvrml::sfbool&>(vrml_cylinder->field("side")).value)
|
||||
{
|
||||
osg::ref_ptr<osg::DrawArrays> side = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP);
|
||||
|
||||
const float texCoordDelta = 1.0f / float(numSegments);
|
||||
float theta = 0.0f;
|
||||
float texCoord = 0.0f;
|
||||
|
||||
for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta, texCoord += texCoordDelta)
|
||||
{
|
||||
std::complex<float> n = -std::polar(1.0f, theta);
|
||||
std::complex<float> e = n * radius;
|
||||
|
||||
osg::Vec3 normal(n.imag(), 0.0f, n.real());
|
||||
|
||||
osg_normals->push_back(normal);
|
||||
osg_normals->push_back(normal);
|
||||
|
||||
osg_texcoords->push_back(osg::Vec2(texCoord, 1.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(texCoord, 0.0f));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(e.imag(), topY, e.real()));
|
||||
osg_vertices->push_back(osg::Vec3(e.imag(), bottomY, e.real()));
|
||||
}
|
||||
|
||||
// do last point by hand to ensure no round off errors.
|
||||
|
||||
osg::Vec3 normal(0.0f, 0.0f, -1.0f);
|
||||
osg_normals->push_back(normal);
|
||||
osg_normals->push_back(normal);
|
||||
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, topY, -radius));
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius));
|
||||
|
||||
side->setCount(osg_vertices->size());
|
||||
osg_geom->addPrimitiveSet(side.get());
|
||||
}
|
||||
|
||||
if (static_cast<const openvrml::sfbool&>(vrml_cylinder->field("bottom")).value)
|
||||
{
|
||||
osg::ref_ptr<osg::DrawArrays> bottom = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN);
|
||||
|
||||
size_t first = osg_vertices->size();
|
||||
bottom->setFirst(first);
|
||||
|
||||
float theta = 0.0f;
|
||||
|
||||
for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta)
|
||||
{
|
||||
std::complex<float> n = -std::polar(1.0f, theta);
|
||||
std::complex<float> e = n * radius;
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.5f - 0.5f * n.imag(), 0.5f + 0.5f * n.real()));
|
||||
osg_vertices->push_back(osg::Vec3(-e.imag(), bottomY, e.real()));
|
||||
}
|
||||
|
||||
// do last point by hand to ensure no round off errors.
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.5f, 0.0f));
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius));
|
||||
|
||||
bottom->setCount(osg_vertices->size() - first);
|
||||
osg_geom->addPrimitiveSet(bottom.get());
|
||||
}
|
||||
|
||||
if (static_cast<const openvrml::sfbool&>(vrml_cylinder->field("top")).value)
|
||||
{
|
||||
osg::ref_ptr<osg::DrawArrays> top = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN);
|
||||
|
||||
size_t first = osg_vertices->size();
|
||||
top->setFirst(first);
|
||||
|
||||
float theta = 0.0f;
|
||||
|
||||
for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta)
|
||||
{
|
||||
std::complex<float> n = -std::polar(1.0f, theta);
|
||||
std::complex<float> e = n * radius;
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.5f + 0.5f * n.imag(), 0.5f - 0.5f * n.real()));
|
||||
osg_vertices->push_back(osg::Vec3(e.imag(), topY, e.real()));
|
||||
}
|
||||
|
||||
// do last point by hand to ensure no round off errors.
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.5f, 1.0f));
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, topY, -radius));
|
||||
|
||||
top->setCount(osg_vertices->size() - first);
|
||||
osg_geom->addPrimitiveSet(top.get());
|
||||
}
|
||||
|
||||
osg_geom->setVertexArray(osg_vertices.get());
|
||||
osg_geom->setTexCoordArray(0, osg_texcoords.get());
|
||||
osg_geom->setNormalArray(osg_normals.get());
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
||||
|
||||
return osg_geom.get();
|
||||
}
|
||||
@@ -14,10 +14,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ReaderWriterVRML2.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <complex>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable: 4250)
|
||||
# pragma warning(disable: 4290)
|
||||
# pragma warning(disable: 4800)
|
||||
#endif
|
||||
|
||||
#include <openvrml/vrml97node.h>
|
||||
#include <openvrml/common.h>
|
||||
@@ -50,29 +56,6 @@
|
||||
#include <map>
|
||||
|
||||
|
||||
/**
|
||||
* OpenSceneGraph plugin wrapper/converter.
|
||||
*/
|
||||
class ReaderWriterVRML2 : public osgDB::ReaderWriter
|
||||
{
|
||||
public:
|
||||
ReaderWriterVRML2() { }
|
||||
|
||||
virtual const char* className()
|
||||
{
|
||||
return "VRML2 Reader/Writer";
|
||||
}
|
||||
|
||||
virtual bool acceptsExtension(const std::string& extension)
|
||||
{
|
||||
return osgDB::equalCaseInsensitive(extension, "wrl") ? true : false;
|
||||
}
|
||||
|
||||
virtual ReadResult readNode(const std::string&, const osgDB::ReaderWriter::Options *options = NULL) const;
|
||||
private:
|
||||
osg::ref_ptr<osg::Node> convertFromVRML(openvrml::node *obj) const;
|
||||
};
|
||||
|
||||
// Register with Registry to instantiate the above reader/writer.
|
||||
REGISTER_OSGPLUGIN(vrml, ReaderWriterVRML2)
|
||||
|
||||
@@ -95,6 +78,8 @@ osgDB::ReaderWriter::ReadResult ReaderWriterVRML2::readNode(const std::string &f
|
||||
else // relative path
|
||||
fileName = unixFileName;
|
||||
|
||||
|
||||
|
||||
std::fstream null;
|
||||
openvrml::browser *browser = new openvrml::browser(null, null);
|
||||
|
||||
@@ -115,17 +100,17 @@ osgDB::ReaderWriter::ReadResult ReaderWriterVRML2::readNode(const std::string &f
|
||||
0, 0, 1, 0,
|
||||
0, -1, 0, 0,
|
||||
0, 0, 0, 1));
|
||||
|
||||
osgDB::getDataFilePathList().push_front(osgDB::getFilePath(unixFileName));
|
||||
for (unsigned i = 0; i < mfn.size(); i++) {
|
||||
openvrml::node *vrml_node = mfn[i].get();
|
||||
osg_root->addChild(convertFromVRML(vrml_node).get());
|
||||
}
|
||||
|
||||
osgDB::getDataFilePathList().pop_front();
|
||||
return osg_root.get();
|
||||
}
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const
|
||||
osg::ref_ptr<osg::Node> ReaderWriterVRML2::convertFromVRML(openvrml::node *obj)
|
||||
{
|
||||
std::string name = obj->id();
|
||||
static int osgLightNum = 0; //light
|
||||
@@ -158,7 +143,8 @@ osg::ref_ptr<osg::Node> ReaderWriterVRML2::convertFromVRML(openvrml::node *obj)
|
||||
|
||||
return osg_group.get();
|
||||
|
||||
} else if (obj->type.id == "Transform") // Handle transforms
|
||||
}
|
||||
else if (obj->type.id == "Transform") // Handle transforms
|
||||
{
|
||||
openvrml::vrml97_node::transform_node *vrml_transform;
|
||||
vrml_transform = dynamic_cast<openvrml::vrml97_node::transform_node *>(obj);
|
||||
@@ -185,16 +171,10 @@ osg::ref_ptr<osg::Node> ReaderWriterVRML2::convertFromVRML(openvrml::node *obj)
|
||||
|
||||
return osg_m.get();
|
||||
|
||||
} else if (obj->type.id == "Shape") // Handle Shape node
|
||||
}
|
||||
else if (obj->type.id == "Shape") // Handle Shape node
|
||||
{
|
||||
osg::ref_ptr<osg::Geode> osg_geode = new osg::Geode();
|
||||
osg::ref_ptr<osg::Geometry> osg_geom = new osg::Geometry();
|
||||
osg_geode->addDrawable(osg_geom.get());
|
||||
osg::StateSet *osg_stateset = osg_geom->getOrCreateStateSet();
|
||||
|
||||
osg::ref_ptr<osg::Material> osg_mat = new osg::Material();
|
||||
osg_stateset->setAttributeAndModes(osg_mat.get());
|
||||
osg_mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
|
||||
osg::ref_ptr<osg::Geometry> osg_geom;
|
||||
|
||||
// parse the geometry
|
||||
{
|
||||
@@ -210,663 +190,23 @@ osg::ref_ptr<osg::Node> ReaderWriterVRML2::convertFromVRML(openvrml::node *obj)
|
||||
|
||||
if (openvrml::vrml97_node::indexed_face_set_node *vrml_ifs = dynamic_cast<openvrml::vrml97_node::indexed_face_set_node *>(vrml_geom))
|
||||
{
|
||||
osg_geom->addPrimitiveSet(new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON));
|
||||
|
||||
// get array of vertex coordinate_nodes
|
||||
{
|
||||
const openvrml::field_value& fv = vrml_ifs->field("coord");
|
||||
const openvrml::sfnode& sfn = dynamic_cast<const openvrml::sfnode&>(fv);
|
||||
openvrml::vrml97_node::coordinate_node* vrml_coord_node = dynamic_cast<openvrml::vrml97_node::coordinate_node*>(sfn.value.get());
|
||||
|
||||
const std::vector<openvrml::vec3f>& vrml_coord = vrml_coord_node->point();
|
||||
osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < vrml_coord.size(); i++)
|
||||
{
|
||||
openvrml::vec3f vec = vrml_coord[i];
|
||||
osg_vertices->push_back(osg::Vec3(vec[0], vec[1], vec[2]));
|
||||
}
|
||||
|
||||
osg_geom->setVertexArray(osg_vertices.get());
|
||||
|
||||
// get array of vertex indices
|
||||
const openvrml::field_value &fv2 = vrml_ifs->field("coordIndex");
|
||||
const openvrml::mfint32 &vrml_coord_index = dynamic_cast<const openvrml::mfint32 &>(fv2);
|
||||
|
||||
osg::ref_ptr<osg::IntArray> osg_vert_index = new osg::IntArray();
|
||||
|
||||
int num_vert = 0;
|
||||
for (i = 0; i < vrml_coord_index.value.size(); i++)
|
||||
{
|
||||
int index = vrml_coord_index.value[i];
|
||||
if (index == -1)
|
||||
{
|
||||
static_cast<osg::DrawArrayLengths*>(osg_geom->getPrimitiveSet(0))->push_back(num_vert);
|
||||
num_vert = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
osg_vert_index->push_back(index);
|
||||
++num_vert;
|
||||
}
|
||||
}
|
||||
if (num_vert)
|
||||
{
|
||||
//GvdB: Last coordIndex wasn't -1
|
||||
static_cast<osg::DrawArrayLengths*>(osg_geom->getPrimitiveSet(0))->push_back(num_vert);
|
||||
}
|
||||
|
||||
osg_geom->setVertexIndices(osg_vert_index.get());
|
||||
}
|
||||
|
||||
{
|
||||
// get texture coordinate_nodes
|
||||
const openvrml::field_value &fv = vrml_ifs->field("texCoord");
|
||||
const openvrml::sfnode &sfn = dynamic_cast<const openvrml::sfnode &>(fv);
|
||||
openvrml::vrml97_node::texture_coordinate_node *vrml_tex_coord_node =
|
||||
dynamic_cast<openvrml::vrml97_node::texture_coordinate_node *>(sfn.value.get());
|
||||
|
||||
if (vrml_tex_coord_node != 0) // if no texture, node is NULL pointer
|
||||
{
|
||||
const std::vector<openvrml::vec2f> &vrml_tex_coord = vrml_tex_coord_node->point();
|
||||
osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < vrml_tex_coord.size(); i++)
|
||||
{
|
||||
openvrml::vec2f vec = vrml_tex_coord[i];
|
||||
osg_texcoords->push_back(osg::Vec2(vec[0], vec[1]));
|
||||
}
|
||||
|
||||
osg_geom->setTexCoordArray(0, osg_texcoords.get());
|
||||
|
||||
// get array of texture indices
|
||||
const openvrml::field_value &fv2 = vrml_ifs->field("texCoordIndex");
|
||||
const openvrml::mfint32 &vrml_tex_coord_index = dynamic_cast<const openvrml::mfint32 &>(fv2);
|
||||
|
||||
osg::ref_ptr<osg::IntArray> osg_tex_coord_index = new osg::IntArray();
|
||||
|
||||
if(vrml_tex_coord_index.value.size() > 0)
|
||||
{
|
||||
for (i = 0; i < vrml_tex_coord_index.value.size(); i++)
|
||||
{
|
||||
int index = vrml_tex_coord_index.value[i];
|
||||
if (index != -1) {
|
||||
osg_tex_coord_index->push_back(index);
|
||||
}
|
||||
}
|
||||
osg_geom->setTexCoordIndices(0, osg_tex_coord_index.get());
|
||||
} else
|
||||
// no indices defined, use coordIndex
|
||||
osg_geom->setTexCoordIndices(0, osg_geom->getVertexIndices());
|
||||
}
|
||||
}
|
||||
|
||||
// get array of normals per vertex (if specified)
|
||||
{
|
||||
const openvrml::field_value& fv = vrml_ifs->field("normal");
|
||||
const openvrml::sfnode& sfn = dynamic_cast<const openvrml::sfnode&>(fv);
|
||||
openvrml::vrml97_node::normal_node* vrml_normal_node = dynamic_cast<openvrml::vrml97_node::normal_node*>(sfn.value.get());
|
||||
|
||||
if (vrml_normal_node != 0) // if no normals, node is NULL pointer
|
||||
{
|
||||
const std::vector<openvrml::vec3f>& vrml_normal_coord = vrml_normal_node->vector();
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osg_normalcoords = new osg::Vec3Array();
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < vrml_normal_coord.size(); i++)
|
||||
{
|
||||
const openvrml::vec3f vec = vrml_normal_coord[i];
|
||||
osg_normalcoords->push_back(osg::Vec3(vec[0], vec[1], vec[2]));
|
||||
}
|
||||
osg_geom->setNormalArray(osg_normalcoords.get());
|
||||
|
||||
// get array of normal indices
|
||||
const openvrml::field_value& fv2 = vrml_ifs->field("normalIndex");
|
||||
const openvrml::mfint32& vrml_normal_index = dynamic_cast<const openvrml::mfint32&>(fv2);
|
||||
|
||||
osg::ref_ptr<osg::IntArray> osg_normal_index = new osg::IntArray();
|
||||
|
||||
if (vrml_normal_index.value.size() > 0)
|
||||
{
|
||||
for (i = 0; i < vrml_normal_index.value.size(); i++)
|
||||
{
|
||||
int index = vrml_normal_index.value[i];
|
||||
if (index != -1)
|
||||
{
|
||||
osg_normal_index->push_back(index);
|
||||
}
|
||||
}
|
||||
osg_geom->setNormalIndices(osg_normal_index.get());
|
||||
}
|
||||
else
|
||||
// unspecified, use the coordIndex field
|
||||
osg_geom->setNormalIndices(osg_geom->getVertexIndices());
|
||||
|
||||
// get normal binding
|
||||
const openvrml::field_value &fv3 = vrml_ifs->field("normalPerVertex");
|
||||
const openvrml::sfbool &vrml_norm_per_vertex = dynamic_cast<const openvrml::sfbool &>(fv3);
|
||||
|
||||
if (vrml_norm_per_vertex.value)
|
||||
{
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
} else
|
||||
{
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get array of colours per vertex (if specified)
|
||||
{
|
||||
const openvrml::field_value &fv = vrml_ifs->field("color");
|
||||
const openvrml::sfnode &sfn = dynamic_cast<const openvrml::sfnode &>(fv);
|
||||
openvrml::vrml97_node::color_node *vrml_color_node =
|
||||
dynamic_cast<openvrml::vrml97_node::color_node *>(sfn.value.get());
|
||||
|
||||
if (vrml_color_node != 0) // if no colors, node is NULL pointer
|
||||
{
|
||||
const std::vector<openvrml::color> &vrml_colors = vrml_color_node->color();
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osg_colors = new osg::Vec3Array();
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < vrml_colors.size(); i++)
|
||||
{
|
||||
const openvrml::color color = vrml_colors[i];
|
||||
osg_colors->push_back(osg::Vec3(color.r(), color.g(), color.b()));
|
||||
}
|
||||
osg_geom->setColorArray(osg_colors.get());
|
||||
|
||||
// get array of color indices
|
||||
const openvrml::field_value &fv2 = vrml_ifs->field("colorIndex");
|
||||
const openvrml::mfint32 &vrml_color_index = dynamic_cast<const openvrml::mfint32 &>(fv2);
|
||||
|
||||
osg::ref_ptr<osg::IntArray> osg_color_index = new osg::IntArray();
|
||||
|
||||
if(vrml_color_index.value.size() > 0)
|
||||
{
|
||||
for (i = 0; i < vrml_color_index.value.size(); i++)
|
||||
{
|
||||
int index = vrml_color_index.value[i];
|
||||
if (index != -1) {
|
||||
osg_color_index->push_back(index);
|
||||
}
|
||||
}
|
||||
osg_geom->setColorIndices(osg_color_index.get());
|
||||
} else
|
||||
// unspecified, use coordIndices field
|
||||
osg_geom->setColorIndices(osg_geom->getVertexIndices());
|
||||
|
||||
// get color binding
|
||||
const openvrml::field_value &fv3 = vrml_ifs->field("colorPerVertex");
|
||||
const openvrml::sfbool &vrml_color_per_vertex = dynamic_cast<const openvrml::sfbool &>(fv3);
|
||||
|
||||
if (vrml_color_per_vertex.value)
|
||||
{
|
||||
osg_geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
} else
|
||||
{
|
||||
osg_geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (static_cast<const openvrml::sfbool&>(vrml_ifs->field("solid")).value)
|
||||
{
|
||||
osg_stateset->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
||||
}
|
||||
|
||||
if (!osg_geom->getNormalArray())
|
||||
{
|
||||
#if 0
|
||||
// GvdB: This is what I wanted to do, but got zero normals since the triangles were considered temporaries (?)
|
||||
osgUtil::SmoothingVisitor().smooth(*osg_geom);
|
||||
#else
|
||||
// GvdB: So I ended up computing the smoothing normals myself. Also, I might add support for "creaseAngle" if a big need for it rises.
|
||||
// However, for now I can perfectly live with the fact that all edges are smoothed despite the use of a crease angle.
|
||||
osg::Vec3Array& coords = *static_cast<osg::Vec3Array*>(osg_geom->getVertexArray());
|
||||
assert(coords.size());
|
||||
|
||||
osg::Vec3Array* normals = new osg::Vec3Array(coords.size());
|
||||
|
||||
for (osg::Vec3Array::iterator it = normals->begin(); it != normals->end(); ++it)
|
||||
{
|
||||
(*it).set(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
osg::IntArray& indices = *static_cast<osg::IntArray*>(osg_geom->getVertexIndices());
|
||||
osg::DrawArrayLengths& lengths = *static_cast<osg::DrawArrayLengths*>(osg_geom->getPrimitiveSet(0));
|
||||
int index = 0;
|
||||
|
||||
for (osg::DrawArrayLengths::iterator it = lengths.begin(); it != lengths.end(); ++it)
|
||||
{
|
||||
assert(*it >= 3);
|
||||
const osg::Vec3& v0 = coords[indices[index]];
|
||||
const osg::Vec3& v1 = coords[indices[index + 1]];
|
||||
const osg::Vec3& v2 = coords[indices[index + 2]];
|
||||
|
||||
osg::Vec3 normal = (v1 - v0) ^ (v2 - v0);
|
||||
normal.normalize();
|
||||
|
||||
for (int i = 0; i != *it; ++i)
|
||||
{
|
||||
(*normals)[indices[index + i]] += normal;
|
||||
}
|
||||
|
||||
index += *it;
|
||||
}
|
||||
|
||||
assert(index == indices.size());
|
||||
|
||||
for(osg::Vec3Array::iterator it = normals->begin(); it != normals->end(); ++it)
|
||||
{
|
||||
(*it).normalize();
|
||||
}
|
||||
|
||||
osg_geom->setNormalArray(normals);
|
||||
osg_geom->setNormalIndices(osg_geom->getVertexIndices());
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
osg::DrawArrayLengths& lengths = *static_cast<osg::DrawArrayLengths*>(osg_geom->getPrimitiveSet(0));
|
||||
|
||||
osg::DrawArrayLengths::iterator it = lengths.begin();
|
||||
if (it != lengths.end())
|
||||
{
|
||||
switch (*it)
|
||||
{
|
||||
case 3:
|
||||
while (++it != lengths.end() && *it == 3)
|
||||
;
|
||||
|
||||
if (it == lengths.end())
|
||||
{
|
||||
// All polys are triangles
|
||||
osg::ref_ptr<osg::DrawArrays> mesh = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES);
|
||||
mesh->setCount(lengths.size() * 3);
|
||||
osg_geom->removePrimitiveSet(0);
|
||||
osg_geom->addPrimitiveSet(mesh.get());
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
while (++it != lengths.end() && *it == 4)
|
||||
;
|
||||
|
||||
if (it == lengths.end())
|
||||
{
|
||||
// All polys are quads
|
||||
osg::ref_ptr<osg::DrawArrays> mesh = new osg::DrawArrays(osg::PrimitiveSet::QUADS);
|
||||
mesh->setCount(lengths.size() * 4);
|
||||
osg_geom->removePrimitiveSet(0);
|
||||
osg_geom->addPrimitiveSet(mesh.get());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
osg_geom = convertVRML97IndexedFaceSet(vrml_ifs);
|
||||
}
|
||||
else if (openvrml::vrml97_node::box_node* vrml_box = dynamic_cast<openvrml::vrml97_node::box_node*>(vrml_geom))
|
||||
{
|
||||
const openvrml::vec3f& size = static_cast<const openvrml::sfvec3f&>(vrml_box->field("size")).value;
|
||||
|
||||
osg::Vec3 halfSize(size[0] * 0.5f, size[1] * 0.5f, size[2] * 0.5f);
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
|
||||
osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
|
||||
osg::ref_ptr<osg::Vec3Array> osg_normals = new osg::Vec3Array();
|
||||
|
||||
osg::ref_ptr<osg::DrawArrays> box = new osg::DrawArrays(osg::PrimitiveSet::QUADS);
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2]));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2]));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2]));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2]));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2]));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2]));
|
||||
osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2]));
|
||||
|
||||
for (int i = 0; i != 6; ++i)
|
||||
{
|
||||
osg_texcoords->push_back(osg::Vec2(0.0f, 1.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f));
|
||||
}
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
|
||||
osg_normals->push_back(osg::Vec3(0.0f, 0.0f, -1.0f));
|
||||
osg_normals->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));
|
||||
osg_normals->push_back(osg::Vec3(-1.0f, 0.0f, 0.0f));
|
||||
osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));
|
||||
osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
|
||||
|
||||
box->setCount(osg_vertices->size());
|
||||
|
||||
osg_geom->addPrimitiveSet(box.get());
|
||||
|
||||
osg_geom->setVertexArray(osg_vertices.get());
|
||||
osg_geom->setTexCoordArray(0, osg_texcoords.get());
|
||||
osg_geom->setNormalArray(osg_normals.get());
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
|
||||
|
||||
osg_stateset->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
||||
osg_geom = convertVRML97Box(vrml_box);
|
||||
}
|
||||
else if (openvrml::vrml97_node::sphere_node* vrml_sphere = dynamic_cast<openvrml::vrml97_node::sphere_node*>(vrml_geom))
|
||||
{
|
||||
float radius = static_cast<const openvrml::sffloat&>(vrml_sphere->field("radius")).value;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
|
||||
osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
|
||||
osg::ref_ptr<osg::Vec3Array> osg_normals = new osg::Vec3Array();
|
||||
|
||||
unsigned int numSegments = 40;
|
||||
unsigned int numRows = 20;
|
||||
|
||||
const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments);
|
||||
const float texCoordSDelta = 1.0f / float(numSegments);
|
||||
const float phiDelta = float(osg::PI) / float(numRows);
|
||||
const float texCoordTDelta = 1.0f / float(numRows);
|
||||
|
||||
float phi = -0.5f * float(osg::PI);
|
||||
float texCoordT = 0.0f;
|
||||
|
||||
osg::ref_ptr<osg::DrawArrayLengths> sphere = new osg::DrawArrayLengths(osg::PrimitiveSet::QUAD_STRIP);
|
||||
|
||||
for (unsigned int i = 0; i < numRows; ++i, phi += phiDelta, texCoordT += texCoordTDelta)
|
||||
{
|
||||
std::complex<float> latBottom = std::polar(1.0f, phi);
|
||||
std::complex<float> latTop = std::polar(1.0f, phi + phiDelta);
|
||||
std::complex<float> eBottom = latBottom * radius;
|
||||
std::complex<float> eTop = latTop * radius;
|
||||
|
||||
float theta = 0.0f;
|
||||
float texCoordS = 0.0f;
|
||||
|
||||
for (unsigned int j = 0; j < numSegments; ++j, theta += thetaDelta, texCoordS += texCoordSDelta)
|
||||
{
|
||||
std::complex<float> n = -std::polar(1.0f, theta);
|
||||
|
||||
osg_normals->push_back(osg::Vec3(latTop.real() * n.imag(), latTop.imag(), latTop.real() * n.real()));
|
||||
osg_normals->push_back(osg::Vec3(latBottom.real() * n.imag(), latBottom.imag(), latBottom.real() * n.real()));
|
||||
|
||||
osg_texcoords->push_back(osg::Vec2(texCoordS, texCoordT + texCoordTDelta));
|
||||
osg_texcoords->push_back(osg::Vec2(texCoordS, texCoordT));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(eTop.real() * n.imag(), eTop.imag(), eTop.real() * n.real()));
|
||||
osg_vertices->push_back(osg::Vec3(eBottom.real() * n.imag(), eBottom.imag(), eBottom.real() * n.real()));
|
||||
}
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, latTop.imag(), -latTop.real()));
|
||||
osg_normals->push_back(osg::Vec3(0.0f, latBottom.imag(), -latBottom.real()));
|
||||
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, texCoordT + texCoordTDelta));
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, texCoordT));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, eTop.imag(), -eTop.real()));
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, eBottom.imag(), -eBottom.real()));
|
||||
|
||||
sphere->push_back(numSegments * 2 + 2);
|
||||
}
|
||||
|
||||
osg_geom->addPrimitiveSet(sphere.get());
|
||||
|
||||
osg_geom->setVertexArray(osg_vertices.get());
|
||||
osg_geom->setTexCoordArray(0, osg_texcoords.get());
|
||||
osg_geom->setNormalArray(osg_normals.get());
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
osg_stateset->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
||||
|
||||
osg_geom = convertVRML97Sphere(vrml_sphere);
|
||||
}
|
||||
else if (openvrml::vrml97_node::cone_node* vrml_cone = dynamic_cast<openvrml::vrml97_node::cone_node*>(vrml_geom))
|
||||
{
|
||||
float height = static_cast<const openvrml::sffloat&>(vrml_cone->field("height")).value;
|
||||
float radius = static_cast<const openvrml::sffloat&>(vrml_cone->field("bottomRadius")).value;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
|
||||
osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
|
||||
osg::ref_ptr<osg::Vec3Array> osg_normals = new osg::Vec3Array();
|
||||
|
||||
unsigned int numSegments = 40;
|
||||
|
||||
const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments);
|
||||
|
||||
float topY = height * 0.5f;
|
||||
float bottomY = height * -0.5f;
|
||||
|
||||
if (static_cast<const openvrml::sfbool&>(vrml_cone->field("side")).value)
|
||||
{
|
||||
osg::ref_ptr<osg::DrawArrays> side = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP);
|
||||
|
||||
const float texCoordDelta = 1.0f / float(numSegments);
|
||||
float theta = 0.0f;
|
||||
float texCoord = 0.0f;
|
||||
|
||||
for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta, texCoord += texCoordDelta)
|
||||
{
|
||||
std::complex<float> n = -std::polar(1.0f, theta);
|
||||
std::complex<float> e = n * radius;
|
||||
|
||||
osg::Vec3 normal(n.imag() * height, radius, n.real() * height);
|
||||
normal.normalize();
|
||||
|
||||
osg_normals->push_back(normal);
|
||||
osg_normals->push_back(normal);
|
||||
|
||||
osg_texcoords->push_back(osg::Vec2(texCoord, 1.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(texCoord, 0.0f));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, topY, 0.0f));
|
||||
osg_vertices->push_back(osg::Vec3(e.imag(), bottomY, e.real()));
|
||||
}
|
||||
|
||||
// do last point by hand to ensure no round off errors.
|
||||
|
||||
osg::Vec3 normal(0.0f, radius, -height);
|
||||
normal.normalize();
|
||||
|
||||
osg_normals->push_back(normal);
|
||||
osg_normals->push_back(normal);
|
||||
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, topY, 0.0f));
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius));
|
||||
|
||||
side->setCount(osg_vertices->size());
|
||||
osg_geom->addPrimitiveSet(side.get());
|
||||
}
|
||||
|
||||
if (static_cast<const openvrml::sfbool&>(vrml_cone->field("bottom")).value)
|
||||
{
|
||||
osg::ref_ptr<osg::DrawArrays> bottom = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN);
|
||||
|
||||
|
||||
size_t first = osg_vertices->size();
|
||||
bottom->setFirst(first);
|
||||
|
||||
float theta = 0.0f;
|
||||
|
||||
for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta)
|
||||
{
|
||||
std::complex<float> n = -std::polar(1.0f, theta);
|
||||
std::complex<float> e = n * radius;
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.5f - 0.5f * n.imag(), 0.5f + 0.5f * n.real()));
|
||||
osg_vertices->push_back(osg::Vec3(-e.imag(), bottomY, e.real()));
|
||||
}
|
||||
|
||||
// do last point by hand to ensure no round off errors.
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.5f, 0.0f));
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius));
|
||||
|
||||
bottom->setCount(osg_vertices->size() - first);
|
||||
osg_geom->addPrimitiveSet(bottom.get());
|
||||
}
|
||||
|
||||
osg_geom->setVertexArray(osg_vertices.get());
|
||||
osg_geom->setTexCoordArray(0, osg_texcoords.get());
|
||||
osg_geom->setNormalArray(osg_normals.get());
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
osg_stateset->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
||||
osg_geom = convertVRML97Cone(vrml_cone);
|
||||
}
|
||||
else if (openvrml::vrml97_node::cylinder_node* vrml_cylinder = dynamic_cast<openvrml::vrml97_node::cylinder_node*>(vrml_geom))
|
||||
{
|
||||
float height = static_cast<const openvrml::sffloat&>(vrml_cylinder->field("height")).value;
|
||||
float radius = static_cast<const openvrml::sffloat&>(vrml_cylinder->field("radius")).value;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
|
||||
osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
|
||||
osg::ref_ptr<osg::Vec3Array> osg_normals = new osg::Vec3Array();
|
||||
|
||||
unsigned int numSegments = 40;
|
||||
|
||||
const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments);
|
||||
|
||||
|
||||
float topY = height * 0.5f;
|
||||
float bottomY = height * -0.5f;
|
||||
|
||||
if (static_cast<const openvrml::sfbool&>(vrml_cylinder->field("side")).value)
|
||||
{
|
||||
osg::ref_ptr<osg::DrawArrays> side = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP);
|
||||
|
||||
const float texCoordDelta = 1.0f / float(numSegments);
|
||||
float theta = 0.0f;
|
||||
float texCoord = 0.0f;
|
||||
|
||||
for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta, texCoord += texCoordDelta)
|
||||
{
|
||||
std::complex<float> n = -std::polar(1.0f, theta);
|
||||
std::complex<float> e = n * radius;
|
||||
|
||||
osg::Vec3 normal(n.imag(), 0.0f, n.real());
|
||||
|
||||
osg_normals->push_back(normal);
|
||||
osg_normals->push_back(normal);
|
||||
|
||||
osg_texcoords->push_back(osg::Vec2(texCoord, 1.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(texCoord, 0.0f));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(e.imag(), topY, e.real()));
|
||||
osg_vertices->push_back(osg::Vec3(e.imag(), bottomY, e.real()));
|
||||
}
|
||||
|
||||
// do last point by hand to ensure no round off errors.
|
||||
|
||||
osg::Vec3 normal(0.0f, 0.0f, -1.0f);
|
||||
osg_normals->push_back(normal);
|
||||
osg_normals->push_back(normal);
|
||||
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f));
|
||||
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, topY, -radius));
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius));
|
||||
|
||||
side->setCount(osg_vertices->size());
|
||||
osg_geom->addPrimitiveSet(side.get());
|
||||
}
|
||||
|
||||
if (static_cast<const openvrml::sfbool&>(vrml_cylinder->field("bottom")).value)
|
||||
{
|
||||
osg::ref_ptr<osg::DrawArrays> bottom = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN);
|
||||
|
||||
size_t first = osg_vertices->size();
|
||||
bottom->setFirst(first);
|
||||
|
||||
float theta = 0.0f;
|
||||
|
||||
for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta)
|
||||
{
|
||||
std::complex<float> n = -std::polar(1.0f, theta);
|
||||
std::complex<float> e = n * radius;
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.5f - 0.5f * n.imag(), 0.5f + 0.5f * n.real()));
|
||||
osg_vertices->push_back(osg::Vec3(-e.imag(), bottomY, e.real()));
|
||||
}
|
||||
|
||||
// do last point by hand to ensure no round off errors.
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.5f, 0.0f));
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius));
|
||||
|
||||
bottom->setCount(osg_vertices->size() - first);
|
||||
osg_geom->addPrimitiveSet(bottom.get());
|
||||
}
|
||||
|
||||
if (static_cast<const openvrml::sfbool&>(vrml_cylinder->field("top")).value)
|
||||
{
|
||||
osg::ref_ptr<osg::DrawArrays> top = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN);
|
||||
|
||||
size_t first = osg_vertices->size();
|
||||
top->setFirst(first);
|
||||
|
||||
float theta = 0.0f;
|
||||
|
||||
for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta)
|
||||
{
|
||||
std::complex<float> n = -std::polar(1.0f, theta);
|
||||
std::complex<float> e = n * radius;
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.5f + 0.5f * n.imag(), 0.5f - 0.5f * n.real()));
|
||||
osg_vertices->push_back(osg::Vec3(e.imag(), topY, e.real()));
|
||||
}
|
||||
|
||||
// do last point by hand to ensure no round off errors.
|
||||
|
||||
osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));
|
||||
osg_texcoords->push_back(osg::Vec2(0.5f, 1.0f));
|
||||
osg_vertices->push_back(osg::Vec3(0.0f, topY, -radius));
|
||||
|
||||
top->setCount(osg_vertices->size() - first);
|
||||
osg_geom->addPrimitiveSet(top.get());
|
||||
}
|
||||
|
||||
osg_geom->setVertexArray(osg_vertices.get());
|
||||
osg_geom->setTexCoordArray(0, osg_texcoords.get());
|
||||
osg_geom->setNormalArray(osg_normals.get());
|
||||
osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
osg_stateset->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
||||
osg_geom = convertVRML97Cylinder(vrml_cylinder);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -875,6 +215,15 @@ osg::ref_ptr<osg::Node> ReaderWriterVRML2::convertFromVRML(openvrml::node *obj)
|
||||
}
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Geode> osg_geode = new osg::Geode();
|
||||
osg_geode->addDrawable(osg_geom.get());
|
||||
osg::StateSet *osg_stateset = osg_geode->getOrCreateStateSet();
|
||||
|
||||
osg::ref_ptr<osg::Material> osg_mat = new osg::Material();
|
||||
osg_stateset->setAttributeAndModes(osg_mat.get());
|
||||
osg_mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
|
||||
|
||||
|
||||
// parse the appearance
|
||||
{
|
||||
const openvrml::field_value &fv = obj->field("appearance");
|
||||
@@ -985,7 +334,8 @@ osg::ref_ptr<osg::Node> ReaderWriterVRML2::convertFromVRML(openvrml::node *obj)
|
||||
osg_stateset->setTextureAttributeAndModes(0, texture.get());
|
||||
//osg_stateset->setMode(GL_BLEND,osg::StateAttribute::ON); //bhbn
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cerr << "texture file " << url << " not found !" << std::endl << std::flush;
|
||||
}
|
||||
}
|
||||
@@ -993,7 +343,9 @@ osg::ref_ptr<osg::Node> ReaderWriterVRML2::convertFromVRML(openvrml::node *obj)
|
||||
}
|
||||
|
||||
return osg_geode.get();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
71
src/osgPlugins/vrml/ReaderWriterVRML2.h
Normal file
71
src/osgPlugins/vrml/ReaderWriterVRML2.h
Normal file
@@ -0,0 +1,71 @@
|
||||
// -*-c++-*-
|
||||
|
||||
/*
|
||||
*
|
||||
* VRML2 file converter for OpenSceneGraph.
|
||||
*
|
||||
* authors : Jan Ciger (jan.ciger@gmail.com),
|
||||
* Tolga Abaci (tolga.abaci@gmail.com),
|
||||
* Bruno Herbelin (bruno.herbelin@gmail.com)
|
||||
*
|
||||
* (c) VRlab EPFL, Switzerland, 2004-2006
|
||||
*
|
||||
* Gino van den Bergen, DTECTA (gino@dtecta.com)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/Geometry>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgDB/FileUtils>
|
||||
|
||||
namespace openvrml
|
||||
{
|
||||
class node;
|
||||
|
||||
namespace vrml97_node
|
||||
{
|
||||
class indexed_face_set_node;
|
||||
class box_node;
|
||||
class sphere_node;
|
||||
class cone_node;
|
||||
class cylinder_node;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenSceneGraph plugin wrapper/converter.
|
||||
*/
|
||||
class ReaderWriterVRML2
|
||||
: public osgDB::ReaderWriter
|
||||
{
|
||||
public:
|
||||
ReaderWriterVRML2()
|
||||
{}
|
||||
|
||||
virtual const char* className()
|
||||
{
|
||||
return "VRML2 Reader/Writer";
|
||||
}
|
||||
|
||||
virtual bool acceptsExtension(const std::string& extension)
|
||||
{
|
||||
return osgDB::equalCaseInsensitive(extension, "wrl");
|
||||
}
|
||||
|
||||
virtual ReadResult readNode(const std::string&, const osgDB::ReaderWriter::Options *options = NULL) const;
|
||||
|
||||
private:
|
||||
static osg::ref_ptr<osg::Node> convertFromVRML(openvrml::node *obj);
|
||||
|
||||
static osg::ref_ptr<osg::Geometry> convertVRML97IndexedFaceSet(openvrml::vrml97_node::indexed_face_set_node *vrml_ifs);
|
||||
static osg::ref_ptr<osg::Geometry> convertVRML97Box(openvrml::vrml97_node::box_node* vrml_box);
|
||||
static osg::ref_ptr<osg::Geometry> convertVRML97Sphere(openvrml::vrml97_node::sphere_node* vrml_sphere);
|
||||
static osg::ref_ptr<osg::Geometry> convertVRML97Cone(openvrml::vrml97_node::cone_node* vrml_cone);
|
||||
static osg::ref_ptr<osg::Geometry> convertVRML97Cylinder(openvrml::vrml97_node::cylinder_node* vrml_cylinder);
|
||||
};
|
||||
Reference in New Issue
Block a user