Analysis of two methods for three-dimensional reconstruction of OSG: Triangular Patches (osgutil::D elaunaytriangulator) and four-corner patches (Osg::heightfield)

Source: Internet
Author: User

The recent project requires the use of OSG to reconstruct three-dimensional surfaces, so I learned a bit.

First, I first used the method of the Baroque triangle, namely Osgutil::D Elaunaytriangulator, the characteristic of this method is:

1. First must give it a storage of three-dimensional point set of the array, the method will automatically sort these chaotic scattered points, and then use these ordered, in line with the triangular network construction rules of the scatter point to build a triangular network, it should be noted that after Dt->setinputpointarray (coords After this sentence, the order of the values of the array coords has changed, no longer the original coords.

2. To paste the texture again, you must first set a color array to it, it should be noted that the texture of the coordinates are 0~1 range, and is two-dimensional (x, y), so the coords coordinates must be mapped to the X and Y values of the 0~1 range.

3. Must output the normal vector, and use the method vector array to the corresponding geometry assignment

The specific code is as follows:

//create Delaunay Triangle Mesh Object
 osg::ref_ptr<osgutil::D elaunaytriangulator> DT = new Osgutil::D elaunaytriangulator ();
 dt->setinputpointarray (coords);//assigns it a three-dimensional point set array
 dt->setoutputnormalarray (normals);//Output normal vector
 //generates a triangulated network
 dt->triangulate ();
 osg::ref_ptr<osg::Geometry> Geometry = new Osg::geometry ();
 //Set coordinates
 geometry->setvertexarray (Coords.get ());
 //Settings Description
 geometry->addprimitiveset (Dt->gettriangles ());
 //set Normal
 geometry->setnormalarray (Normals.get ());
 geometry->setnormalbinding (osg::geometry::bind_per_primitive);
 //Set texture coordinates (texture fill)
 osg::ref_ptr<osg::Vec2Array> texcoords = computertexturecoords (* ( Coords.get ()));//Get one by one after mapping the range in 0~1 's two-dimensional texture array
 geometry->settexcoordarray (0,texcoords.get ());

Try a color fill
osg::ref_ptr<osg::vec4array> Vextexcolorarray = Computepervertexcolor (* (Coords.get ()), getOSGColorTable ()) ;
Geometry->setcolorarray (Vextexcolorarray);
Geometry->setcolorbinding (Osg::geometry::bind_per_vertex);

Preparing texture Images

Create a pair of qimage that give each pixel a predefined color assignment. Finally, save as a PNG image, save by Image.Save (strpath) parameter is to save the full file name, including the path and suffix.

Qimage image (XCOUNT,YCOUNT,QIMAGE::FORMAT_INDEXED8);
qvector<qrgb> colortable = getcolortable ();
Image.setcolortable (colortable);
Interpolateanddrawimage (Veczs,&image,xcount,ycount,xcount,ycount);
QString StrName =:: Getimagepath () + pcontourdata->getname () + ". png";
Image.Save (strName);//Save as PNG image

Start creating textures with PNG images
osg::ref_ptr<osg::image> teximage = Osgdb::readimagefile (strname.tostdstring ());

Osg::ref_ptr<osg::texture2d> tex = new Osg::texture2d;
Tex->setimage (Teximage.get ());
Tex->setdatavariance (osg::object::D ynamic);

osg::ref_ptr<osg::stateset> stateset = new Osg::stateset ();
Stateset->settextureattributeandmodes (0,tex.get (), osg::stateattribute::on);


osg::ref_ptr<osg::geode> Geode = new Osg::geode ();
Geode->adddrawable (Geometry.get ());
Geode->setstateset (Stateset.get ());

Set Matrix transformation matrix
M_prootswitch->addchild (Geode);

By using triangular patches to reconstruct the three-dimensional surface, the effect of texture rendering is already out, but it is important to note that if the point set is a regular grid data, the construction of this method is not suitable and should be used in the way of Osg::heightfield.

Two or four side-shaped patches

This approach is built with the following features:

1 It must be assigned a row number, that is, how many rows of the grid are constructed, using allocate (unsigned int rownum,unsigned int columnnum) function to allocate.

2. It must be given an initial position, specified with Setorigin (const osg::vec3& origin), notice that the z-axis of the three-dimensional vertex array is set to 0, and the smallest x, y in the point set.

3. The interval between each column in the x and Y directions must be specified with Setxinterval (float dx) and setyinterval (float dy).

4. With the initial position, row number, and interval, you can calculate the position of each vertex of the quadrilateral patch, then set the elevation value at each location, with setheight (float height)

The implementation process is as follows, the texture rendering process is similar to triangular patches, just one less step is: Do not need to set the texture coordinates, with simple and easy.

osg::ref_ptr<osg::heightfield> Pheightfield = new Osg::heightfield ();
 pheightfield->allocate (Xcount,ycount);
 pheightfield->setorigin (OSG::VEC3 (xmin,ymin,0));
 pheightfield->setxinterval (Xdelta);
 pheightfield->setyinterval (Ydelta);
 
 float x, y;
 for (int i = 0; i < Ycount; i++)
 {
  for (int j = 0; J < Xcount; J + +)
  {
   x = XMin + J * XDELTA;
   y = ymin + i * YDELTA;
   double z = Pinterpolater->getinterpolatedz (X,y,input.begin (), Input.end ());
   veczs.push_back (-z+zmin);
   coords->push_back (Geotogeonormal (osg::vec3f (x,y,0)));
   
   pheightfield->setheight (j,ycount-i-1,-z);//loop to get each vertex and set Z-values for it
  }
 }

Drawing Texture Images
Qimage image (XCOUNT,YCOUNT,QIMAGE::FORMAT_INDEXED8);
qvector<qrgb> colortable = getcolortable ();
Image.setcolortable (colortable);
Interpolateanddrawimage (Veczs,&image,xcount,ycount,xcount,ycount);
QString StrName =:: Getimagepath () + pcontourdata->getname () + ". png";
Image.Save (StrName);
osg::ref_ptr<osg::image> teximage = Osgdb::readimagefile (strname.tostdstring ());

Osg::ref_ptr<osg::texture2d> tex = new Osg::texture2d;
Tex->setimage (Teximage.get ());
Tex->setdatavariance (osg::object::D ynamic);

osg::ref_ptr<osg::stateset> stateset = new Osg::stateset ();
Stateset->settextureattributeandmodes (0,tex.get (), osg::stateattribute::on);

osg::ref_ptr<osg::geode> Geode = new Osg::geode ();
Geode->adddrawable (New Osg::shapedrawable (Pheightfield.get ()));
Geode->setstateset (Stateset.get ());



Appendix: Three functions used to paste textures:

The first mapping of the true vertex coordinate one by one to the (0~1) range

Osg::ref_ptr<osg::vec2array> cosg3dsurfacenode::computertexturecoords (const Osg::vec3array & VP)
{
osg::ref_ptr<osg::vec2array> texcoords = new Osg::vec2array ();
int nSize = Vp.size ();

float MaxX = vp[0].x ();
float MinX = MaxX;
float Maxy = Vp[0].y ();
float miny = Maxy;

for (int i=0;i<nsize;i++)
{
MaxX = maxx<vp[i].x ()? vp[i].x (): MaxX;
MinX = minx>vp[i].x ()? vp[i].x (): MinX;
Maxy = Maxy<vp[i].y ()? Vp[i].y (): Maxy;
Miny = Miny>vp[i].y ()? Vp[i].y (): Miny;
}

for (int i = 0;i< nSize; i++)
{
float XValue = n (maxx-vp[i].x ())/(Maxx-minx);
float Yvalue = n (maxy-vp[i].y ())/(Maxy-miny);
float Yvalue = n (vp[i].y ()-miny)/(Maxy-miny);
Texcoords->push_back (OSG::VEC2 (Xvalue,yvalue));
}

return texcoords;
}

Second, the color array is obtained by the color configuration file

Qvector<qrgb> cosg3dsurfacenode::getcolortable ()
{
qvector<qrgb> table;

QString Colotpath =:: Getimagepath () + "colorbar.txt";
QFile file (Colotpath);
if (!file.open (qiodevice::readonly))
{
ASSERT (FALSE);
}

Qtextstream Wxstream (&file);
for (int i=0;i<32;i++)
{
Float Rcolor (0.0), Gcolor (0.0), Bcolor (0.0), acolor (1.0);
OSG::VEC4 Vcolor;
wxstream>>rcolor>>gcolor>>bcolor;
Table.push_back (Qrgb (rcolor*255,gcolor*255,bcolor*255));
}

return table;
}

Third, generate texture image, according to color configuration file to the image pixel to assign value

void Cosg3dsurfacenode::interpolateanddrawimage (const std::vector<float>& vecdata,qimage* pImage,int Xcount,int ycount,int imagesizex,int Imagesizey)
{
ASSERT (Xcount > 0);
ASSERT (Ycount > 0);
ASSERT (vecdata.size () = = Xcount * ycount);

float min = vecdata[0];
float max = vecdata[0];
for (int i = 0; i < vecdata.size (); i++)
{

if (Max < vecdata[i]) max = Vecdata[i];
if (min > vecdata[i]) min = vecdata[i];
}

Double colorfactor = getcolortable (). Size ()/(max-min);
Todo image interpolation
for (int i = 0; i < Imagesizex; i++)
{
for (int j = 0; J < Imagesizey; J + +)
{
Pimage->setpixel (I,j, (Vecdata[j*xcount + i]-min) * colorfactor);
}
}
Pimage->save (:: Getimagepath () + "123.png");
}


M_prootswitch->addchild (Geode);


Eventually:




Analysis of two methods for three-dimensional reconstruction of OSG: Triangular Patches (osgutil::D elaunaytriangulator) and four-corner patches (Osg::heightfield)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.