http://tinypic.com/r/fwubzc/5
That shows what a flip should be and what a mirror should be.
Code for both types of mirrors:
void mirrorLeftRight()
{
for (int x = 0; x < width/2; x++) {
for (int y = 0; y < height; y++) {
int temp = pixelData[x][y];
pixelData[x][y]=pixelData[width-x][y]
pixelData[width-x][y]=temp;
}
}
}
void mirrorUpDown()
{
for (int x = 0; x < width; x++) {
for (int y = 0; y < height/2; y++) {
int temp = pixelData[x][y];
pixelData[x][y]=pixelData[x][height-y]
pixelData[x][height-y]=temp;
}
}
}
Does this seem right for mirrors?
And for flip, just a matter of using width and height w/o dividing by 2?
You need to use width-1-x instead of width-x, and height-1-y instead of height-y. Otherwise for x==0 you'll try to index [width], which is outside the array.
It shouldn't work since you are swapping pixels while you just have to override the right part of the image with the left part. Same thing applies to the mirrorUpDown.
If you swap them you obtain a flip, if you overwrite them you obtain a mirror.
mirrorLeftRight: take pixels from left half and use them to overwrite right part
mirrorUpDown: take pixels from upper part and use them to overwrite lower one
flip: in this case you don't overwrite but you swap pixels (source half it's not influent in this case)
The code above seems more like the correct way to Flip, not mirror.
Mirror I would guess that you not switch the pixels, but rather copy from one side to the other.
With mirror I would guess that you need to change
int temp = pixelData[x][y];
pixelData[x][y]=pixelData[width-x][y]
pixelData[width-x][y]=temp;
to something like this only
pixelData[x][y]=pixelData[width-x][y]
Related
I'm learning OpenGL and I have tried to make a voxel game like Minecraft. In the beginning, everything was good. I created a CubeRenderer class to render a cube with its position. The below picture is what I have done.
https://imgur.com/yqn783x
And then I got a serious problem when I try to create a large terrain, I hit a slowing performance. It was very slow and fps just around 15fps, I thought.
Next, I figured out Minecraft chunk and culling face algorithm can solve slowing performance by dividing the world map into small pieces like chunk and just rendering visible faces of a cube. So how to create a chunk in the right way and how the culling face algorithm is applied in Chunk?
So far, that is what I have tried
I read about Chunk in Minecraft at https://minecraft.gamepedia.com/Chunk
I created a demo Chunk by this below code (it is not the completed code because I removed it out)
I created a CubeData that contains cube position and cube type.
And I call the GenerateTerrain function to make a simple chunk data (16x16x16) like below (CHUNK_SIZE is 16)
for (int x = 0; x < CHUNK_SIZE; x++) {
for (int y = 0; y < CHUNK_SIZE; y++) {
for (int z = 0; z < CHUNK_SIZE; z++) {
CubeType cubeType = { GRASS_BLOCK };
Location cubeLocation = { x, y, z };
CubeData cubeData = { cubeLocation, cubeType };
this->Cubes[x][y][z] = cubeData;
}
}
}
After that, I had a boolean array which is called "mask" contains two values are 0 (not visible) or 1 (visible) and matches with their cube data. And then I call Render function of Chunk class to render a chunk. This code below like what I have done (but it is not complete code because I removed that code and replaced with new code)
for (int x = 0; x < CHUNK_SIZE; x++) {
for (int y = 0; y < CHUNK_SIZE; y++) {
for (int z = 0; z < CHUNK_SIZE; z++) {
for(int side = 0; side < 6;side++){
if(this->mask[x][y][z][side] == true) cubeRenderer.Render(cubeData[x][y][z]);
}
}
}
}
But the result I got that everything still slow (but it is better than the first fps, from 15fps up to 25-30fps, maybe)
I guess it is not gpu problem, it is a cpu problem because there is too many loops in render call.
So I have kept research because I think my approach was wrong. There may have some right way to create a chunk, right?
So I found the solution that puts every visible verticle to one VBO. So I just have to call and bind VBO definitely one time.
So this below code show what I have tried
cout << "Generating Terrain..." << endl;
for (int side = 0; side < 6; side++) {
for (int x = 0; x < CHUNK_SIZE; x++) {
for (int y = 0; y < CHUNK_SIZE; y++) {
for (int z = 0; z < CHUNK_SIZE; z++) {
if (this->isVisibleSide(x, y, z, side) == true) {
this->cubeRenderer.AddVerticleToVBO(this->getCubeSide(side), glm::vec3(x, y, z), this->getTexCoord(this->Cubes[x][y][z].cubeType, side));
}
}
}
}
}
this->cubeRenderer.GenerateVBO();
And call render one time at all.
void CubeChunk::Update()
{
this->cubeRenderer.Render(); // with VBO data have already init above
}
And I got this:
https://imgur.com/YqsrtPP
I think my way was wrong.
So what should I do to create a chunk? Any suggestion?
I have been trying to implement noise based grass patches all day. Before I just had it pick random tiles, but they looked bad because they weren't in patches.
FastNoise GrassNoise;
for (int x = 0; x < MapSizeX; x++) {
for (int y = 0; y < MapSizeY; y++) {
if (GrassNoise.GetValue(Map[x][y].Sprite.getPosition().x, Map[x][y].Sprite.getPosition().y) > 0.5) {
Map[x][y].Sprite.setTexture(*Grass);
}
}
}
I'm pretty sure that I'm just not generating the Noise correctly. With that code, all of the tiles get turned grass. I'm looking for just a few patches.
github.com/Auburns/FastNoise
Thanks in advance
For the record, the problem was that the arguments passed to GrassNoise.GetValue were floating points in the [0,1] range, whereas the function expects integers.
I'm looking for an efficiant way to get the posistion of all pixels that has a value bigger that let's say (100,100,100). I know I could put use minmaxLoc to get the position of the max and min but a want to add an average to it to I can get them all, and I don't want to use a while loop.
thanks in advance
You could use a pseudocode like the following:
//process the loop in a multithread way with openmp
#pragma omp parallel for
int xy=0;
for(int x = 0; x <= x_resolution; ++x) {
for(int y = 0; y <= y_resolution, ++y) {
if(value of Point bigger than (100,100,100) {
do_what_you_want;
}
++xy;
}
}
I am working on the implementation of functions for an already written image processing program. I am given explanations of functions, but not sure how they are designating pixels of the image.
In this case, I need to flip the image horizontally, i.e., rotates 180 degrees around the vertical axis
Is this what makes the "image" i am to flip?
void Image::createImage(int width_x, int height_y)
{
width = width_x;
height = height_y;
if (pixelData!=NULL)
freePixelData();
if (width <= 0 || height <= 0) {
return;
}
pixelData = new Color* [width]; // array of Pixel*
for (int x = 0; x < width; x++) {
pixelData[x] = new Color [height]; // this is 2nd dimension of pixelData
}
}
I do not know if all the functions I have written are correct.
Also, the Image class calls on a Color class
So to re-ask: what am I "flipping" here?
Prototype for function is:
void flipLeftRight();
As there is no input into the function, and I am told it modifies pixelData, how do I flip left to right?
A quick in place flip. Untested, but the idea is there.
void flipHorizontal(u8 *image, u32 width, u32 height)
{
for(int i=0; i < height; i++)
{
for(int j=0; j < width/2; j++)
{
int sourceIndex = i * width + j;
int destIndex = (i+1) * width - j - 1;
image[sourceIndex] ^= image[destIndex];
image[destIndex] ^= image[sourceIndex];
image[sourceIndex] ^= image[destIndex];
}
}
}
well, the simplest approach would be to read it 1 row at a time into a temporary buffer the same size as 1 row.
Then you could use something like std::reverse on the temporary buffer and write it back.
You could also do it in place, but this is the simplest approach.
EDIT: what i;ve described is a mirror, not a flip, to mirror you also need to reverse the order of the rows. Nothing too bad, to do that I would create a buffer the same size as the image, copy the image and then write it back with the coordinates adjusted. Something like y = height - x and x = width - x.
I am trying to take the imageData of image in this where w= width of image and h = height of image
for (int i = x; i < x+h; i++) //height of frame pixels
{
for (int j = y; j < y+w; j++)//width of frame pixels
{
int pos = i * w * Channels + j; //channels is 3 as rgb
// if any data exists
if (data->imageData[pos]>0) //Taking data (here is the problem how to take)
{
xPos += j;
yPos += i;
nPix++;
}
}
}
jeff7 gives you a link to a very old version of OpenCV. OpenCV 2.0 has a new C++ wrapper that is much better than the C++ wrapper mentioned in the link. I recommend that you read the C++ reference of OpenCV for information on how to access individual pixels.
Another thing to note is: you should have the outer loop being the loop in y-direction (vertical) and the inner loop be the loop in x-direction. OpenCV is in C/C++ and it stores the values in row major.
See good explanation here on multiple methods for accessing pixels in an IplImage in OpenCV.
From the code you've posted your problem lies in your position variable, you'd want something like int pos = i*w*Channels + j*Channels, then you can access the RGB pixels at
unsigned char r = data->imageData[pos];
unsigned char g = data->imageData[pos+1];
unsigned char b = data->imageData[pos+2];
(assuming RGB, but on some platforms I think it can be stored BGR).
uchar* colorImgPtr;
for(int i=0; i<colorImg->width; i++){
for(int j=0; j<colorImg->height; j++){
colorImgPtr = (uchar *)(colorImg->imageData) + (j*colorImg->widthStep + i-colorImg->nChannels)
for(int channel = 0; channel < colorImg->nChannels; channel++){
//colorImgPtr[channel] here you have each value for each pixel for each channel
}
}
}
There are quite a few methods to do this (the link provided by jeff7 is very useful).
My preferred method to access image data is the cvPtr2D method. You'll want something like:
for(int x = 0; x < width; ++x)
{
for(int y = 0; y < height; ++y)
{
uchar* ptr = cvPtr2D(img, y, x, NULL);
// blue channel can now be accessed with ptr[0]
// green channel can now be accessed with ptr[1]
// red channel can now be accessed with ptr[2]
}
}
(img is an IplImage* in the above code)
Not sure if this is the most efficient way of doing this etc. but I find it the easiest and simplest way of doing it.
You can find documentation for this method here.