I have some 3d models and I want to display each face of the model seperately. For each face, I have a list of the vertices (as pcl::PointCloud), the Translation vector (as Eigen::Vector3f) and the Rotation Matrix (as Eigen::Quaternionf). The faces can have different shapes. It will be rectangular, round (n-verts polygon) and trapezial.
For the rectangular faces, I used vtkCubeSource so far and it works good. For the round faces, I could maybe use vtkCylinderSource. For trapezial faces, I didn't found a solution so far.
The best would be a class like vtkPolyLineSource, where I just need a list of vertices for any polygons. But as far as I see, vtkPolyLineSource would just draw the the line and don't fill the polynom with a color.
Is there a way to draw a polygon into 3d-space with vtk? Since it is possible to directly draw a 3d-model from a file, I think there should be a method for drawing a model (or just one face), but I couldn't find it so far. That's my first contact with VTK, so I think I just overlooked the right classes.
One reason why I don't just load a model-file is, that I need the faces in different colors and opacitys (defiend at runtime).
Use vtkPolygon
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
// ... fill in your points with n points
// Create the polygon
vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New();
polygon->GetPointIds()->SetNumberOfIds(n);
for (int j = 0; j < n; j++)
{
polygon->GetPointIds()->SetId(j, j);
}
// Add the polygon to a list of polygons
vtkSmartPointer<vtkCellArray> polygons = vtkSmartPointer<vtkCellArray>::New();
polygons->InsertNextCell(polygon);
// Create a PolyData
vtkPolyData* polygonPolyData = vtkPolyData::New();
polygonPolyData->SetPoints(points);
polygonPolyData->SetPolys(polygons);
// create mapper and actor using this polydata - the usual stuff
Related
I created a new class PieSource (based on vtkCylinderSource) which creates a number of triangles together with the colors they should have:
int vtkPieSource::RequestData(vtkInformation *info,
vtkInformationVector **infoV,
vtkInformationVector *outputVector) {
vtkInformation *outInfo = outputVector->GetInformationObject(0);
vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkPoints *newPoints;
vtkFloatArray *newNormals;
vtkUnsignedCharArray *newCols = vtkUnsignedCharArray::New();
newCols->SetNumberOfComponents(3);
newCols->SetName("Colors");
newPoints = vtkPoints::New();
newPoints->SetDataType(VTK_FLOAT);
newPoints->Allocate(iNumVerts);
newPolys = vtkCellArray::New();
newPolys->Allocate(iNumTriangles);
(-- here we create the triangles and determine their colors --)
for (uint i = 0; i < iNumVerts; i+=3) {
vtkTriangle *triangle1 =vtkTriangle::New();
triangle1->GetPointIds()->SetId(0, i);
triangle1->GetPointIds()->SetId(1, i+1);
triangle1->GetPointIds()->SetId(2, i+2);
newPolys->InsertNextCell(triangle1);
}
output->SetPoints(newPoints);
newPoints->Delete();
output->GetPointData()->SetScalars(newCols);
newCols->Delete();
output->SetPolys(newPolys);
newPolys->Delete();
return 0;
}
In my application i create a vtkGlyph3DMapper which uses the output of PieSource
vtkNew<vtkPieSource> pieSource;
pieSource->SetData(5, testData);
vtkNew<vtkGlyph3DMapper> glyph3Dmapper;
glyph3Dmapper->SetSourceConnection(pieSource->GetOutputPort());
glyph3Dmapper->SetInputData(polydata);
// glyph3Dmapper->SelectColorArray("Colors");
(polydata contains 2 triangles with colors -- without this InputData nothing is drawn)
When i run this, the glyph geometries are drawn in the correct places with correct orientations,
but they don't have the colors i have assigned them (all triangles are grey). If i uncomment the line glyph3Dmapper->SelectColorArray("Colors"); the entire glyph is drawn with the same color (the one specified in the array named "Colors").
Is it possible to have a glyph whose triangles are individually colored?
If yes how must i do this?
First, since your newCols array is empty, I don't know which color you are expecting.
Then if you want a color associated to the triangle, you should add your data array in CellData rather than in PointData. The array should have one tuple per cell (triangle here)
A small style remark: instead of vtkXXX * myObj = vtkXXX::New();, it is recommended to use a local-scoped object instanciated with vtkNew<vtkXXX> myObject;, so you do not need to Delete it.
I have many Esri Grid files (https://en.wikipedia.org/wiki/Esri_grid#ASCII) and I would like to render them in 3D without losing precision, I am using OpenSceneGraph.
The problem is this grids are around 1000x1000 (or more) points, so when I extract the vertices, then compute the triangles to create the geometry, I end up having millions of them and the interaction with the scene is impossible (frame rate drops to 0).
I've tried several approches:
Triangle list
Basically, as I read the file, I fill an array with 3 vertices per triangle (this leads to duplication);
osg::ref_ptr<osg::Geode> l_pGeodeSurface = new osg::Geode;
osg::ref_ptr<osg::Geometry> l_pGeometrySurface = new osg::Geometry;
osg::ref_ptr<osg::Vec3Array> l_pvTrianglePoints = osg::Vec3Array;
osg::ref_ptr<osg::Vec3Array> l_pvOriginalPoints = osg::Vec3Array;
... // Read the file and fill l_pvOriginalPoints
for(*triangle inside the file*)
{
... // Compute correct triangle indices (l_iP1, l_iP2, l_iP3)
// Push triangle vertices inside the array
l_pvTrianglePoints->push_back(l_pvOriginalPoints->at(l_iP1));
l_pvTrianglePoints->push_back(l_pvOriginalPoints->at(l_iP2));
l_pvTrianglePoints->push_back(l_pvOriginalPoints->at(l_iP3));
}
l_pGeometrySurface->setVertexArray(l_pvTrianglePoints);
l_pGeometrySurface->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, 3, l_pvTrianglePoints->size()));
Indexed triangle list
Same as before, but the array contains the every vertices just once and I create a second array of indices (basically i tell osg how to build triangles, no duplication)
osg::ref_ptr<osg::Geode> l_pGeodeSurface = new osg::Geode;
osg::ref_ptr<osg::Geometry> l_pGeometrySurface = new osg::Geometry;
osg::ref_ptr<osg::DrawElementsUInt> l_pIndices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, *number of indices*);
osg::ref_ptr<osg::Vec3Array> l_pvOriginalPoints = osg::Vec3Array;
... // Read the file and fill l_pvOriginalPoints
for(i = 0; i < *number of indices*; i++)
{
... // Compute correct triangle indices (l_iP1, l_iP2, l_iP3)
// Push vertices indices inside the array
l_pIndices->at(i) = l_iP1;
l_pIndices->at(i+1) = l_iP2;
l_pIndices->at(i+2) = l_iP3;
}
l_pGeometrySurface->setVertexArray(l_pvOriginalPoints );
l_pGeometrySurface->addPrimitiveSet(l_pIndices.get());
Instancing
this was a bit of an experiment, since I've never used shaders, I tought I could instance a single triangle, then manipulate its coordinates in a vertex shader for every triangle in my scene, using transformation matrices (passing the matrices as a uniform array, one for triangle). I ended up with too many uniforms just with a grid 20x20.
I used these links as a reference:
https://learnopengl.com/Advanced-OpenGL/Instancing,
https://books.google.it/books?id=x_RkEBIJeFQC&pg=PT265&lpg=PT265&dq=osg+instanced+geometry&source=bl&ots=M8ii8zn8w7&sig=ACfU3U0_92Z5EGCyOgbfGweny4KIUfqU8w&hl=en&sa=X&ved=2ahUKEwj-7JD0nq7qAhUXxMQBHcLaAiUQ6AEwAnoECAkQAQ#v=onepage&q=osg%20instanced%20geometry&f=false
None of the above solved my issue, what else can I try? Am I missing something in terms of rendering techinques? I thought it was fairly simple task, but I'm kind of stuck.
I feel like you should consider taking a step back. If you're visualizing GIS-based terrain data, osgEarth is really designed for doing this and has fairly efficient LOD tools for large terrains. Do you need the data always represented at maximum full LOD or are you looking for dynamic LOD to improve frame rate?
Depending on your goals and requirements you might want to look at some more advanced terrain rendering techniques, like rightfield tracing, etc. If the terrain is always static, you can precompute quadtrees and Signed Distance Functions and trace against the heightfield.
I'm looking for advice on an algorithm I've been struggling with. I have something represented in code (shown later) that looks like the following diagram (initial state on left, desired output on right):
I have this represented in C++ as the following:
#include <vector>
using namespace std;
class Shape {
public:
Shape(vector<vector<float> > c) {
coordinates = c;
}
vector<vector<float> > coordinates; // in format {{x1,y1},{x2,y2}}
};
class Shape_Group {
public:
Shape_Group(vector<Shape> s) {
shapes = s;
}
vector<Shape> shapes;
Shape generate_border();
};
Shape Shape_Group::generate_border() {
/*
define algorithm here
*/
}
int main() {
// define rectangle shapes
Shape s1({{0,0}, {0,1}, {1,1}, {1,0}});
Shape s2({{0,0}, {0,1}, {1,-1}, {-1,0}});
Shape_Group group({s1, s2});
Shape border = group.generate_border(); // should return a shape with the exterior border
// border should be filed with {{1,0}, {1,1}, {1,-1}, {-1,0}};
}
My initial idea for generating this exterior shape was to do something like the following:
loop through each line segment for each shape in the Shape_Group object
loop through every other segment in the Shape_Group object
if both line segments are colinear and overlap, remove them
whatever's left over should be the exterior border
However, with large inputs this is a very slow algorithm. What else can I do?
Geometry O(n^2) approach:
make list of all edges
remove all interrior edges
use hit test to detect interior/exterior edges.
reconnect all remaining edges into new polygon
simply connect edges sharing the same end point.
If you want something simpler then O(n) graphics approach:
render your shape
fill background with specific color
remove all edges not neighboring background color
this is somewhat related:
Render filled complex polygons with large number of vertices with OpenGL
it also combines vector graphics and pixel access ...
There are also different approaches to this problem for example like this one:
Finding holes in 2d point sets?
I have a particle simulation program I'm currently working on that generate random particle positions in a rectangular shape. This works for now but it's not the best solution, often particles overlap and there are small holes in the rectangle. How would I initialize the particles in the shape of a rectangle?
My current loop:
for(auto i=0; i<MAXPARTICLES; i++){
int particleIndex = FindUnusedParticle(); //grab the index to give a particle life
ParticlesContainer[particleIndex].life = 100.0f; //Long particle life
//generate random positions for particles in the shape of a box with random patterns
ParticlesContainer[particleIndex].pos = glm::vec3((rand()%50)/5.0,(rand()%50)/5.0,-50.0);
// Very bad way to generate a random color
ParticlesContainer[particleIndex].r = 255;
ParticlesContainer[particleIndex].g = 0;
ParticlesContainer[particleIndex].b = 0;
ParticlesContainer[particleIndex].a = 255;
ParticlesContainer[particleIndex].size = .2f;
}
It's a more complicated problem than just using uniform distribution over two dimensions separately. If your "evenliness" is the distance between two closest particles, then there are exactly two ways to achieve that: equilateral triangles and squares (well, three if you count hexagons). The only random thing there is the position of one seed and the "direction" in which that will go.
Refer to the image:
That will give you a very regular, grid-like look, though. You could try applying random, minuscule changes to particles distributed that way, and see how that would work.
I am trying to compute the visibility between two planes or patches.
I have a wireframe of quads. Each quad has a normal vector with X, Y and Z coordinates. Each quad has 4 vertices. Each vertex has X, Y and Z coordinates.
Given two quads, how can I know if there is an occluder or another object in between these two patches (quads).
Therefore, I need to create a method that returns 1 if patches has no occluders or return 0 if patches has occluder.
The method I picture would be something like this:
GLint visibility(Patch i, Patch j) {
GLboolean isVisible;
vector<Patch> allPatches; // can be used to get all patches in the scene
// Check if there is any occluder between patch i and patch j
Some computations here
if(isVisible) {
return 1;
} else {
return 0;
}
}
I've heard of z-buffer algorithms and the hemicube implementation that would get this done. I already have the form-factors computed. I just need to finish this step to get shadows.
Make sure you give some form of answer with graphs or methods because I am not that genius
I found the solution. Basically I needed to use ray tracing techniques. Throw ray from one patch to another and check if ray intercepts the planes with barycentric equation computation. Once you find the control points you need to check if the control point lies on you quad.