最近两天碰到一个需求“用户要求系统能够导入其输出的vrml文件”。通过上网查询和几次尝试发现如果不想花时间研究vrml文件的结果的话,比较信得过的vrml文件读取方式就是借助开源库OpenVRML,因为开源软件OSG,ARTOOLKit都是用的它(它们用的版本都是OpenVRML 0.14.3)。所以如果想快的话就使用这种方法吧。
如果不想编译OpenVrml,可以从ARToolKit的网站链接中找到编译好的lib,dll。(哈)
读入wrl文件后解析方法我比较了OSG,ARTOOLKit, osg 写的较仔细,但也不是很全,同志们如果有必要的话则要自己补充。下面是osg 中读取和解析wrl的代码:
osgDB::ReaderWriter::ReadResult ReaderWriterVRML2::readNodeconst std::string &fname, const Options* opt) const
{
std::string fileName = osgDB::findDataFilefname, opt);
if fileName.empty)) return ReadResult::FILE_NOT_FOUND;
// convert possible Windows backslashes to Unix slashes
// OpenVRML doesn’t like backslashes, even on Windows
std::string unixFileName = osgDB::convertFileNameToUnixStylefileName);
#ifdef WIN32
ifunixFileName[1] == ‘:’) // absolute path
fileName = “file:///” + unixFileName;
#else
ifunixFileName[0] == ‘/’) // absolute path
fileName = “file://” + unixFileName;
#endif
else // relative path
fileName = unixFileName;
std::fstream null;
openvrml::browser *browser = new openvrml::browsernull, null);
std::vector<std::string> parameter;
std::vector<std::string> vuri;
vuri.push_backfileName);
browser->load_urlvuri, parameter); //****读入vrml文件数据入openvrml系统中
std::vector< openvrml::node_ptr > mfn;
mfn = browser->root_nodes);
if mfn.size) == 0) {
return ReadResult::FILE_NOT_HANDLED;
} else {
osg::ref_ptr<osg::MatrixTransform> osg_root =
new osg::MatrixTransformosg::Matrix 1, 0, 0, 0,
0, 0, 1, 0,
0, -1, 0, 0,
0, 0, 0, 1));
osgDB::getDataFilePathList).push_frontosgDB::getFilePathunixFileName));
for unsigned i = 0; i < mfn.size); i++) {
openvrml::node *vrml_node = mfn[i].get);
osg_root->addChildconvertFromVRMLvrml_node).get));
}
osgDB::getDataFilePathList).pop_front);
return osg_root.get);
}
}
osg::ref_ptr<osg::Node> ReaderWriterVRML2::convertFromVRMLopenvrml::node *obj) const
{
std::string name = obj->id);
static int osgLightNum = 0; //light
// std::cout << obj->type.id << ” Node ” << ” [“<< name <<‘]’ << std::endl;
//****解析node类型将相关数据转入osg系统中
if obj->type.id == “Group”) // Group node
{
openvrml::vrml97_node::group_node *vrml_group;
vrml_group = dynamic_cast<openvrml::vrml97_node::group_node *>obj);
osg::ref_ptr<osg::Group> osg_group = new osg::Group;
try
{
const openvrml::field_value &fv = obj->field”children”);
if fv.type) == openvrml::field_value::mfnode_id ) {
const openvrml::mfnode &mfn = dynamic_cast<const openvrml::mfnode &>fv);
for unsigned i = 0; i < mfn.value.size); i++) {
openvrml::node *node = mfn.value[i].get);
osg_group->addChildconvertFromVRMLnode).get));
}
}
}
catch openvrml::unsupported_interface&)
{
// no children
}
return osg_group.get);
}
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);
openvrml::mat4f vrml_m = vrml_transform->transform);
osg::ref_ptr<osg::MatrixTransform> osg_m = new osg::MatrixTransformosg::Matrixvrml_m[0][0], vrml_m[0][1], vrml_m[0][2], vrml_m[0][3], vrml_m[1][0], vrml_m[1][1], vrml_m[1][2], vrml_m[1][3], vrml_m[2][0], vrml_m[2][1], vrml_m[2][2], vrml_m[2][3], vrml_m[3][0], vrml_m[3][1], vrml_m[3][2], vrml_m[3][3]));
try
{
const openvrml::field_value &fv = obj->field”children”);
if fv.type) == openvrml::field_value::mfnode_id ) {
const openvrml::mfnode &mfn = dynamic_cast<const openvrml::mfnode &>fv);
for unsigned i = 0; i < mfn.value.size); i++) {
openvrml::node *node = mfn.value[i].get);
osg_m->addChildconvertFromVRMLnode).get));
}
}
}
catch openvrml::unsupported_interface&)
{
// no children
}
return osg_m.get);
}
else if obj->type.id == “Shape”) // Handle Shape node
{
osg::ref_ptr<osg::Geometry> osg_geom;
// parse the geometry
{
const openvrml::field_value &fv = obj->field”geometry”);
if fv.type) == openvrml::field_value::sfnode_id)
{
const openvrml::sfnode &sfn = dynamic_cast<const openvrml::sfnode &>fv);
// is it indexed_face_set_node ?
openvrml::vrml97_node::abstract_geometry_node* vrml_geom =
static_cast<openvrml::vrml97_node::abstract_geometry_node*>sfn.value.get)->to_geometry));
if openvrml::vrml97_node::indexed_face_set_node *vrml_ifs = dynamic_cast<openvrml::vrml97_node::indexed_face_set_node *>vrml_geom))
{
osg_geom = convertVRML97IndexedFaceSetvrml_ifs);
}
else if openvrml::vrml97_node::box_node* vrml_box = dynamic_cast<openvrml::vrml97_node::box_node*>vrml_geom))
{
osg_geom = convertVRML97Boxvrml_box);
}
else if openvrml::vrml97_node::sphere_node* vrml_sphere = dynamic_cast<openvrml::vrml97_node::sphere_node*>vrml_geom))
{
osg_geom = convertVRML97Spherevrml_sphere);
}
else if openvrml::vrml97_node::cone_node* vrml_cone = dynamic_cast<openvrml::vrml97_node::cone_node*>vrml_geom))
{
osg_geom = convertVRML97Conevrml_cone);
}
else if openvrml::vrml97_node::cylinder_node* vrml_cylinder = dynamic_cast<openvrml::vrml97_node::cylinder_node*>vrml_geom))
{
osg_geom = convertVRML97Cylindervrml_cylinder);
}
else
{
// other geometry types not handled yet
}
}
}
osg::ref_ptr<osg::Geode> osg_geode = new osg::Geode);
osg_geode->addDrawableosg_geom.get));
osg::StateSet *osg_stateset = osg_geode->getOrCreateStateSet);
osg::ref_ptr<osg::Material> osg_mat = new osg::Material);
osg_stateset->setAttributeAndModesosg_mat.get));
osg_mat->setColorModeosg::Material::AMBIENT_AND_DIFFUSE);
// parse the appearance
{
const openvrml::field_value &fv = obj->field”appearance”);
// *****设置材质和光照属性
if fv.type) == openvrml::field_value::sfnode_id)
{
const openvrml::sfnode &sfn = dynamic_cast<const openvrml::sfnode &>fv);
// std::cerr << “FV->sfnode OK” << std::endl << std::flush;
openvrml::vrml97_node::appearance_node* vrml_app = static_cast<openvrml::vrml97_node::appearance_node*>sfn.value.get)->to_appearance));
const openvrml::node_ptr &vrml_material_node = vrml_app->material);
const openvrml::node_ptr &vrml_texture_node = vrml_app->texture);
const openvrml::vrml97_node::material_node *vrml_material =
dynamic_cast<const openvrml::vrml97_node::material_node *>vrml_material_node.get));
// std::cerr << “sfnode->Material OK” << std::endl << std::flush;
if vrml_material != NULL)
{
osg_mat->setAmbientosg::Material::FRONT_AND_BACK,
osg::Vec4vrml_material->ambient_intensity),
vrml_material->ambient_intensity),
vrml_material->ambient_intensity),
1.0));
osg_mat->setDiffuseosg::Material::FRONT_AND_BACK,
osg::Vec4vrml_material->diffuse_color).r),
vrml_material->diffuse_color).g),
vrml_material->diffuse_color).b),
1.0));
osg_mat->setEmissionosg::Material::FRONT_AND_BACK,
osg::Vec4vrml_material->emissive_color).r),
vrml_material->emissive_color).g),
vrml_material->emissive_color).b),
1.0));
osg_mat->setSpecularosg::Material::FRONT_AND_BACK,
osg::Vec4vrml_material->specular_color).r),
vrml_material->specular_color).g),
vrml_material->specular_color).b),
1.0));
osg_mat->setShininessosg::Material::FRONT_AND_BACK, vrml_material->shininess) );
if vrml_material->transparency) > 0.0f)
{
osg_mat->setTransparencyosg::Material::FRONT_AND_BACK, vrml_material->transparency));
osg_stateset->setModeGL_BLEND, osg::StateAttribute::ON);
osg_stateset->setAttributenew osg::Depthosg::Depth::LESS, 0.0, 1.0, false)); // GvdB: transparent objects do not write depth
osg_stateset->setRenderingHintosg::StateSet::TRANSPARENT_BIN);
}
else
{
osg_stateset->setModeGL_BLEND, osg::StateAttribute::OFF);
osg_stateset->setRenderingHintosg::StateSet::OPAQUE_BIN);
}
osg_stateset->setAttributeAndModesosg_mat.get));
}
const openvrml::vrml97_node::image_texture_node *vrml_texture =
dynamic_cast<const openvrml::vrml97_node::image_texture_node *>vrml_texture_node.get));
// std::cerr << “TextureNode -> ImageTexture OK” << std::endl << std::flush;
// if texture is provided
//
if vrml_texture != 0) {
const openvrml::field_value &texture_url_fv = vrml_texture->field”url”);
const openvrml::mfstring &mfs = dynamic_cast<const openvrml::mfstring &>texture_url_fv);
// std::cerr << “Texture URL FV -> mfstring OK” << std::endl << std::flush;
const std::string &url = mfs.value[0];
osg::ref_ptr<osg::Image> image = osgDB::readRefImageFileurl);
if image != 0) {
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
texture->setImageimage.get));
// defaults
texture->setWraposg::Texture::WRAP_S, osg::Texture::REPEAT);
texture->setWraposg::Texture::WRAP_R, osg::Texture::REPEAT);
texture->setWraposg::Texture::WRAP_T, osg::Texture::REPEAT);
// get the real texture wrapping parameters if any)
try {
const openvrml::field_value &wrap_fv = vrml_texture->field”repeatS”);
const openvrml::sfbool &sfb = dynamic_cast<const openvrml::sfbool &>wrap_fv);
if !sfb.value) {
texture->setWraposg::Texture::WRAP_S, osg::Texture::CLAMP);
}
} catch …) {
// nothing specified
}
try {
const openvrml::field_value &wrap_fv = vrml_texture->field”repeatT”);
const openvrml::sfbool &sfb = dynamic_cast<const openvrml::sfbool &>wrap_fv);
if !sfb.value) {
texture->setWraposg::Texture::WRAP_S, osg::Texture::CLAMP);
}
} catch …) {
// nothing specified
}
osg_stateset->setTextureAttributeAndModes0, texture.get));
//osg_stateset->setModeGL_BLEND,osg::StateAttribute::ON); //bhbn
}
else {
std::cerr << “texture file ” << url << ” not found !” << std::endl << std::flush;
}
}
}
}
return osg_geode.get);
}
else
{
return 0;
}
/*
} else ifobj->type.id == “DirectionalLight”) // Handle lights
{
osg::Group* lightGroup = new osg::Group;
openvrml::vrml97_node::directional_light_node *vrml_light;
vrml_light = dynamic_cast<openvrml::vrml97_node::directional_light_node *>obj);
// create light with global params
osg::Light* myLight = new osg::Light;
myLight->setLightNumosgLightNum);
myLight->setAmbientosg::Vec4vrml_light->ambient_intensity),vrml_light->ambient_intensity),vrml_light->ambient_intensity),vrml_light->ambient_intensity)));
float osgR = vrml_light->color).r)*vrml_light->intensity);
float osgG = vrml_light->color).g)*vrml_light->intensity);
float osgB = vrml_light->color).b)*vrml_light->intensity);
myLight->setDiffuseosg::Vec4osgR, osgG, osgB, 1.0f));
myLight->setSpecularosg::Vec4osgR, osgG, osgB, 1.0f));
// configure light as DIRECTIONAL
openvrml::sfvec3f &dir = vrml_light->direction_;
myLight->setDirectionosg::Vec3dir.value[0],dir.value[1],dir.value[2]));
myLight->setPositionosg::Vec4dir.value[0],dir.value[1],dir.value[2], 0.0f));
// add the light in the scenegraph
osg::LightSource* lightS = new osg::LightSource;
lightS->setLightmyLight);
if vrml_light->on)) {
lightS->setLocalStateSetModesosg::StateAttribute::ON);
//lightS->setStateSetModes*rootStateSet,osg::StateAttribute::ON);
}
lightGroup->addChildlightS);
osgLightNum++;
return lightGroup;
} else ifobj->type.id == “PointLight”) // Handle lights
{
osg::Group* lightGroup = new osg::Group;
openvrml::vrml97_node::point_light_node *vrml_light;
vrml_light = dynamic_cast<openvrml::vrml97_node::point_light_node *>obj);
// create light with global params
osg::Light* myLight = new osg::Light;
myLight->setLightNumosgLightNum);
//std::cout<<“lightnum = “<<osgLightNum;
openvrml::sfvec3f &pos = vrml_light->location_;
myLight->setPositionosg::Vec4pos.value[0], pos.value[1], pos.value[2], 1.0f));
myLight->setAmbientosg::Vec4vrml_light->ambient_intensity),vrml_light->ambient_intensity),vrml_light->ambient_intensity),vrml_light->ambient_intensity)));
float osgR = vrml_light->color).r)*vrml_light->intensity);
float osgG = vrml_light->color).g)*vrml_light->intensity);
float osgB = vrml_light->color).b)*vrml_light->intensity);
myLight->setDiffuseosg::Vec4osgR, osgG, osgB, 1.0f));
myLight->setSpecularosg::Vec4osgR, osgG, osgB, 1.0f));
// configure light as POINT
myLight->setDirectionosg::Vec30.f,0.f,0.f));
// add the light in the scenegraph
osg::LightSource* lightS = new osg::LightSource;
lightS->setLightmyLight);
if vrml_light->on)) {
lightS->setLocalStateSetModesosg::StateAttribute::ON);
//lightS->setStateSetModes*rootStateSet,osg::StateAttribute::ON);
}
lightGroup->addChildlightS);
osgLightNum++;
return lightGroup;
} else ifobj->type.id == “SpotLight”) // Handle lights
{
osg::Group* lightGroup = new osg::Group;
openvrml::vrml97_node::spot_light_node *vrml_light;
vrml_light = dynamic_cast<openvrml::vrml97_node::spot_light_node *>obj);
// create light with global params
osg::Light* myLight = new osg::Light;
myLight->setLightNumosgLightNum);
myLight->setPositionosg::Vec40.0f, 0.0f, 0.0f, 1.0f));
myLight->setAmbientosg::Vec4vrml_light->ambient_intensity),vrml_light->ambient_intensity),vrml_light->ambient_intensity),vrml_light->ambient_intensity)));
float osgR = vrml_light->color).r)*vrml_light->intensity);
float osgG = vrml_light->color).g)*vrml_light->intensity);
float osgB = vrml_light->color).b)*vrml_light->intensity);
myLight->setDiffuseosg::Vec4osgR, osgG, osgB, 1.0f));
myLight->setSpecularosg::Vec4osgR, osgG, osgB, 1.0f));
// configure light as SPOT
openvrml::sfvec3f &dir = vrml_light->direction_;
myLight->setDirectionosg::Vec3dir.value[0],dir.value[1],dir.value[2]));
// The cutOff value in osg ranges from 0 to 90, we need
// to divide by 2 to avoid openGL error.
// myLight->setSpotCutoffls.fallsize/2.0f);
// The bigger the differens is between fallsize and hotsize
// the bigger the exponent should be.
// float diff = ls.fallsize – ls.hotsize;
// myLight->setSpotExponentdiff);
// add the light in the scenegraph
osg::LightSource* lightS = new osg::LightSource;
lightS->setLightmyLight);
if vrml_light->on)) {
lightS->setLocalStateSetModesosg::StateAttribute::ON);
//lightS->setStateSetModes*rootStateSet,osg::StateAttribute::ON);
}
lightGroup->addChildlightS);
osgLightNum++;
return lightGroup;
} else {
return NULL;
}
*/
}
20102.3.25
饮水思源,不忘初心。
要面包,也要有诗和远方。
