查看: 1717|回复: 11

求助:OSG绘制图形:椭球

[复制链接]

该用户从未签到

发表于 2014-10-10 10:06:49 | 显示全部楼层 |阅读模式
怎么用osg绘制可编辑的椭球?

该用户从未签到

发表于 2014-10-10 17:23:18 | 显示全部楼层
本帖最后由 buaahc 于 2014-10-10 17:26 编辑

椭球:去网上寻找椭球的参数方程,使用osg实现之即可。但是可编辑?具体要求怎么解释?

该用户从未签到

 楼主| 发表于 2014-10-10 22:23:14 | 显示全部楼层
buaahc 发表于 2014-10-10 17:23
椭球:去网上寻找椭球的参数方程,使用osg实现之即可。但是可编辑?具体要求怎么解释?

因为我是想用椭球作为初始模板模拟对象的三维表面,然后需要根据对象的实际形状去调整椭球使其逼近对象三维表面。现在有两个想法:1、对现有的sphere做变形;2、先构造椭球,然后对其变形。大师你觉得怎么更好一些?
我尝试了下用椭球的参数方程去实现,但是先绘制的骨架点,不只是直接画出一圈一圈的曲线,尝试了几种顶点关联方式都没起作用,现一筹莫展,求大神帮助。

该用户从未签到

发表于 2014-10-11 09:53:29 | 显示全部楼层
不论椭球还是求抑或其他什么图形,只要参数方程存在,使用osg都能实现绘制,绘制的难点在于如何存储vexterArray,很多人不会存储,关联方式肯定是GL_TRIANGLE_STRIP,我觉得你所指的根据对象的实际形状去调整椭球应该就是调整椭球的a,b参数即可,
如果sphere你能够实现,椭球也一样,osg::shape里面有完整的sphere实现代码,阅读之,参考之,实现之

该用户从未签到

 楼主| 发表于 2014-10-12 09:39:14 | 显示全部楼层
本帖最后由 osgxch 于 2014-10-12 09:53 编辑
buaahc 发表于 2014-10-11 09:53
不论椭球还是求抑或其他什么图形,只要参数方程存在,使用osg都能实现绘制,绘制的难点在于如何存储vexterA ...


大师这是我的代码,正如大师所说,可能就是我在存储顶点时顺序有问题,但我还是不知道怎么存储,请大师指教。
#include "../Common/Common.h"
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Material>
#include<osg/StateSet>
#include <osg/Image>
#include <osg/Texture2D>
#include <osg/Texture3D>
#include <osg/LineWidth>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/GUIEventAdapter>
#include <iostream>

#ifdef _DEBUG
#pragma comment(lib,"../Debug/Commond.lib")
#else
#pragma comment(lib,"../Release/Common.lib")
#endif


osg::ref_ptr<osg::Geode>CreateEllipsoid(float a,float b,int n,int m)
{
        double PI = osg:I;
        float x, y, z, angle_l, angle_v;
        int i, j;
       
        angle_l = 0.0;
        angle_v = 0.0;

        osg::ref_ptr<osg::Geode>geode = new osg::Geode;
        osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;

        //申请一些顶点
        osg::ref_ptr<osg::Vec3Array>coords = new osg::Vec3Array;
        //申请颜色
        osg::ref_ptr<osg::Vec4Array>colors = new osg::Vec4Array;
        //申请法向量
        osg::ref_ptr<osg::Vec3Array>norms = new osg::Vec3Array;
       
        geode->addDrawable(geom);

        //设置顶点
        geom->setVertexArray(coords.get());
        //设置顶点关联方式
        geom->addPrimitiveSet(new osg:rawArrays(osg::PrimitiveSet::Mode::TRIANGLE_STRIP, 0, 5));
        //设置顶点颜色
        geom->setColorArray(colors);
        geom->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_VERTEX);
        //设置法向量
        geom->setNormalArray(norms);
        geom->setNormalBinding(osg::Geometry::AttributeBinding::BIND_PER_VERTEX);

        for (j = 0; j <= 1 + (m + 1) / 2;j++)
        {
                for (i = 0; i <= n / 4 + 1;i++)
                {
                        angle_l = 2 * PI / n*i;
                        angle_v = PI / m*j;
                        x = a*sin(angle_v)*cos(angle_l);
                        y = a*sin(angle_v)*sin(angle_l);
                        z = b*cos(angle_v);
                        osg::ref_ptr<osg::ShapeDrawable>point1 = new osg::ShapeDrawable(new        osg::Sphere(osg::Vec3(x, y, z), 0.2));
                        osg::ref_ptr<osg::ShapeDrawable>point2 = new osg::ShapeDrawable(new        osg::Sphere(osg::Vec3(x, -y, z), 0.2));
                        osg::ref_ptr<osg::ShapeDrawable>point3 = new osg::ShapeDrawable(new        osg::Sphere(osg::Vec3(-x, y, z), 0.2));
                        osg::ref_ptr<osg::ShapeDrawable>point4= new osg::ShapeDrawable(new        osg::Sphere(osg::Vec3(-x, -y, z), 0.2));
                        osg::ref_ptr<osg::ShapeDrawable>point5 = new osg::ShapeDrawable(new        osg::Sphere(osg::Vec3(x, y, -z), 0.2));
                        osg::ref_ptr<osg::ShapeDrawable>point6 = new osg::ShapeDrawable(new        osg::Sphere(osg::Vec3(x, -y, -z), 0.2));
                        osg::ref_ptr<osg::ShapeDrawable>point7 = new osg::ShapeDrawable(new        osg::Sphere(osg::Vec3(-x, y, -z), 0.2));
                        osg::ref_ptr<osg::ShapeDrawable>point8 = new osg::ShapeDrawable(new        osg::Sphere(osg::Vec3(-x, -y, -z), 0.2));
                        //设置顶点球颜色
                        point1->setColor(osg::Vec4(x, y, z, 1.0));
                        point2->setColor(osg::Vec4(x, -y, z, 1.0));
                        point3->setColor(osg::Vec4(-x, y, z, 1.0));
                        point4->setColor(osg::Vec4(-x, -y, z, 1.0));
                        point5->setColor(osg::Vec4(x, y, -z, 1.0));
                        point6->setColor(osg::Vec4(x, -y, -z, 1.0));
                        point7->setColor(osg::Vec4(-x, y, -z, 1.0));
                        point8->setColor(osg::Vec4(-x, -y, -z, 1.0));
                        //顶点
                        coords->push_back(osg::Vec3(x, y, z));
                        coords->push_back(osg::Vec3(x, -y, z));
                        coords->push_back(osg::Vec3(-x, y, z));
                        coords->push_back(osg::Vec3(-x, -y, z));
                        coords->push_back(osg::Vec3(x, y, -z));
                        coords->push_back(osg::Vec3(x, -y, -z));
                        coords->push_back(osg::Vec3(-x, y, -z));
                        coords->push_back(osg::Vec3(-x, -y, -z));
                        //颜色
                        colors->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.5));
                        colors->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.5));
                        colors->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.5));
                        colors->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.5));
                        colors->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.5));
                        colors->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.5));
                        colors->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.5));
                        colors->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.5));
                        //法向量
                        norms->push_back(osg::Vec3(x, y, z));
                        norms->push_back(osg::Vec3(x, -y, z));
                        norms->push_back(osg::Vec3(-x, y, z));
                        norms->push_back(osg::Vec3(-x, -y, z));
                        norms->push_back(osg::Vec3(x, y, -z));
                        norms->push_back(osg::Vec3(x, -y, -z));
                        norms->push_back(osg::Vec3(-x, y, -z));
                        norms->push_back(osg::Vec3(-x, -y, -z));

                        geode->addDrawable(point1.get());
                        geode->addDrawable(point2.get());
                        geode->addDrawable(point3.get());
                        geode->addDrawable(point4.get());
                        geode->addDrawable(point5.get());
                        geode->addDrawable(point6.get());
                        geode->addDrawable(point7.get());
                        geode->addDrawable(point8.get());
                }
        }
        return geode;
}
int main()
{
        osg::ref_ptr < osgViewer::Viewer >viewer = new osgViewer::Viewer;
        osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("glider.osg");
        osg::ref_ptr<osg::Group>group = new osg::Group;
        group->addChild(CreateEllipsoid(30.0, 50.0, 100, 49));
        viewer->setSceneData(group);
        return viewer->run();
}

该用户从未签到

发表于 2014-10-13 16:54:29 | 显示全部楼层
本帖最后由 buaahc 于 2014-10-13 16:58 编辑

你这里面绘制大堆球是什么概念。。。椭球参数方程跟圆球的参数方程基本上一致,只是球的三轴的数字参数是R,而椭球的三轴参数分别是abc,如果你会写sphere,椭球完全一样嘛。。。关于sphere怎么写,我前面已经说了去看osg::sphere的源代码里面有现成的。。。通过阅读并且实现,这样你会印象非常深刻~
椭球参数方程x=asinβcosθ,y=bsinβsinθ,z=ccosβ  (0≤θ<2π,-0.5*n≤β≤0.5π)
球参数方程x=Rsinβcosθ,y=Rsinβsinθ,z=Rcosβ  (0≤θ<2π,-0.5*n≤β≤0.5π)

该用户从未签到

 楼主| 发表于 2014-10-14 12:52:10 | 显示全部楼层
buaahc 发表于 2014-10-13 16:54
你这里面绘制大堆球是什么概念。。。椭球参数方程跟圆球的参数方程基本上一致,只是球的三轴的数字参数是R ...

大师,先问你个问题。osgUtil::SmoothingVisitor 的成员函数smooth(*(geometry.get()))可以自动生成顶点法线,不管这个geometry多复杂,一次就可以生成所有顶点的法线吗?他和人工计算生成法线效果一样吗?
还有一个小问题,对一个vec3的向量,我怎么取到它的x,y,z值。
谢谢大师

该用户从未签到

发表于 2014-10-14 13:35:16 | 显示全部楼层
可以,但是肯定不是跟人工指定生成的一样,osg::vec3 a; a.x();a.y();a.z();。。。

该用户从未签到

 楼主| 发表于 2014-10-16 12:58:03 | 显示全部楼层
buaahc 发表于 2014-10-14 13:35
可以,但是肯定不是跟人工指定生成的一样,osg::vec3 a; a.x();a.y();a.z();。。。

大神,再问个问题 ,就是TexGen类自动生成纹理坐标,但是出现一个问题,纹理结果贴到几何体的内表面了,这是怎么回事?能设置到外表面吗?按理说它是贴到有法线的这一侧才对啊,大神请指导
        osg::ref_ptr<osg::TexGen>texgen = new osg::TexGen;
        texgen->setMode(osg::TexGen::SPHERE_MAP);

该用户从未签到

发表于 2014-10-16 16:30:16 | 显示全部楼层
绘制几何体的时候要务必注意正反面,正反面是根据顶点的绘制顺序进行判断,遵循右手法则,顶点逆时针旋转为正,顺时针旋转为反面

该用户从未签到

 楼主| 发表于 2014-10-16 23:23:12 | 显示全部楼层
buaahc 发表于 2014-10-16 16:30
绘制几何体的时候要务必注意正反面,正反面是根据顶点的绘制顺序进行判断,遵循右手法则,顶点逆时针旋转为 ...

大神,那怎么关闭背面绘制呢?

该用户从未签到

发表于 2014-10-17 09:56:13 | 显示全部楼层
有个cull_face属性,参数使用GL_FRONT调用,,并赋给节点就行,我建议你看一下opengl吧~
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表