OSG读取obj模型坐标变化的问题

您所在的位置:网站首页 osg加载obj模型 OSG读取obj模型坐标变化的问题

OSG读取obj模型坐标变化的问题

2023-11-22 14:16| 来源: 网络整理| 查看: 265

首先需要强烈吐槽一下OSG这个设计,在加载obj模型的时候,会默认将模型绕x轴逆时针旋转90度,让我整整找了两天的原因。。。。这个设计真的太智障了。。。。

我们来看一下,有一个正方体的obj模型,用记事本打开以后,里面的内容如下:

# cube.obj # g cube v 0.0 0.0 0.0 v 0.0 0.0 1.0 v 0.0 1.0 0.0 v 0.0 1.0 1.0 v 1.0 0.0 0.0 v 1.0 0.0 1.0 v 1.0 1.0 0.0 v 1.0 1.0 1.0 vn 0.0 0.0 1.0 vn 0.0 0.0 -1.0 vn 0.0 1.0 0.0 vn 0.0 -1.0 0.0 vn 1.0 0.0 0.0 vn -1.0 0.0 0.0 f 1//2 7//2 5//2 f 1//2 3//2 7//2 f 1//6 4//6 3//6 f 1//6 2//6 4//6 f 3//3 8//3 7//3 f 3//3 4//3 8//3 f 5//5 7//5 8//5 f 5//5 8//5 6//5 f 1//4 5//4 6//4 f 1//4 6//4 2//4 f 2//1 6//1 8//1 f 2//1 8//1 4//1

然后我们读取这个模型,然后把他不做任何操作,再另存成一个obj文件(可能有人要问,为什么要这样搞,其实有应用场景的,比如你拿到一个obj模型,然后在osg中做了某些处理以后,再把他另存为obj模型,然后去其他软件中处理),这个过程的代码应该是这样的:

osg::ref_ptrnode = osgDB::readNodeFile("cube.obj"); osgDB::writeNodeFile(*node, "cube_trans.obj");

理论上来说,cube.obj没有经过任何操作就被另存为了cube_trans.obj了,这两个模型不管有没有被三角形带化,他们的顶点坐标应该是不变的,然后再次在osg中加载,两个模型应该是重合的,对吧。图样图森破,我们加载这两个模型看一下,加载的代码如下:

osgViewer::Viewer viewer; osg::ref_ptrnode = osgDB::readNodeFile("cube.obj"); osg::ref_ptrnode1 = osgDB::readNodeFile("cube_trans.obj"); osg::ref_ptrgroup = new osg::Group; group->addChild(node); group->addChild(node1); viewer.setSceneData(group); return viewer.run();

好嘛,咱们来看看加载的是啥样的

是的,你没看错,两个模型不重合了,再打开cube_trans.obj,看看里面的坐标值,

# file written by OpenSceneGraph mtllib cube_trans.mtl g Group_0 o Group_cube_Geometry_0 v 0 -0 0 v 1 -0 1 v 1 -0 0 v 0 -0 1 v 0 -0 0 v 0 -1 1 v 0 -0 1 v 0 -1 0 v 0 -0 1 v 1 -1 1 v 1 -0 1 v 0 -1 1 v 1 -0 0 v 1 -0 1 v 1 -1 1 v 1 -1 0 v 0 -0 0 v 1 -0 0 v 1 -1 0 v 0 -1 0 v 0 -1 0 v 1 -1 0 v 1 -1 1 v 0 -1 1 # 24 elements written vn 0 1 0 vn 0 1 0 vn 0 1 0 vn 0 1 0 vn -1 -0 0 vn -1 -0 0 vn -1 -0 0 vn -1 -0 0 vn 0 -0 1 vn 0 -0 1 vn 0 -0 1 vn 0 -0 1 vn 1 -0 0 vn 1 -0 0 vn 1 -0 0 vn 1 -0 0 vn 0 -0 -1 vn 0 -0 -1 vn 0 -0 -1 vn 0 -0 -1 vn 0 -1 0 vn 0 -1 0 vn 0 -1 0 vn 0 -1 0 # 24 elements written f 3//3 1//1 2//2 f 1//1 4//4 2//2 f 8//8 6//6 5//5 f 6//6 7//7 5//5 f 24//24 21//21 23//23 f 21//21 22//22 23//23 f 20//20 17//17 19//19 f 17//17 18//18 19//19 f 14//14 15//15 13//13 f 15//15 16//16 13//13 f 11//11 9//9 10//10 f 9//9 12//12 10//10

嗯,你也没看错,顶点坐标值中,y坐标出现-1的值了。。。。对模型没有经过任何操作,另存一下模型的坐标就变了,这谁扛得住啊?找了好久的资料,再快要放弃想重写另存obj的方法时,在osg的论坛上发现了,在调用 osgDB::readNodeFile函数时,可以设置osgDB::Options,然后在读取obj的插件时,可以设置option为“noRotation”。原来,osg在加载obj模型的时候,会默认将obj模型绕着x轴旋转-90°。旋转就旋转嘛,那为什么前后模型会不一样呢?因为在加载cube.obj的时候,将模型旋转了-90°对吧,然后另存为cube_trans.obj的时候,存储的时候旋转了-90°的模型,这也就解释了为什么另存的模型的顶点坐标出现了负值的原因。然后我们再加载cube_trans.obj,OSG又默认将模型旋转了-90°,所以,在第二段代码加载两个模型的时候,cube.obj是被旋转了-90°,然后cube_trans.obj在存储的时候被旋转了-90°,然后在加载的时候,又被默认旋转了-90°,所以相对于cube.obj,它在场景中是多旋转了-90°的,这就造成了他们的不重合。

好了,知道原因就好办了。有两种解决方法:

1.在加载的模型1的时候,就设置不旋转,这样另存的模型2也没有旋转。然后同时加载两个模型的时候,都设置为旋转或不旋转。说着有点抽象,具体看代码:  

osg::ref_ptr options = new osgDB::Options("noRotation"); osg::ref_ptrnode = osgDB::readNodeFile("cube.obj", options); osgDB::writeNodeFile(*node, "cube_trans.obj"); osg::ref_ptrnode1 = osgDB::readNodeFile("cube_trans.obj", options); osg::ref_ptrgroup = new osg::Group; group->addChild(node); group->addChild(node1); viewer.setSceneData(group); return viewer.run();

这样,另存的obj文件坐标没有变化,加载的时候,两个都没有旋转。关键就在于

osg::ref_ptr options = new osgDB::Options("noRotation"); osg::ref_ptrnode = osgDB::readNodeFile("cube.obj", options);

这一句,设置了让模型加载的时候不旋转。

2.如果存储的时候没有设置不旋转,那我们可以设置在加载的时候不旋转,具体原因上面已经解释过,因为原模型在加载的时候会默认旋转,另存的模型也是旋转过的,在加载另存模型的时候设置不旋转,则两个模型正好能重合。

osgViewer::Viewer viewer; osg::ref_ptr options = new osgDB::Options("noRotation"); osg::ref_ptrnode = osgDB::readNodeFile("cube.obj"); osgDB::writeNodeFile(*node, "cube_trans.obj"); osg::ref_ptrnode1 = osgDB::readNodeFile("cube_trans.obj", options); osg::ref_ptrgroup = new osg::Group; group->addChild(node); group->addChild(node1); viewer.setSceneData(group);

但是强烈不建议这种做法,因为另存的时候模型已经经过旋转了,拿经过旋转后的模型去做分析什么的,坐标就全是错的,会很麻烦。

最后,再让我吐槽一下OSG的文档,各种Options根本找不到在哪定义的,到底有哪些Options,要找的话只能去网上搜或者去翻源码。。。希望能改进一下吧



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3