OpenGL Application crashes when accessing Assimp Texture Coordinate Data - c++

I am trying to access the Texture Coordinate of a Cube model made in blender.
for (int i = 0; i < mMesh->mNumVertices; i++) {
std::cout << mMesh->mTextureCoords[i][0].x << " " << mMesh->mTextureCoords[i][0].y << std::endl;
}
Why is this happening.
The application window launches but the red color background doesnt display.
And the first coords also get printed 0 1
How do i solve this.
Removing this code doesn't lead to a crash.

This should be:
for (int i = 0; i < mMesh->mNumVertices; i++)
{
std::cout << mMesh->mTextureCoords[0][i].x << " " << mMesh->mTextureCoords[0][i].y << std::endl;
}
Looks like you messed up the first and second array arguments. Also, it is good practice to check if the mesh has texture coordinates or not. Then the code becomes
if (mMesh->HasTextureCoords(0)) //HasTextureCoords is an assimp function
{
for (int i = 0; i < mMesh->mNumVertices; i++)
{
std::cout << mMesh->mTextureCoords[0][i].x << " " << mMesh- >mTextureCoords[0][i].y << std::endl;
}
}

Related

Changing one element in a two-dimensional vector changes all elements?

I'm coding a checkered board game where the board is a two-dimensional vector that holds a Square object, and the Square holds a Piece. Using a nested for-loop, I'm initializing a new Square object in each slot in the 8x8 vector - but when I add a Piece to one Square, it's adding a Piece to every single Square. I think that, somehow, each slot in the vector is only pointing to one Square, even though I'm initializing a new Square every time.
I've tried this with a two-dimensional vector of Square objects as well as with a vector of Square pointers. Currently I'm using the vector of pointers: vector<vector<Square*>> _board;
// initializing an empty board
_board = {{},{},{},{},{},{},{},{}};
// adding a new Square to each of the 8x8 slots
string colorAlternator = WHITE;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
_board[i].push_back(new Square(colorAlternator, make_tuple(i,j)));
if (colorAlternator == WHITE) {
colorAlternator = BLACK;
} else {
colorAlternator = WHITE;
}
}
}
// placing a piece
/* placePiece() is a function of Square
* (p2Pieces.at(0) is a piece being pulled from elsewhere)
*/
_board[0][1]->placePiece(*p2Pieces.at(0));
In another function called view(), it prints out a visualization of the board (excuse my inelegant implementation, it will be fixed with a for-loop shortly!):
for (int i = 7; i >= 0; i--)
{
cout << BORDER << endl;
cout << i + 1 << " " << "| "
<< board[i][0]->displayToken() << " | "
<< board[i][1]->displayToken() << " | "
<< board[i][2]->displayToken() << " | "
<< board[i][3]->displayToken() << " | "
<< board[i][4]->displayToken() << " | "
<< board[i][5]->displayToken() << " | "
<< board[i][6]->displayToken() << " | "
<< board[i][7]->displayToken() << " | " << i + 1 << endl;
}
This should be printing every Square as being blank except for the one I placed the Piece in - but it's printing each Square out as containing the Piece I just added.
Any ideas what's causing each slot in the vector to be linking to the same Square? (Or is that even what's happening?)
update: here is the implementation for placePiece(), displayToken(), and supporting method containsPiece() in class Square:
Piece* _piece;
void Square::placePiece(Piece &piece) {
_piece = &piece;
}
bool Square::containsPiece() {
return _piece != nullptr;
}
string Square::displayToken() {
string displayStr = " ";
if (containsPiece()) {
displayStr = _piece->getToken();
}
return displayStr;
}

weird glm::mat2x4 assignment behaviour

I am trying to load freetype chars, stuff them into a texture as subimages and then render them instanced.
While most of it seems to work, right now I have a problem with storing the texture coordinates into a glm::mat2x4 matrix.
As can be seen below each character has a struct with information I right now deem necessary, including a matrix called face, which should store the texture coordinates.
But when it comes to assigning the coordinates, after leaving the loop in which it takes place, suddenly all the values go crazy, without any (wanted/ intended) operation taking place from my side.
After creating the texture atlas with freetype and putting all my structs into the map, I assign the width and height of my texture aw & ah to a storage class called c_atlas.
I calculate the texture coordinates in the loop shown below, make the glm::mat2x4 a 0.0f matrix and then stuff them into it. Couting them into the console gives the values I want.
After leaving the for loop I start another one, browsing over the matrix and cout them into the console, which gives me more or less random values in the range of e^-23 to e^32.
All of this happens in namespace foo and is called in a constructor of a class in the same namespace (sth. like this:)
foo::class::constructor()
{
call_function();
}
int main()
{
foo::class c;
c.call_function();
}
I crafted a minimum working example, but unfortunatly I am not able to replicate the error.
So I have the following loop running (a part of call_function():
namespace foo
{
namespace alphabet
{
const char path_arial[] = "res/font/consola.ttf";
class character
{
public:
glm::vec2 advance;
glm::vec2 bearing;
glm::vec2 size;
glm::vec2 offset;
glm::mat2x4 face;
};
std::map<char, character> char_map;
FT_Library m_ftlib;
FT_Face m_ftface;
GLuint m_VBO, m_VAO;
}
c_atlas ascii;
}
void foo::call_function()
{
//creating all the charactur structs with freetype and store them in the char_map
std::ofstream f("atlas_data.csv", std::ios::openmode::_S_app);
f << "letter;topleft.x;topleft.y;topright.x;topright.y;bottomright.x;bottomright.y;bottomleft.x;bottomleft.y" << std::endl;
for(auto c : alphabet::char_map)
{
std::cout << "b4: " << c.second.offset.x;
c.second.offset /= glm::vec2(aw,ah);
std::cout << "\nafter: " << c.second.offset.x << std::endl;
glm::vec2 ts = c.second.size/glm::vec2(aw,ah);
//couts the right values
uint16_t n = 0;
c.second.face = glm::mat2x4(0.0f);
for(uint16_t i = 0; i < 4; ++i)
{
std::cout << c.first << " at init:\n";
std::cout << c.second.face[0][i] << "\n";
std::cout << c.second.face[1][i] << std::endl;
}
//couts the right values
c.second.face[0][n++] = c.second.offset.x;
c.second.face[0][n++] = c.second.offset.y;
c.second.face[0][n++] = c.second.offset.x+ts.x;
c.second.face[0][n++] = c.second.offset.y;
n = 0;
c.second.face[1][n++]= c.second.offset.x+ts.x;
c.second.face[1][n++] = c.second.offset.y+ts.y;
c.second.face[1][n++] = c.second.offset.x;
c.second.face[1][n++]= c.second.offset.y+ts.y;
for(uint16_t i = 0; i < 4; ++i)
{
std::cout << c.first << " assigned:\n";
std::cout << c.second.face[0][i] << "\n";
std::cout << c.second.face[1][i] << std::endl;
}
//still couts the right values
f << (char)c.first << ";" << c.second.face[0].x << ";" << c.second.face[0].y << ";" << c.second.face[0].z << ";" << c.second.face[0].w << ";" << c.second.face[1].x << ";" << c.second.face[1].y << ";" << c.second.face[1].z << ";" << c.second.face[1].w << std::endl;
//the file also have the right values
}
f.close();
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
//yet here all the values totally off track, i.e. e^32 or e^-23 (while they should all be between 0.01f - 1.0f)
for(auto i : alphabet::char_map)
{
std::cout << "\ntopleft:\n";
std::cout << "X: " << i.second.face[0].x << " | " << "Y: " << i.second.face[0].x;
std::cout << "\ntopright:\n";
std::cout << "X: " << i.second.face[0].z << " | " << "Y: " << i.second.face[0].w;
std::cout << "\nbotleft:\n";
std::cout << "X: " << i.second.face[1].x << " | " << "Y: " << i.second.face[1].x;
std::cout << "\nbotright:\n";
std::cout << "X: " << i.second.face[1].z << " | " << "Y: " << i.second.face[1].w;
}
}
my mwe:
#include <iostream>
#include <string>
#include "glm/glm.hpp"
#include "GL/gl.h"
#include <map>
struct bin
{
glm::mat2x4 mat;
};
int main( int argc, char *argv[] )
{
std::map<char, bin> bucket;
uint16_t r = 0;
for(uint16_t n = 0; n < 7; ++n)
{
glm::vec4 v = glm::vec4(0.12128f, 0.12412f, 0.15532f, 0.23453f);
bin b;
r = 0;
b.mat[0][r++] = v.x;
b.mat[0][r++] = v.y;
b.mat[0][r++] = v.z;
b.mat[0][r++] = v.w;
r = 0;
b.mat[1][r++] = v.x;
b.mat[1][r++] = v.y;
b.mat[1][r++] = v.z;
b.mat[1][r++] = v.w;
bucket[n] = b;
}
for(auto it : bucket)
{
r = 0;
std::cout << "0:\t" << it.second.mat[0][0] << "\t" << it.second.mat[0][1] << "\t" << it.second.mat[0][2] << "\t" << it.second.mat[0][3] << "\n";
r = 0;
std::cout << "1:\t" << it.second.mat[1][0] << "\t" << it.second.mat[1][1] << "\t" << it.second.mat[1][2] << "\t" << it.second.mat[1][3] << std::endl;
}
return 0;
}
Right now I am totally lost, especially as my mwe works fine.
I am clueless what goes wrong after leaving the for-loop, so thanks for any thought on that!
Indeed, I could just rewrite that section and hope it would work - as my mwe does. But I would like to find out/ get help on finding out what exactly happens between the "assign" for loop and the "retrieve" for loop. Any ideas on that?
I made it work for me now:
Appartenly assigning the values this way:
for(auto c : alphabet::char_map)
{
c.second.face[0][n++] = c.second.offset.x;
//and so on
}
Did not work properly (for whatever reason..)
Changing this into a for(uint16_t i = 32; i < 128; ++i) worked for me. Also it was just the assigning loop, the auto-iterating ofer the map elsewhere works just fine.

saving CGAL alpha shape surface mesh

I have never used CGAL and have got almost no C/C++ experience. But following
Google I have however managed to compile the example "Alpha_shapes_3"
(\CGAL-4.1-beta1\examples\Alpha_shapes_3) on a Windows 7 64bit machine using
visual studio 2010.
Now if we check the source code for the program "ex_alpha_shapes_3" we
notice that a data file called "bunny_1000" is red where the 3d point
cluster resides.
Now my question is how can I change the source code so that after the alpha
shape is computed for the given points, surface mesh of the alpha shape is
saved/wrote in an external file. It can be simply the list of polygons and
their respective 3D vertices. I guess these polygons will be defining the
surface mesh of the alpha shape. If I can do that I can see the output of
the alpha shape generation program in an external tool I am familiar with.
I know this is very straightforward but I could not figure this out with my
limited knowledge of CGAL.
I know you gueys have the code but I am pasting it again for completion.
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <CGAL/Alpha_shape_3.h>
#include <fstream>
#include <list>
#include <cassert>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Gt;
typedef CGAL::Alpha_shape_vertex_base_3<Gt> Vb;
typedef CGAL::Alpha_shape_cell_base_3<Gt> Fb;
typedef CGAL::Triangulation_data_structure_3<Vb,Fb> Tds;
typedef CGAL::Delaunay_triangulation_3<Gt,Tds> Triangulation_3;
typedef CGAL::Alpha_shape_3<Triangulation_3> Alpha_shape_3;
typedef Gt::Point_3 Point;
typedef Alpha_shape_3::Alpha_iterator Alpha_iterator;
int main()
{
std::list<Point> lp;
//read input
std::ifstream is("./data/bunny_1000");
int n;
is >> n;
std::cout << "Reading " << n << " points " << std::endl;
Point p;
for( ; n>0 ; n--) {
is >> p;
lp.push_back(p);
}
// compute alpha shape
Alpha_shape_3 as(lp.begin(),lp.end());
std::cout << "Alpha shape computed in REGULARIZED mode by default"
<< std::endl;
// find optimal alpha value
Alpha_iterator opt = as.find_optimal_alpha(1);
std::cout << "Optimal alpha value to get one connected component is "
<< *opt << std::endl;
as.set_alpha(*opt);
assert(as.number_of_solid_components() == 1);
return 0;
}
After searching a lot in the internet I found that probably we need to use something like
std::list<Facet> facets;
alpha_shape.get_alpha_shape_facets
(
std::back_inserter(facets),Alpha_shape::REGULAR
);
But I am still completely clueless how to use this in the above code!
As documented here, a facet is a pair (Cell_handle c,int i) defined as the facet in c opposite to the vertex of index i.
On this page, you have the description of how the vertex indices of a cell are.
In the following code sample, I added a small output that prints an OFF file on cout by duplicating the vertices. To do something clean, you can either use a std::map<Alpha_shape_3::Vertex_handle,int> to associate a unique index per vertex or add an info to the vertices like in those examples.
/// collect all regular facets
std::vector<Alpha_shape_3::Facet> facets;
as.get_alpha_shape_facets(std::back_inserter(facets), Alpha_shape_3::REGULAR);
std::stringstream pts;
std::stringstream ind;
std::size_t nbf=facets.size();
for (std::size_t i=0;i<nbf;++i)
{
//To have a consistent orientation of the facet, always consider an exterior cell
if ( as.classify( facets[i].first )!=Alpha_shape_3::EXTERIOR )
facets[i]=as.mirror_facet( facets[i] );
CGAL_assertion( as.classify( facets[i].first )==Alpha_shape_3::EXTERIOR );
int indices[3]={
(facets[i].second+1)%4,
(facets[i].second+2)%4,
(facets[i].second+3)%4,
};
/// according to the encoding of vertex indices, this is needed to get
/// a consistent orienation
if ( facets[i].second%2==0 ) std::swap(indices[0], indices[1]);
pts <<
facets[i].first->vertex(indices[0])->point() << "\n" <<
facets[i].first->vertex(indices[1])->point() << "\n" <<
facets[i].first->vertex(indices[2])->point() << "\n";
ind << "3 " << 3*i << " " << 3*i+1 << " " << 3*i+2 << "\n";
}
std::cout << "OFF "<< 3*nbf << " " << nbf << " 0\n";
std::cout << pts.str();
std::cout << ind.str();
Here is my code, which outputs vtk file for visualization in Paraview. Comparing with slorior's solutions, no duplicated points are saved in the file. But my code is just for the visualization, if you need to figure out the exterior or interior simplexes, you should modify the code to get these results.
void writevtk(Alpha_shape_3 &as, const std::string &asfile) {
// http://cgal-discuss.949826.n4.nabble.com/Help-with-filtration-and-filtration-with-alpha-values-td4659524.html#a4659549
std::cout << "Information of the Alpha_Complex:\n";
std::vector<Alpha_shape_3::Cell_handle> cells;
std::vector<Alpha_shape_3::Facet> facets;
std::vector<Alpha_shape_3::Edge> edges;
// tetrahedron = cell, they should be the interior, it is inside the 3D space
as.get_alpha_shape_cells(std::back_inserter(cells), Alpha_shape_3::INTERIOR);
// triangles
// for the visualiization, don't need regular because tetrahedron will show it
//as.get_alpha_shape_facets(std::back_inserter(facets), Alpha_shape_3::REGULAR);
as.get_alpha_shape_facets(std::back_inserter(facets), Alpha_shape_3::SINGULAR);
// edges
as.get_alpha_shape_edges(std::back_inserter(edges), Alpha_shape_3::SINGULAR);
std::cout << "The alpha-complex has : " << std::endl;
std::cout << cells.size() << " cells as tetrahedrons" << std::endl;
std::cout << facets.size() << " triangles" << std::endl;
std::cout << edges.size() << " edges" << std::endl;
size_t tetra_num, tri_num, edge_num;
tetra_num = cells.size();
tri_num = facets.size();
edge_num = edges.size();
// vertices: points <-> id
std::map<Point, size_t> points;
size_t index = 0;
// finite_.. is from DT class
for (auto v_it = as.finite_vertices_begin(); v_it != as.finite_vertices_end(); v_it++) {
points[v_it->point()] = index;
index++;
}
// write
std::ofstream of(asfile);
of << "# vtk DataFile Version 2.0\n\nASCII\nDATASET UNSTRUCTURED_GRID\n\n";
of << "POINTS " << index << " float\n";
for (auto v_it = as.finite_vertices_begin(); v_it != as.finite_vertices_end(); v_it++) {
of << v_it->point() << std::endl;
}
of << std::endl;
of << "CELLS " << tetra_num + tri_num + edge_num << " " << 5 * tetra_num + 4 * tri_num + 3 * edge_num << std::endl;
for (auto cell:cells) {
size_t v0 = points.find(cell->vertex(0)->point())->second;
size_t v1 = points.find(cell->vertex(1)->point())->second;
size_t v2 = points.find(cell->vertex(2)->point())->second;
size_t v3 = points.find(cell->vertex(3)->point())->second;
of << "4 " << v0 << " " << v1 << " " << v2 << " " << v3 << std::endl;
}
// https://doc.cgal.org/latest/TDS_3/classTriangulationDataStructure__3.html#ad6a20b45e66dfb690bfcdb8438e9fcae
for (auto tri_it = facets.begin(); tri_it != facets.end(); ++tri_it) {
of << "3 ";
auto tmp_tetra = tri_it->first;
for (int i = 0; i < 4; i++) {
if (i != tri_it->second) {
of << points.find(tmp_tetra->vertex(i)->point())->second << " ";
}
}
of << std::endl;
}
// https://doc.cgal.org/latest/TDS_3/classTriangulationDataStructure__3.html#af31db7673a6d7d28c0bb90a3115ac695
for (auto e : edges) {
of << "2 ";
auto tmp_tetra = e.get<0>();
int p1, p2;
p1 = e.get<1>();
p2 = e.get<2>();
of << points.find(tmp_tetra->vertex(p1)->point())->second << " "
<< points.find(tmp_tetra->vertex(p2)->point())->second << std::endl;
}
of << std::endl;
of << "CELL_TYPES " << tetra_num + tri_num + edge_num << std::endl;
for (int i = 0; i < tetra_num; i++) {
of << "10 ";
}
for (int i = 0; i < tri_num; i++) {
of << "5 ";
}
for (int i = 0; i < edge_num; i++) {
of << "3 ";
}
of << std::endl;
of.close();
}

VTKPNGWriter printing out black images?

I am doing some image processing using ITK and then using VTK to print the results in a .png format however, the output image is always black.
Currently, I am converting itk::Image to vtk::vtkImageData using the itk::ImagetoVTKImageFilter(typedeffed to ITKtoVTKFilterType in my code).
ITKtoVTKFilterType::Pointer itk2vtkGray = ITKtoVTKFilterType::New();
itk2vtkGray->SetInput(grayBinary); //grayBinary is of type itk::Image<unsigned short, 2>
itk2vtkGray->Update();
vtkSmartPointer<vtkImageData> grayVTK = vtkSmartPointer<vtkImageData>::New();
grayVTK->SetExtent(extent);
grayVTK->SetSpacing(m_spacing);
grayVTK->SetScalarTypeToUnsignedShort();
grayVTK->SetNumberOfScalarComponents(1);
grayVTK->AllocateScalars();
grayVTK->DeepCopy(static_cast<vtkImageData*>(itk2vtkGray->GetOutput()));
//grayVTK = itk2vtkGray->GetOutput();
I have even confirmed that my VTK ImageData contains values of either 255 or 0 using the following code.
int *dims = grayVTK->GetDimensions();
std::cout << "Dims: " << " x: " << dims[0] << " y: " << dims[1] << " z: " << dims[2] << std::endl;
std::cout << "Number of points: " << grayVTK->GetNumberOfPoints() << std::endl;
std::cout << "Number of cells: " << grayVTK->GetNumberOfCells() << std::endl;
for (int y = 0; y < dims[1]; y++)
{
for (int x = 0; x < dims[0]; x++)
{
unsigned short *pixel = static_cast<unsigned short*>(grayVTK->GetScalarPointer(x,y,0));
std::cout << "PIXEL LOC/VAL "<< y*dims[0] + x << " " << pixel[0] <<std::endl;
}
std::cout << std::endl;
}
I then go on to do an ImageCast to ensure the type of the data is unsignedShort.
vtkSmartPointer<vtkImageCast> cast2 = vtkSmartPointer<vtkImageCast>::New();
cast2->SetInput(grayVTK);
cast2->SetOutputScalarTypeToUnsignedShort();
cast2->ClampOverflowOn();
cast2->Update();
Then finally I use vtkPNGwriter to output the .png files. Notice that I have tried to output both the actual vtkImageData as well as output from the ImageCastFilter.
vtkSmartPointer<vtkPNGWriter> writer =
vtkSmartPointer<vtkPNGWriter>::New();
writer->SetFileName(filename.toStdString().c_str());
writer->SetInputConnection(cast2->GetOutputPort());
//writer->SetInput(grayVTK); I have tried to method as well but to no success
writer->Write();
However, the .png output is always black. Does anyone know what I am doing wrong.
For future reference it seems that many PNG readers do not display 16 bit data. Hence the casting I was doing to unsigned short at the end should have rather been to char.
vtkSmartPointer<vtkImageCast> cast2 = vtkSmartPointer<vtkImageCast>::New();
cast2->SetInput(grayVTK);
cast2->SetOutputScalarTypeToChar();
cast2->ClampOverflowOn();
cast2->Update();

How to read height map values to generate a terrain?

I am trying to make a terrain using a height map image in OpenGL. As a experiment i use 4x4 pixel image. this is a zoomed screen shot. so you can see the pixels.
This is a part of my code.
ILubyte * image = ilGetData();
int bpp = ilGetInteger(IL_IMAGE_BPP);
std::cout << "BPP = " << bpp << std::endl;
for (int z=0; z < terrainHeight; ++z)
{
for (int x=0; x < terrainWidth; ++x)
{
pVertices[z*terrainWidth+x] = NxVec3(NxF32(x),
NxF32(image[z*terrainWidth+x]*bpp), NxF32(z));
}
}
for (int i=0; i < vertexCount; ++i)
{
std::cout << "x = " << pVertices[i].x << "\t y = "
<< pVertices[i].y << "\t z = " << pVertices[i].z << std::endl;
}
Then, i'm getting the following result.
I'm expecting the zero values(for y-coordinate) for (0,0), (1,1), (2,2) and (3,3). but the result is different. why i'm not getting the expected results ?
I think it should be image[(z*terrainWidth+x)*bpp] instead of image[z*terrainWidth+x]*bpp.