在OpenSceneGraph中创建一个球体(使用osg :: Geometry) [英] Creating a Sphere (using osg::Geometry) in OpenSceneGraph

查看:102
本文介绍了在OpenSceneGraph中创建一个球体(使用osg :: Geometry)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了很多时间来使它工作,但我的Sphere却无法显示.
使用以下代码来实现我的功能:
使用Visual C ++在Opengl中创建3D球形

I spent quite some time to get this working, but my Sphere just won't display.
Used the following code to make my function:
Creating a 3D sphere in Opengl using Visual C++

剩下的是简单的OSG osg :: Geometry .
(注意:不可ShapeDrawable,因为您不能使用它来实现自定义形状.)
在VecArrays中添加了顶点,法线和texcoords.

And the rest is simple OSG with osg::Geometry.
(Note: Not ShapeDrawable, as you can't implement custom shapes using that.)
Added the vertices, normals, texcoords into VecArrays.

一个,我怀疑行为不正确,因为我保存的对象是空的.
有没有办法将现有描述转换为OSG?
原因?我想稍后了解如何创建对象.
确实,它与以后的任务有关,但是目前我只是在进行预配对.

For one, I suspect something misbehaving, as my saved object is half empty.
Is there a way to convert the existing description into OSG?
Reason? I want to understand how to create objects later on.
Indeed, it is linked with a later assignment, but currently I'm just prepairing beforehand.

Sidenote :由于我必须使其没有索引,因此将它们省略了.
但是如果没有它们,我的气瓶就会很好地显示出来.

Sidenote: Since I have to make it without indices, I left them out.
But my cylinder displays just fine without them.

推荐答案

注意:我不是OSG专家.但是,我确实做了一些研究.

Caveat: I'm not an OSG expert. But, I did do some research.

OSG要求以逆时针顺序定义所有面,以便背面剔除可以拒绝面朝外"的面.您用于生成球体的代码不会按逆时针顺序生成所有面.

OSG requires all of the faces to be defined in counter-clockwise order, so that backface culling can reject faces that are "facing away". The code you're using to generate the sphere does not generate all the faces in counter-clockwise order.

您可以通过以下两种方法进行处理:

You can approach this a couple ways:

  1. 通过按CCW顺序插入面孔来调整代码生成面孔的方式.
  2. 将模型加倍,然后将每个面插入两次,一次以当前面的顶点顺序排列,一次以相反顺序的顶点插入.

以上选项1会将您的多边形总数限制为所需数量.选项2将为您提供一个可以从球体外部以及球体内部看到的球体.

Option 1 above will limit your total polygon count to what's needed. Option 2 will give you a sphere that's visible from outside the sphere as well as within.

要实现选项2,您只需要根据链接到的代码修改此循环:

To implement Option 2, you merely need to modify this loop from the code you linked to:

    indices.resize(rings * sectors * 4);
    std::vector<GLushort>::iterator i = indices.begin();
    for(r = 0; r < rings-1; r++) 
        for(s = 0; s < sectors-1; s++) {
            *i++ = r * sectors + s;
            *i++ = r * sectors + (s+1);
            *i++ = (r+1) * sectors + (s+1);
            *i++ = (r+1) * sectors + s;
        }

将四边形集加倍,如下所示:

Double up the set of quads like so:

    indices.resize(rings * sectors * 8);
    std::vector<GLushort>::iterator i = indices.begin();
    for(r = 0; r < rings-1; r++) 
        for(s = 0; s < sectors-1; s++) {
            *i++ = r * sectors + s;
            *i++ = r * sectors + (s+1);
            *i++ = (r+1) * sectors + (s+1);
            *i++ = (r+1) * sectors + s;

            *i++ = (r+1) * sectors + s;
            *i++ = (r+1) * sectors + (s+1);
            *i++ = r * sectors + (s+1);
            *i++ = r * sectors + s;
        }

但这确实是更大的锤子"解决方案.

That really is the "bigger hammer" solution, though.

就个人而言,我很难弄清楚为什么原始循环不够用;为什么?纵观我的几何图形,感觉好像已经在生成CCW面,因为每个连续的环都在前一个环上方,并且每个连续的扇形都围绕着前一个球体绕CCW.因此,相对于距观看者最近的脸部,原始订单本身应为CCW.

Personally, I'm having a hard time figuring out why the original loop isn't sufficient; intuiting my way through the geometry, it feels like it's already generating CCW faces, because each successive ring is above the previous, and each successive sector is CCW around the surface of the sphere from the previous. So, the original order itself should be CCW with respect to the face nearest the viewer.

编辑使用之前链接的OpenGL代码和今天链接的OSG教程,我将我认为是正确的程序组合在一起,可以为球体生成osg::Geometry/osg::Geode.我没有办法测试以下代码,但要对其进行桌面检查,它看起来正确或至少在很大程度上是正确的.

EDIT Using the OpenGL code you linked before and the OSG tutorial you linked today, I put together what I think is a correct program to generate the osg::Geometry / osg::Geode for the sphere. I have no way to test the following code, but desk-checking it, it looks correct or at least largely correct.

#include <vector>

class SolidSphere
{
protected:

    osg::Geode      sphereGeode;
    osg::Geometry   sphereGeometry;
    osg::Vec3Array  sphereVertices;
    osg::Vec3Array  sphereNormals;
    osg::Vec2Array  sphereTexCoords;

    std::vector<osg::DrawElementsUInt> spherePrimitiveSets;

public:
    SolidSphere(float radius, unsigned int rings, unsigned int sectors)
    {
        float const R = 1./(float)(rings-1);
        float const S = 1./(float)(sectors-1);
        int r, s;

        sphereGeode.addDrawable( &sphereGeometry );

        // Establish texture coordinates, vertex list, and normals
        for(r = 0; r < rings; r++)
            for(s = 0; s < sectors; s++)
            {
                float const y = sin( -M_PI_2 + M_PI * r * R );
                float const x = cos(2*M_PI * s * S) * sin( M_PI * r * R );
                float const z = sin(2*M_PI * s * S) * sin( M_PI * r * R );

                sphereTexCoords.push_back( osg::Vec2(s*R, r*R) );

                sphereVertices.push_back ( osg::Vec3(x * radius,
                                                     y * radius,
                                                     z * radius) );

                sphereNormals.push_back  ( osg::Vec3(x, y, z) );

            }

        sphereGeometry.setVertexArray  ( &spehreVertices  );
        sphereGeometry.setTexCoordArray( &sphereTexCoords );

        // Generate quads for each face.  
        for(r = 0; r < rings-1; r++)
            for(s = 0; s < sectors-1; s++)
            {
                spherePrimitiveSets.push_back(
                    DrawElementUint( osg::PrimitiveSet::QUADS, 0 )
                );

                osg::DrawElementsUInt& face = spherePrimitiveSets.back();

                // Corners of quads should be in CCW order.
                face.push_back( (r + 0) * sectors + (s + 0) );
                face.push_back( (r + 0) * sectors + (s + 1) );
                face.push_back( (r + 1) * sectors + (s + 1) );
                face.push_back( (r + 1) * sectors + (s + 0) );

                sphereGeometry.addPrimitveSet( &face );
            }
    }

    osg::Geode     *getGeode()     const { return &sphereGeode;     }
    osg::Geometry  *getGeometry()  const { return &sphereGeometry;  }
    osg::Vec3Array *getVertices()  const { return &sphereVertices;  }
    osg::Vec3Array *getNormals()   const { return &sphereNormals;   }
    osg::Vec2Array *getTexCoords() const { return &sphereTexCoords; }

};

您可以使用getXXX方法来获取各种片段.我没有看到如何将表面法线连接到任何东西,但是我确实将它们存储在Vec2Array中.如果您对它们有用途,则将对它们进行计算和存储,并等待将其挂接到某处.

You can use the getXXX methods to get the various pieces. I didn't see how to hook the surface normals to anything, but I do store them in a Vec2Array. If you have a use for them, they're computed and stored and waiting to be hooked to something.

这篇关于在OpenSceneGraph中创建一个球体(使用osg :: Geometry)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆