I have a mesh (with color) loaded and want to write it to a .ply file and store the rgb information as well. I currently have the code below, which uses the vtkPLYWriter class, but this just saves the vertices and not the RGB info. Is there a built in way to do this?
Code
vtkSmartPointer<vtkTransformPolyDataFilter> rotate_and_save_mesh(vtkSmartPointer<vtkPLYReader> mesh_reader, double rotation_angle, double x, double y, double z,
std::string& out_name, bool should_write = true){
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->RotateWXYZ(rotation_angle, x, y, z);
vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
transformFilter->SetTransform(transform);
transformFilter->SetInputConnection(mesh_reader->GetOutputPort());
transformFilter->Update();
if(should_write){
vtkSmartPointer<vtkPLYWriter> writer = vtkSmartPointer<vtkPLYWriter>::New();
writer->SetInputConnection(transformFilter->GetOutputPort());
writer->SetFileName(out_name.c_str());
writer->Write();
}
return transformFilter;
}
This is very awkward. Unlike vtkPolyDataXMLWriter and most other VTK writers, you must specify
plyWriter->SetArrayName("Colors");
where your color array was created/named like this:
vtkSmartPointer<vtkUnsignedCharArray> colors =
vtkSmartPointer<vtkUnsignedCharArray>::New();
colors->SetNumberOfComponents(3);
colors->SetName("Colors");
Related
My question is pretty simple, suppose I have an image and I want to load it into my program so that I can get the color of each pixel. How could I do that? In a nutshell I want a method that gives me the color of a pixel.
struct color{
double r, g, b;
color(){}
color(float red, float green, float blue){r = red; g = green; b = blue;}
};
color GetPixel(string imageName, int x, int y){
//if(x < 0 || x >= width of image) return color(0,0,0);
//if(y < 0 || y >= height of image) return color(0,0,0);
//do stuff
return colorForPixelXY;
}
Preferably I would like to do it natively, without using any external libs.
The STB image library is a single file, header only "library" that you can include and use in your project scott free. It's sort of an industry standard for cases like yours. Highly recommended.
https://github.com/nothings/stb
That said, reading a PNM/PPM file is very easy thing to do in C++ as it is basically a text file. Any image package can take your BMP,JPG and save it to PNM that you can even include in your executable binary.
read PPM file and store it in an array; coded with C
My C++/SDL2 program uses a Sprites class with a std::map of pointers to SDL_Textures and member functions for loading and rendering images, however when the program ran none of the loaded images showed up in the window.
I've found that the Sprites instance is given a correct pointer to the renderer and IMG_LoadTexture did not return 0. The renderer is also working properly since primitives like SDL_RenderDrawLine are drawn just fine.
Interestingly when I wanted to check if SDL_QueryTexture gave correct dimensions by printing the source rectangle's width and height, the program rendered the images properly. The printed dimensions were also correct, and trying to print the x and y fixed it too.
Why does this happen?
Here's the two important member functions in the Sprites class.
void Sprites::load(std::string id, std::string filename, int length) {
SDL_Texture* tex = IMG_LoadTexture(renderer, filename.c_str());
if (tex == 0) {
printf("Texture %s could not be loaded\n", filename.c_str());
}
sprmap[id] = tex;
lengthmap[id] = length;
printf("%s should be loaded now\n", id.c_str());
}
void Sprites::render(std::string id, float x, float y, int frame) {
SDL_Rect src;
SDL_Rect dest;
SDL_QueryTexture(sprmap[id], NULL, NULL, &src.w, &src.h);
src.w /= lengthmap[id];
printf("src x: %s, src y %s\n", std::to_string(src.x).c_str(), std::to_string(src.y).c_str());
//Images do not render when above line is omitted
src.x = frame*src.w;
dest.x = x;
dest.y = y;
dest.w = src.w;
dest.h = src.h;
SDL_RenderCopy(renderer, sprmap[id], &src, &dest);
}
Your SDL_Rect is not correctly initialised. Printing "fixes" it, but only by chance.
Your SDL_QueryTexture allows you to initialise w and h, but x and y have completely random values. As to why EXACTLY printing the values fixes things is beyond me, but I suspect that the random values don't go well with SDL_RenderCopy (especially negative values).
If you give proper values to x and y, your problem should go away.
If you want to read more about how variables are initialised this SO post should be a good place to start.
An alternative could be zero initialisation to make sure your structs always have a default value of 0.
The simplest way should be like this : SDL_Rect src{};
I used to have a project that used a grey scale image to set the height of vertices in a simple flat mesh, which resulted in nice looking height mapped terrain. However, I have since converted my project to C++ and can no longer use the help of BufferedImage and such to use the old grey scale approach for creating height-mapped terrain from a flat mesh.
Because of this my C++ project now uses a .obj file for the terrain, but I am finding it very difficult to update the player/camera height as the user walks around the terrain, instead I just float through everything as the player height never changes or only does so very frequently (so I know the height is at least being updated, just not correctly).
Bellow is a small sample of code that does the actual updating of the player height based on the terrain.obj file, it does this by storing all the vertices of the .obj file and comparing each of their x and z components with the x and z components of the player and if there is a match then set the y value of the player to the current vertexes y position:
Vector3f *playerPos = freeMoveObjects[0]->GetParent()->GetTransform()->GetPos();
float playerXPos = playerPos->GetX();
float playerZPos = playerPos->GetZ();
int playerXPosInt = (int)playerXPos;
int playerZPosInt = (int)playerZPos;
for (Vector3f currentVector : meshObjects[0]->getMeshVertices()) {
int meshHeightXInt = (int)currentVector.GetX();
int meshHeightZInt = (int)currentVector.GetZ();
if (meshHeightXInt == playerXPosInt & meshHeightZInt == playerZPosInt){//currentVector.GetX() <= playerXPos & currentVector.GetZ() <= playerZPos) {
freeMoveObjects[0]->GetParent()->GetTransform()->GetPos()->SetY(currentVector.GetY());
}
}
What you're doing is very inefficient right now; you shouldn't have to loop through all vertices if you already have a heightmap which you can use for updating the player's position.
Why don't you store the heightmap in a pseudo-2d-array, like this:
class HeightMap {
private:
int width;
int height;
std::unique_ptr<int[]> data = std::make_unique<int[]>(width * height);
public:
HeightMap(int width, int height) : width{width}, height{height} {}
// you can default copy, move constructors and assignments
int heightAt(int x, int y) {
return heightmap[x + y * width];
}
}
Using heightAt you now have efficient random access to the data in the map. Thanks to unique_ptr you don't need to manage any memory manually and other constructors can be defaulted.
Note that you need to handle errors like x or y being out of range manually.
I am using https://github.com/syoyo/tinygltf to load glTF model. glTF models have a buffer that includes the position datas (vertex coordinates). I want to print these coordinates to the screen.
for (int i = 0; i < model.meshes.size(); ++i)
{
Mesh &gltfmesh = model.meshes[i];
Primitive &prim = gltfmesh.primitives[i];
Accessor& acess = model.accessors[prim.attributes["POSITION"]];
BufferView& bview = model.bufferViews[acess.bufferView];
Buffer& bfer = model.buffers[bview.buffer];
// cout << bfer.data ... I need to cout the vertex arrays somehow
}
As you can see the coordinates are in the Buffer& bfer now I want to extract them into Vec3F structures (one Vec3F struct has 3 variables: float x, y, z), or anything that I can print it.
Also I need to mention that the buffer not just includes vertex coordinates, there is an offset to the them that are given in the BufferView& bview (BufferViews), so I will need to use bview.byteOffset somehow to determine the location of the vertices in the buffer.
Thank you so much if you can help me out !
I am having some problems finding a solution on how to retrieve a specific color of a pixel on a SDL_Texture...
To be bit more specific: I am trying to calculate the average amount of color used in a given texture. Later on I want to devide for example the number of red pixels by the total amount of pixels. For this task I will need a method, which will get me each pixel color...
I tried to search for some functions, but unfortunately I wasnt able to figure it out..
I saw methods like SDL_RenderReadPixels and SDL_GetPixelFormatName, but none of those helped me out...
Do you have a solution for me?
To access an SDL_Texture's pixels, you must create a blank texture using SDL_CreateTexture() and pass in SDL_TEXTUREACCESS_STREAMING for the access parameter, then copy the pixels of a surface into it. Once that's done, you can use the SDL_LockTexture() function to retrieve a pointer to the pixel data which can then be accessed and modified. To save your changes, you'd call SDL_UnlockTexture(). Try something like this:
SDL_Texture *t;
int main()
{
// Init SDL
SDL_Surface * img = IMG_Load("path/to/file");
SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, img->w, img->h);
void * pixels;
SDL_LockTexture(t, &img->clip_rect, &pixels, img->pitch);
memcpy(pixels, img->pixels, img->w * img->h);
Uint32 * upixels = (Uint32 *) pixels;
// get or modify pixels
SDL_UnlockTexture(t);
return 0;
}
Uint32 get_pixel_at(Uint32 * pixels, int x, int y, int w)
{
return pixels[y * w + x];
}
You can get the colors from a pixel like this:
Uint32 pixel = get_pixel_at(pixels, x, y, img->w);
Uint8 * colors = (Uint8 *) pixel;
// colors[0] is red, 1 is green, 2 is blue, 3 is alpha (assuming you've set the blend mode on the texture to SDL_BLENDMODE_BLEND
If you want more information, then check out these SDL 2.0 tutorials: http://lazyfoo.net/tutorials/SDL/index.php. Tutorial 40 deals specifically with this problem.
Let me know if you have any questions or something is unclear.
Good luck!