gpt4 book ai didi

c++ - 带有两组 Geodes 的扭曲场景

转载 作者:太空宇宙 更新时间:2023-11-04 11:28:55 26 4
gpt4 key购买 nike

我有几个对象要合并到场景图中。

  1. Street继承自 Geode并且有一个 Geometry由 GL_LINE_STRIP 组成的子可绘制对象。

  2. Pointer继承自 PositionAttitudeTransform并包含 Geode其中包含两个 Geometry多边形。

当我将一堆街道添加到 Group 时,看起来还不错。当我仅将指针添加到 Group 时,看起来也不错。但是,如果我以某种方式将它们都放在场景中,那么第二个就搞砸了。看两张图。

One view when the streets are first

上图中,街道网络如愿,下图中,指针如愿。

One view when the pointer is first

如果有任何帮助,我将不胜感激!如果您需要查看代码,请告诉我,我会更新我的问题。

更新 1: 由于到目前为止什么都没有发生,这里是产生该现象所需的最少代码量。我已经将两个指针并排放置,没有问题,所以我开始怀疑我弄错了街道……下一次更新将是一些街道生成代码。

更新 2:代码现在包含街道绘图代码。

更新 3:代码现在也包含指针绘图代码,以及街道绘图代码已被简化。

// My libraries:
#include <asl/util/color.h>
using namespace asl;

#include <straph/point.h>
#include <straph/straph.h>
using namespace straph;

// Standard and OSG libraries:
#include <utility>
#include <boost/tuple/tuple.hpp> // tie
using namespace std;

#include <osg/ref_ptr>
#include <osg/Array>
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/Group>
#include <osg/LineWidth>
using namespace osg;

#include <osgUtil/Tessellator>
#include <osgViewer/Viewer>
using namespace osgViewer;

/*
* Just FYI: A Polyline looks like this:
*
* typedef std::vector<Point> Polyline;
*
* And a Point basically is a simple struct:
*
* struct Point {
* double x;
* double y;
* };
*/

inline osg::Vec3d toVec3d(const straph::Point& p, double elevation=0.0)
{
return osg::Vec3d(p.x, p.y, elevation);
}

Geometry* createStreet(const straph::Polyline& path)
{
ref_ptr<Vec3dArray> array (new Vec3dArray(path.size()));
for (unsigned i = 0; i < path.size(); ++i) {
(*array)[i] = toVec3d(path[i]);
}
Geometry* geom = new Geometry;
geom->setVertexArray(array.get());
geom->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, array->size()));
return geom;
}

Geode* load_streets()
{
unique_ptr<Straph> graph = read_shapefile("mexico/roads", 6);

Geode* root = new Geode();
boost::graph_traits<straph::Straph>::edge_iterator ei, ee;
for (boost::tie(ei, ee) = edges(*graph); ei != ee; ++ei) {
const straph::Segment& s = (*graph)[*ei];
root->addDrawable(createStreet(s.polyline));
}
return root;
}

Geode* createPointer(double width, const Color& body_color, const Color& border_color)
{
float f0 = 0.0f;
float f3 = 3.0f;
float f1 = 1.0f * width;
float f2 = 2.0f * width;

// Create vertex array
ref_ptr<Vec3Array> vertices (new Vec3Array(4));
(*vertices)[0].set( f0 , f0 , f0 );
(*vertices)[1].set( -f1/f3, -f1/f3 , f0 );
(*vertices)[2].set( f0 , f2/f3 , f0 );
(*vertices)[3].set( f1/f3, -f1/f3 , f0 );

// Build the geometry object
ref_ptr<Geometry> polygon (new Geometry);
polygon->setVertexArray( vertices.get() );
polygon->addPrimitiveSet( new DrawArrays(GL_POLYGON, 0, 4) );

// Set the colors
ref_ptr<Vec4Array> body_colors (new Vec4Array(1));
(*body_colors)[0] = body_color.get();
polygon->setColorArray( body_colors.get() );
polygon->setColorBinding( Geometry::BIND_OVERALL );

// Start the tesselation work
osgUtil::Tessellator tess;
tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY );
tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_ODD );
tess.retessellatePolygons( *polygon );

// Create the border-lines
ref_ptr<Geometry> border (new Geometry);
border->setVertexArray( vertices.get() );
border->addPrimitiveSet(new DrawArrays(GL_LINE_LOOP, 0, 4));
border->getOrCreateStateSet()->setAttribute(new LineWidth(2.0f));

ref_ptr<Vec4Array> border_colors (new Vec4Array(1));
(*border_colors)[0] = border_color.get();
border->setColorArray( border_colors.get() );
border->setColorBinding( Geometry::BIND_OVERALL );

// Create Geode object
ref_ptr<Geode> geode (new Geode);
geode->addDrawable( polygon.get() );
geode->addDrawable( border.get() );

return geode.release();
}

int main(int, char**)
{
Group* root = new Group();

Geode* str = load_streets();
root->addChild(str);

Geode* p = createPointer(6.0, TangoColor::Scarlet3, TangoColor::Black);
root->addChild(p);

Viewer viewer;
viewer.setSceneData(root);
viewer.getCamera()->setClearColor(Color(TangoColor::White).get());
viewer.run();
}

最佳答案

在函数 createStreet 中,我使用 Vec3dArray 作为顶点数组,而在 createPointer 函数中,我使用 Vec3Array 。在图书馆我猜它期望所有节点由 float double 组成,但不能同时由两者组成。更改这两个函数解决了问题:

inline osg::Vec3 toVec3(const straph::Point& p, float elevation=0.0)
{
return osg::Vec3(float(p.x), float(p.y), elevation);
}

Geometry* createStreet(const straph::Polyline& path)
{
ref_ptr<Vec3Array> array (new Vec3Array(path.size()));
for (unsigned i = 0; i < path.size(); ++i) {
(*array)[i] = toVec3(path[i]);
}
Geometry* geom = new Geometry;
geom->setVertexArray(array.get());
geom->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, array->size()));
return geom;
}

这里是 Robert Osfield 的评论:

I can only provide a guess, and that would be that the Intel OpenGL doesn't handle double vertex data correctly, so you are stumbling across a driver bug.

In general OpenGL hardware is based around floating point maths so the drivers normally convert any double data you pass it into floats before passing it to the GPU. Even if the driver does this correctly this conversion process slows performance down so it's best to keep osg::Geometry vertex/texcoord/normal etc. data all in float arrays such as Vec3Array.

You can retain precision by translating your data to a local origin prior to conversion to float then place a MatrixTransform above your data to place it in the correct 3D position. The OSG by default uses double for all internal matrices that that when it accumulates the modelvew matrix during the cull traversal double precision is maintain for as long as possible before passing the final modelview matrix to OpenGL. Using this technique the OSG can handle whole earth data without any jitter/precision problems.

关于c++ - 带有两组 Geodes 的扭曲场景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25576762/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com