CGAL - cannot use import_from_polyhedron_3 - c++

I want to simplify a surface read from .off file and view it using CGAL.
I read the surface as Polyhedron_3 and I want to convert it to Linear_cell_complex_for_combinatorial_map to view it but there is a problem in import_from_polyhedron_3 method
my code:
typedef CGAL::Linear_cell_complex_for_combinatorial_map<2,3> LCC_3;
typedef LCC_3::Dart_handle Dart_handle;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
QWidget* viewer ;
QString fileName;
LCC_3 lcc;
QMainWindow qWin;
CGAL::DefaultColorFunctorLCC fcolor;
Polyhedron P;
void MainWindow::preview()
{
QWidget* centralWidget = new QWidget(viewer);
centralWidget->setSizePolicy(QSizePolicy::Maximum,QSizePolicy::Maximum);
CGAL::import_from_polyhedron_3<LCC_3, Polyhedron>(lcc, P);
setCentralWidget( new CGAL::SimpleLCCViewerQt<LCC_3, CGAL::DefaultColorFunctorLCC>(&qWin ,
lcc,
"Basic LCC Viewer",
false,
fcolor ) );
show();
}
void MainWindow::fileOpen()
{
fileName = QFileDialog::getOpenFileName(this,tr("Select object"), ".", tr("*.off"));
std::ofstream out(fileName.toLocal8Bit());
out<<P;
preview();
}
void MainWindow ::simplify()
{
bool ok;
int n = QInputDialog::getInt(this, "", tr("Number of vertices in each cell:"),P.size_of_vertices(),0, P.size_of_vertices(),1, &ok);
if (ok){
int r = P.size_of_vertices() - n;
int target_edges = P.size_of_halfedges()/2 - r*3;
n=target_edges+1;
}
typedef CGAL::Polyhedron_3<Kernel> Surface;
SaveOFF("temp.off");
namespace SMS = CGAL::Surface_mesh_simplification ;
Surface surface;
std::ifstream is("temp.off") ; is >> surface ;
// This is a stop predicate (defines when the algorithm terminates).
// In this example, the simplification stops when the number of undirected edges
// left in the surface drops below the specified number (1000)
SMS::Count_stop_predicate<Surface> stop(n);
// This the actual call to the simplification algorithm.
// The surface and stop conditions are mandatory arguments.
// The index maps are needed because the vertices and edges
// of this surface lack an "id()" field.
int r = SMS::edge_collapse
(surface
,stop
,CGAL::parameters::vertex_index_map(get(CGAL::vertex_external_index,surface))
.halfedge_index_map (get(CGAL::halfedge_external_index ,surface))
);
std::ofstream os("temp.off"); os << surface ;
OpenOFF("temp.off");
std::cout << "Finished..." << r << " edges removed."<<std::endl;
std::cout<<P.size_of_vertices()<<" Vertices"<<std::endl;
std::cout<<P.size_of_facets()<<" Facets"<<std::endl;
std::cout<<P.size_of_halfedges()<<" Halfedges"<<std::endl;
preview();
}
it shows me the following error:
‘import_from_polyhedron_3’ is not a member of ‘CGAL’
CGAL::import_from_polyhedron_3(lcc, P);
another problem it cannot reload the surface in the viewer after simplifying it , it shows the following error :
it's shows error "The inferior stopped because it received a signal from the operating system."
I need any help please
thanks

Missing #include< CGAL/Polyhedron_3_to_lcc.h > (cf doc here)

Related

Mouse control is lost after using vtk interactor

I'm trying to visualize a vtk unstructuredgrid mesh.
In order to get the coordinate of a point of my mesh I use the vtk interactor.
I'm able to get the point coordinate by selecting the point using OnRightButtonDown() "overrid"
. However, I loose control of my window . means I can not rotate, translate or zoom my mesh.
I tried to do use OnRightButtonDoubleClick() but this doesn't seem to work . Any idea how may I
get the node coordinate using the interactor without affecting the mouse event behavior or how to re-initialize it when the mouse button is Up...
foo
{
...
// vtk visualization
container = new QWidget(ui->graphicsView);
qvtkWidget = new QVTKOpenGLNativeWidget(container);
...
//Create and link the mapper actor and renderer together.
mapper = vtkSmartPointer<vtkDataSetMapper>::New();
actor = vtkSmartPointer<vtkActor>::New();
renderer = vtkSmartPointer<vtkRenderer>::New();
...
// add elements nodes
...
mapper->SetInputData(eleNodeIdsPtr);
actor->SetMapper(mapper);
renderer->AddActor(actor);
// ste up camera
renderer->SetBackground(0.06, 0.2, 0.5);
double pos[3] = { 0, 0.2, 1 };
double focalPoint[3] = { 0, 0, 0 };
double viewUp[3] = { 1, 1, 1 };
renderer->GetActiveCamera()->SetPosition(pos);
renderer->GetActiveCamera()->SetFocalPoint(focalPoint);
renderer->GetActiveCamera()->SetViewUp(viewUp);
renderer->GetActiveCamera()->Zoom(0.5);
//Add render
qvtkWidget->GetRenderWindow()->AddRenderer(renderer);
qvtkWidget->show();
// Select node
renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(qvtkWidget-
>GetRenderWindow());
vtkNew<InteractorStyle2> style;
renderWindowInteractor->SetInteractorStyle(style);
style->eleNodeIdsPtr = eleNodeIdsPtr;
style->xyzGlobalPtr = xyzGlobalPtr;
renderWindowInteractor->Initialize();
}
// Define interaction style
class InteractorStyle2 : public vtkInteractorStyleTrackballActor
{
public:
static InteractorStyle2* New();
vtkTypeMacro(InteractorStyle2, vtkInteractorStyleTrackballActor);
vtkNew<vtkNamedColors> color;
...
void OnLeftButtonDown() //...>>>This doesn't work!!
{
}
void OnLeftButtonDown() override // .. this work but the I can't controle the transformation anymore!!
{
this->PointPicker = vtkSmartPointer<vtkPointPicker>::New();
// Get the selected point
int x = this->Interactor->GetEventPosition()[0];
int y = this->Interactor->GetEventPosition()[1];
this->FindPokedRenderer(x, y);
this->PointPicker->Pick(this->Interactor->GetEventPosition()[0],
this->Interactor->GetEventPosition()[1],
0, // always zero.
this->Interactor->GetRenderWindow()
->GetRenderers()
->GetFirstRenderer());
if (this->PointPicker->GetPointId() >= 0)
{
this->StartPan();
this->SelectedPoint = this->PointPicker->GetPointId();
double p[3];
this->eleNodeIdsPtr->GetPoint(this->SelectedPoint, p);
std::cout << "p: " << p[0] << " " << p[1] << " " << p[2] << std::endl;
}
}
vtkSmartPointer<vtkPointPicker> PointPicker;
vtkIdType SelectedPoint;
vtkSmartPointer<vtkUnstructuredGrid> eleNodeIdsPtr;
vtkSmartPointer< vtkPoints > xyzGlobalPtr;
}
vtkStandardNewMacro(InteractorStyle2);
}
You should call the OnLeftButtonDown (or up) of the parent class, by adding this line at the end of your method impl:
vtkInteractorStyleTrackballActor::OnLeftButtonDown();
A similar example

VTK: View doesn't update until after user interaction

TL;DR
I have a pipeline which reads an image and displays a mesh using VTK; upon changing the input to the image reader and updating the pipeline, the mesh doesn't update until I interact with the window.
The Long Version
I have a directory with a sequence of segmentation files (i.e., 3D image volumes where pixel values correspond to structures in a corresponding image) which show how a structure changes over time. I've written a utility in VTK which allows me to load the first image in the directory, visualize a label as a mesh, and "step" forwards or backwards using the arrow keys by changing the file name of the input image and updating the pipeline. This very nearly works--the only issue is that, after updating the pipeline, the meshes don't update until I interact with the window (simply clicking anywhere in the window causes the mesh to update, for example).
What I've Tried:
Calling Update() on the reader:
this->reader->Update();
Calling Modified() on the actors:
const auto actors = this->GetCurrentRenderer()->GetActors();
actors->InitTraversal();
for (vtkIdType i = 0; i < actors->GetNumberOfItems(); ++i)
{
actors->GetNextActor()->Modified();
}
Calling Render() on the current render window:
this->GetCurrentRenderer()->Render();
MCVE:
NOTE: the reader is updated in KeyPressInteractorStyle::UpdateReader().
// VTK
#include <vtkSmartPointer.h>
#include <vtkNIFTIImageReader.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkCamera.h>
#include <vtkDiscreteMarchingCubes.h>
#include <vtkProperty.h>
#include <vtkInteractorStyleTrackballCamera.h>
// Define interaction style
class KeyPressInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:
static KeyPressInteractorStyle* New();
vtkTypeMacro(KeyPressInteractorStyle, vtkInteractorStyleTrackballCamera);
virtual void OnKeyPress()
{
// Get the keypress
vtkRenderWindowInteractor *rwi = this->Interactor;
std::string key = rwi->GetKeySym();
// Output the key that was pressed
std::cout << "Pressed " << key << std::endl;
// Handle an arrow key
if(key == "Down" || key == "Right")
{
this->index += 1;
this->UpdateReader();
}
// Handle an arrow key
if(key == "Up" || key == "Left")
{
this->index -= 1;
this->UpdateReader();
}
// Forward events
vtkInteractorStyleTrackballCamera::OnKeyPress();
}
void UpdateReader()
{
std::cout << "Frame: " << this->index << std::endl;
const auto fn = this->directory + std::to_string(this->index) + ".nii.gz";
std::cout << fn << std::endl;
this->reader->SetFileName( fn.c_str() );
this->reader->Update();
const auto actors = this->GetCurrentRenderer()->GetActors();
actors->InitTraversal();
for (vtkIdType i = 0; i < actors->GetNumberOfItems(); ++i)
{
actors->GetNextActor()->Modified();
}
this->GetCurrentRenderer()->Render();
}
unsigned int index = 0;
std::string directory;
vtkSmartPointer<vtkNIFTIImageReader> reader;
};
vtkStandardNewMacro(KeyPressInteractorStyle);
int
main( int argc, char ** argv )
{
std::string dn = argv[1];
const auto renderer = vtkSmartPointer<vtkRenderer>::New();
unsigned int frameid = 0;
const auto reader = vtkSmartPointer<vtkNIFTIImageReader>::New();
reader->SetFileName( (dn + std::to_string(frameid) + ".nii.gz").c_str() );
const auto cubes = vtkSmartPointer<vtkDiscreteMarchingCubes>::New();
cubes->SetInputConnection( reader->GetOutputPort() );
cubes->SetValue( 0, 1 );
const auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection( cubes->GetOutputPort() );
mapper->ScalarVisibilityOff();
const auto actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper( mapper );
renderer->AddActor( actor );
const auto window = vtkSmartPointer<vtkRenderWindow>::New();
window->AddRenderer( renderer );
const auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
const auto style = vtkSmartPointer<KeyPressInteractorStyle>::New();
style->reader = reader;
style->directory = dn;
interactor->SetInteractorStyle( style );
style->SetCurrentRenderer( renderer );
interactor->SetRenderWindow( window );
window->Render();
interactor->Start();
return EXIT_SUCCESS;
}
You have actually not tried to call Render() on the current render window, you are calling it on the current renderer, which are two different things. As the documentation of vtkRenderer::Renderer() states,
CALLED BY vtkRenderWindow ONLY.
End-user pass your way and call vtkRenderWindow::Render(). Create an
image. This is a superclass method which will in turn call the
DeviceRender method of Subclasses of vtkRenderer.
So change this->GetCurrentRenderer()->Render(); to this->GetCurrentRenderer()->GetRenderWindow()->Render();

how to create a graphics object using an Atom text editor

I am having a hard time determining a way to include graphics.h file in my compiler. All information I have came across is for IDE such as CodeBlocks. I would like to be able include graphics file for use without facing any problems. My questions are:
Can you use a text editor like Atom to create a graphics object?
If so what steps should be taken in order to accomplish that?
There are lot of graphics formats available with varying capabilities.
First distinction I would make is:
raster graphics vs. vector graphics
Raster graphics (storing the image pixel by pixel) are more often binary encoded as the amount of data is usally directly proportional to size of image. However some of them are textual encoded or can be textual as well as binary encoded.
Examples are:
Portable anymap
X Pixmap
Although these file formats are a little bit exotic, it is not difficult to find software which supports them. E.g. GIMP supports both out of the box (and even on Windows). Btw. they are that simple that it is not too complicated to write loader and writer by yourself.
A simple reader and writer for PPM (the color version of Portable anymap) can be found in my answer to SO: Convolution for Edge Detection in C.
Vector graphics (store graphics primitives which build the image) are more often textual encoded. As vector graphics can be "loss-less" scaled to any image size by simply applying a scaling factor to all coordinates, file size and destination image size are not directly related. Thus, vector graphics are the preferrable format for drawings especially if they are needed in multiple target resolutions.
For this, I would exclusively recommend:
Scalable Vector Graphics
which is (hopefully) the upcoming standard for scalable graphics in Web contents. Qt does provide (limited) support for SVG and thus, it is my preferred option for resolution independent icons.
A different (but maybe related) option is to embed graphics in source code. This can be done with rather any format if your image loader library provides image loading from memory (as well as from file). (All I know does this.)
Thus, the problem can be reduced to: How to embed a large chunk of (ASCII or binary) data as constant in C/C++ source code? which is IMHO trivial to solve.
I did this in my answer for SO: Paint a rect on qglwidget at specifit times.
Update:
As I noticed that the linked sample for PPM (as well as another for PBM) read actually the binary format, I implemented a sample application which demonstrates usage of ASCII PPM.
I believe that XPM is better suitable for the specific requirement to be editable in a text editor. Thus, I considered this in my sample also.
As the question doesn't mention what specific internal image format is desired nor in what API it shall be usable, I choosed Qt which
is something I'm familiar with
provides a QImage which is used as destination for image import
needs only a few lines of code for visual output of result.
Source code test-QShowPPM-XPM.cc:
// standard C++ header:
#include <cassert>
#include <iostream>
#include <string>
#include <sstream>
// Qt header:
#include <QtWidgets>
// sample image in ASCII PPM format
// (taken from https://en.wikipedia.org/wiki/Netpbm_format)
const char ppmData[] =
"P3\n"
"3 2\n"
"255\n"
"255 0 0 0 255 0 0 0 255\n"
"255 255 0 255 255 255 0 0 0\n";
// sample image in XPM3 format
/* XPM */
const char *xpmData[] = {
// w, h, nC, cPP
"16 16 5 1",
// colors
" c #ffffff",
"# c #000000",
"g c #ffff00",
"r c #ff0000",
"b c #0000ff",
// pixels
" ## ",
" ###gg### ",
" #gggggggg# ",
" #gggggggggg# ",
" #ggbbggggbbgg# ",
" #ggbbggggbbgg# ",
" #gggggggggggg# ",
"#gggggggggggggg#",
"#ggrrggggggrrgg#",
" #ggrrrrrrrrgg# ",
" #ggggrrrrgggg# ",
" #gggggggggggg# ",
" #gggggggggg# ",
" #gggggggg# ",
" ###gg### ",
" ## "
};
// Simplified PPM ASCII Reader (no support of comments)
inline int clamp(int value, int min, int max)
{
return value < min ? min : value > max ? max : value;
}
inline int scale(int value, int maxOld, int maxNew)
{
return value * maxNew / maxOld;
}
QImage readPPM(std::istream &in)
{
std::string header;
std::getline(in, header);
if (header != "P3") throw "ERROR! Not a PPM ASCII file.";
int w = 0, h = 0, max = 255; // width, height, bits per component
if (!(in >> w >> h >> max)) throw "ERROR! Premature end of file.";
if (max <= 0 || max > 255) throw "ERROR! Invalid format.";
QImage qImg(w, h, QImage::Format_RGB32);
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
int r, g, b;
if (!(in >> r >> g >> b)) throw "ERROR! Premature end of file.";
qImg.setPixel(x, y,
scale(clamp(r, 0, 255), max, 255) << 16
| scale(clamp(g, 0, 255), max, 255) << 8
| scale(clamp(b, 0, 255), max, 255));
}
}
return qImg;
}
// Simplified XPM Reader (implements sub-set of XPM3)
char getChar(const char *&p)
{
if (!*p) throw "ERROR! Premature end of file.";
return *p++;
}
std::string getString(const char *&p)
{
std::string str;
while (*p && !isspace(*p)) str += *p++;
return str;
}
void skipWS(const char *&p)
{
while (*p && isspace(*p)) ++p;
}
QImage readXPM(const char **xpmData)
{
int w = 0, h = 0; // width, height
int nC = 0, cPP = 1; // number of colors, chars per pixel
{ std::istringstream in(*xpmData);
if (!(in >> w >> h >> nC >> cPP)) throw "ERROR! Premature end of file.";
++xpmData;
}
std::map<std::string, std::string> colTbl;
for (int i = nC; i--; ++xpmData) {
const char *p = *xpmData;
std::string chr;
for (int j = cPP; j--;) chr += getChar(p);
skipWS(p);
if (getChar(p) != 'c') throw "ERROR! Format not supported.";
skipWS(p);
colTbl[chr] = getString(p);
}
QImage qImg(w, h, QImage::Format_RGB32);
for (int y = 0; y < h; ++y, ++xpmData) {
const char *p = *xpmData;
for (int x = 0; x < w; ++x) {
std::string pixel;
for (int j = cPP; j--;) pixel += getChar(p);
qImg.setPixelColor(x, y, QColor(colTbl[pixel].c_str()));
}
}
return qImg;
}
// a customized QLabel to handle scaling
class LabelImage: public QLabel {
private:
QPixmap _qPixmap, _qPixmapScaled;
public:
LabelImage();
LabelImage(const QPixmap &qPixmap): LabelImage()
{
setPixmap(qPixmap);
}
LabelImage(const QImage &qImg): LabelImage(QPixmap::fromImage(qImg))
{ }
void setPixmap(const QPixmap &qPixmap) { setPixmap(qPixmap, size()); }
protected:
virtual void resizeEvent(QResizeEvent *pQEvent);
private:
void setPixmap(const QPixmap &qPixmap, const QSize &size);
};
// main function
int main(int argc, char **argv)
{
qDebug() << QT_VERSION_STR;
// main application
#undef qApp // undef macro qApp out of the way
QApplication qApp(argc, argv);
// setup GUI
QMainWindow qWin;
QGroupBox qBox;
QGridLayout qGrid;
LabelImage qLblImgPPM(readPPM(std::istringstream(ppmData)));
qGrid.addWidget(&qLblImgPPM, 0, 0, Qt::AlignCenter);
LabelImage qLblImgXPM(readXPM(xpmData));
qGrid.addWidget(&qLblImgXPM, 1, 0, Qt::AlignCenter);
qBox.setLayout(&qGrid);
qWin.setCentralWidget(&qBox);
qWin.show();
// run application
return qApp.exec();
}
// implementation of LabelImage
LabelImage::LabelImage(): QLabel()
{
setFrameStyle(Raised | Box);
setAlignment(Qt::AlignCenter);
//setMinimumSize(QSize(1, 1)); // seems to be not necessary
setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored));
}
void LabelImage::resizeEvent(QResizeEvent *pQEvent)
{
QLabel::resizeEvent(pQEvent);
setPixmap(_qPixmap, pQEvent->size());
}
void LabelImage::setPixmap(const QPixmap &qPixmap, const QSize &size)
{
_qPixmap = qPixmap;
_qPixmapScaled = _qPixmap.scaled(size, Qt::KeepAspectRatio);
QLabel::setPixmap(_qPixmapScaled);
}
This has been compiled in VS2013 and tested in Windows 10 (64 bit):

Warped scene with two sets of Geodes

I have a few objects that I want to combine into a scene graph.
Street inherits from Geode and has a Geometry child drawable made up of a GL_LINE_STRIP.
Pointer inherits from PositionAttitudeTransform and contains a Geode which contains two Geometry polygons.
When I add a bunch of Streets to a Group, it looks just fine. When I add only the Pointer to a Group, it also looks fine. But if I somehow have them both in the scene, the second one is screwed up. See the two pictures.
In the above picture, the street network is as desired, and in the picture below, the pointer is as desired.
I'd appreciate any help! If you need to see the code, let me know and I'll update my question.
Update 1: Since nothing has happened so far, here is the minimal amount of code necessary to produce the phenomenon. I have put two pointers next to each other with no problem, so I'm starting to suspect that I made the streets wrong... next update will be some street generation code.
Update 2: The code now contains the street drawing code.
Update 3: The code now contains the pointer drawing code as well, and the street drawing
code has been simplified.
// 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();
}
In the functions createStreet I use a Vec3dArray for the vertex array, whereas in the createPointer function, I use a Vec3Array. In the library I guess it expects all nodes
to be composed of floats or doubles, but not both. Changing these two functions solves the problem:
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;
}
Here a comment by 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.

Rotate a 3D object (OSG & vc++)

I'm developing a 3D environment using VC++ and OSG and I need some help
I'm using this code below to charge the 3D models for the scene
mueble00Node = osgDB::readNodeFile("Model/mueble_desk.3ds");
mueble00Transform = new osg::MatrixTransform;
mueble00Transform->setName("mueble00");
mueble00Transform->setDataVariance(osg::Object::STATIC);
mueble00Transform->addChild(mueble00Node);
sceneRoot->addChild(mueble00Transform);
I've tried with some lines to rotate the 3D models, but with no result
Could anybody explain to me how to rotate the models on its own axis?
Use MatrixTransform::setMatrix() to change the orientation of the child node.
MatrixTransform* transform = new osg::MatrixTransform;
const double angle = 0.8;
const Vec3d axis(0, 0, 1);
transform->setMatrix(Matrix::rotate(angle, axis));
Below is a complete program that loads and displays a 3D object with and without the transformation added.
#include <string>
#include <osg/Object>
#include <osg/Node>
#include <osg/Transform>
#include <osg/Matrix>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
using namespace osg;
int main(int argc, char** argv)
{
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << "<file>\n";
exit(1);
}
const std::string file = argv[1];
// Load a node.
Node* node = osgDB::readNodeFile(file);
if (!node) {
std::cerr << "Can't load node from file '" << file << "'\n";
exit(1);
}
// Set a transform for the node.
MatrixTransform* transform = new osg::MatrixTransform;
const double angle = 0.8;
const Vec3d axis(0, 0, 1);
transform->setMatrix(Matrix::rotate(angle, axis));
transform->setName(file);
transform->addChild(node);
// Add the node with and without the transform.
Group* scene = new Group();
scene->addChild(transform);
scene->addChild(node);
// Start a scene graph viewer.
osgViewer::Viewer viewer;
viewer.setSceneData(scene);
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
viewer.realize();
while (!viewer.done()) viewer.frame();
}
You'll want to use a quat
http://www.openscenegraph.org/documentation/OpenSceneGraphReferenceDocs/a00568.html
It has a number of functions you can use for rotation.