osg绘制圆角矩形气泡

在网上找了好多好像没有看到有些圆角矩形的,只看到一个绘制圆形矩形(类似学习操场的跑道);根据那个写了一个求圆角矩形的函数

void arrayVac(double v[90][2],double x=0,double y=0)//v 顶点数组、x,y 鼠标点击位置
{
    double r=0.5;//圆角半径
    double angle0=0.f; //圆角度  右上
    double angle1=osg::PI/2; //圆角度  左上
    double angle2=osg::PI; //圆角度  左下
    double angle3=3*osg::PI/2; //圆角度  右下
    for (int i=0;i<90;i++)
    {
        //矩形部分
        switch (i)
        {

        case 2://0
            v[i][0]=0.5+x;
            v[i][1]=-0.6+y;
            break;
        case 1://1
            v[i][0]=0+x;
            v[i][1]=0+y;
            break;
        case 0://2
            v[i][0]=1.5+x;
            v[i][1]=-0.6+y;
            break;
        case 89://3
            v[i][0]=2.5+x;
            v[i][1]=-0.6+y;
            break;
        case 67://24
            v[i][0]=3+x;
            v[i][1]=-1.1+y;
            break;
        case 66://25
            v[i][0]=3+x;
            v[i][1]=-2.1+y;
            break;
        case 45://46
            v[i][0]=2.5+x;
            v[i][1]=-2.6+y;
            break;
        case 44://47
            v[i][0]=0.5+x;
            v[i][1]=-2.6+y;
            break;
        case 23://68
            v[i][0]=0+x;
            v[i][1]=-2.1+y;
            break;
        case 22://69
            v[i][0]=0+x;
            v[i][1]=-1.1+y;
            break;
        }
        //右上
        if (i>67&&i<89)
        {//(2.5,-1.1)
            v[i][0]=r*cosf(angle0)+2.5+x;                        //circle1[i][0] = radius * cosf(angle);
            v[i][1]=r*sinf(angle0)-1.1+y;                        //circle1[i][1] = radius * sinf(angle);
            angle0+=    2.0*osg::PI/80;                                //angle += 2.0*osg::PI / 35.0;
        }
        //左上
        if (i>2&&i<22)
        {//(0.5,-1.1)
            v[i][0]=r*cosf(angle1)+0.5+x;        
            v[i][1]=r*sinf(angle1)-1.1+y;        
            angle1+=    2.0*osg::PI/80;                    
        }
        //左下
        if (i>23&&i<44)
        {//(0.5,-2.1)
            v[i][0]=r*cosf(angle2)+0.5+x;            
            v[i][1]=r*sinf(angle2)-2.1+y;            
            angle2+=    2.0*osg::PI/80;                    
        }
        //右下
        if (i>45&&i<66)
        {//(2.5,-2.1)
            v[i][0]=r*cosf(angle3)+2.5+x;    
            v[i][1]=r*sinf(angle3)-2.1+y;    
            angle3+=    2.0*osg::PI/80;                    
        }        
        //std::cout<<angle*180/3.14<<std::endl;    

        //计算纹理坐标
        coord[i][0]=(vertex[i][0]-x)/(3.0);
        coord[i][1]=(vertex[i][1]-y)/(-2.6);
    }

}

其中圆角部分我都是按照四分之一的扇形绘制的,之前由于绘制没注意顺序一直绘制不出来,后来发现要逆时针绘制,并且还要计算好点号;特别是矩形部分点号与扇形区域点号

每个扇形我分成20分,一个圆就是80份,所以在求angle的时候除以80,其实没必要分成angle0、1、2、3,不过我是刚开始实验,后面加减的x、y是希望以后添加鼠标点击位置显示。

调用函数计算几何坐标以及纹理坐标:

	osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();//多边形绘制
	osg::ref_ptr<osg::Texture2D>tex=new osg::Texture2D();//纹理
	osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array();//顶点
	osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array();//法线
	osg::ref_ptr<osg::Geode> geode = new osg::Geode();	//组节点
    



    //圆角矩形顶点坐标
	arrayVac(vertex);
	for (int i=0;i<90;i++)
	{
		v->push_back(osg::Vec3(vertex[i][0],vertex[i][1],0.0));
	}

    
	//设置纹理坐标
	osg::ref_ptr<osg::Vec2Array>coord1 = new osg::Vec2Array;	
	//圆角矩形纹理坐标
	for (int i=0;i<90;i++)
	{
		coord1->push_back(osg::Vec2(coord[i][0],coord[i][1]));
	}

将坐标添加到geom(Geometry)就OK啦。

### 如何使用 OpenSceneGraph (OSG) 绘制矩形 在 OSG 中,可以通过多种方式绘制矩形。以下是几种常见的方法: #### 方法一:使用 `osg::ShapeDrawable` 和 `osg::Box` 可以利用 `osg::Box` 创建一个立方体并调整其尺寸为扁平的矩形。 ```cpp #include <osg/Shape> #include <osg/Geode> #include <osgViewer/Viewer> // 创建矩形几何对象 osg::ref_ptr<osg::Geode> createRectangleWithBox() { osg::ref_ptr<osg::Box> box = new osg::Box; box->setCenter(osg::Vec3(0.0f, 0.0f, 0.0f)); // 设置中心点 box->setHalfLengths(osg::Vec3(2.0f, 1.0f, 0.0f)); // 宽度、高度和厚度 osg::ref_ptr<osg::ShapeDrawable> shapeDrawable = new osg::ShapeDrawable(box.get()); osg::ref_ptr<osg::Geode> geode = new osg::Geode; geode->addDrawable(shapeDrawable.get()); return geode.release(); } int main(int argc, char** argv) { osg::ref_ptr<osg::Group> root = new osg::Group; root->addChild(createRectangleWithBox()); osgViewer::Viewer viewer; viewer.setSceneData(root.get()); return viewer.run(); } ``` 此代码片段展示了如何通过 `osg::Box` 来模拟矩形形状[^5]。 --- #### 方法二:手动创建顶点数据 如果需要更灵活的方式,可以直接定义矩形的顶点坐标并通过 `osg::Geometry` 渲染。 ```cpp #include <osg/Geometry> #include <osg/Geode> #include <osgViewer/Viewer> // 手动创建矩形几何对象 osg::ref_ptr<osg::Geode> createRectangleManually() { osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry; std::vector<osg::Vec3> vertices = { {-1.0f, -1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {-1.0f, 1.0f, 0.0f} }; geometry->setVertexArray(new osg::Vec3Array(vertices.begin(), vertices.end())); std::vector<unsigned int> indices = { 0, 1, 2, 2, 3, 0 }; geometry->addPrimitiveSet(new osg::DrawElementsUInt(GL_TRIANGLES, indices)); osg::ref_ptr<osg::Geode> geode = new osg::Geode; geode->addDrawable(geometry); return geode.release(); } int main(int argc, char** argv) { osg::ref_ptr<osg::Group> root = new osg::Group; root->addChild(createRectangleManually()); osgViewer::Viewer viewer; viewer.setSceneData(root.get()); return viewer.run(); } ``` 这种方法提供了更高的灵活性,允许用户完全控制矩形的属性[^6]。 --- #### 方法三:使用纹理映射的平面 当需要带纹理的矩形时,可以结合 `osg::Texture2D` 和 `osg::StateSet` 实现。 ```cpp #include <osg/Texture2D> #include <osgDB/ReadFile> #include <osg/Geometry> #include <osg/Geode> #include <osgViewer/Viewer> // 带纹理的矩形 osg::ref_ptr<osg::Geode> createTexturedRectangle(const std::string& texturePath) { osg::ref_ptr<osg::Image> image = osgDB::readImageFile(texturePath); if (!image) return nullptr; osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D(image); osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry; std::vector<osg::Vec3> vertices = { {-1.0f, -1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {-1.0f, 1.0f, 0.0f} }; std::vector<osg::Vec2> texcoords = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} }; geometry->setVertexArray(new osg::Vec3Array(vertices.begin(), vertices.end())); geometry->setTexCoordArray(0, new osg::Vec2Array(texcoords.begin(), texcoords.end())); std::vector<unsigned int> indices = { 0, 1, 2, 2, 3, 0 }; geometry->addPrimitiveSet(new osg::DrawElementsUInt(GL_TRIANGLES, indices)); osg::ref_ptr<osg::StateSet> stateset = geometry->getOrCreateStateSet(); stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); osg::ref_ptr<osg::Geode> geode = new osg::Geode; geode->addDrawable(geometry); return geode.release(); } int main(int argc, char** argv) { osg::ref_ptr<osg::Group> root = new osg::Group; root->addChild(createTexturedRectangle("path/to/texture.jpg")); osgViewer::Viewer viewer; viewer.setSceneData(root.get()); return viewer.run(); } ``` 这段代码展示了一个带有纹理贴图的矩形实现[^7]。 --- ### 总结 以上三种方法分别适用于不同的场景需求: - **方法一**适合快速原型开发; - **方法二**提供更大的自由度; - **方法三**则用于处理复杂的材质效果。 每种方法都有其适用范围,具体选择取决于实际项目中的功能需求和技术约束条件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值