Creating a right side menu on C++ using openGL - c++

I'm working on a project that is creating a painting program using OpenGL and GLUT on C++.
So far I have a color menu on the left side and now I am trying to make a tool menu on the right side but I can't figure out how to get it on the right.
This is what i have so far:
int inwindow(int x, int y)
{
return (x > WLEFT && x < WRIGHT && y > WBOTTOM && y < WTOP);
}
static float colormenu[][8] = {{Red}, {Orange}, {Yellow}, {Green}, {Cyan}, {Blue}, {Purple}, {Black}};
int incolormenu(int x, int y)
{
return (x >= 0 && x <= MENUWIDTH && y >= 0 && y <= HEIGHT);
}
int colormenuindex(int x, int y)
{
if(!incolormenu(x, y))
return -1;
else
return(y / BOXHEIGHT);
}
static float toolmenu[][6] = {{Pencil}, {Line}, {Box}, {Rectangle}, {Circle}, {FCircle}};
int intoolmenu(int x, int y)
{
return (x >= 0 && x <= MENUWIDTH && y >= 0 && y <= HEIGHT);
}
int toolmenuindex(int x, int y)
{
if(!intoolmenu(x, y))
return -1;
else
return(y / BOXHEIGHT);
}
void drawSketch()
{
int i;
glClearColor(Grey, 1);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(Black);
for(i = 0; i < NCOLORS; i++)
{
glColor3f(colormenu[i][R], colormenu[i][G], colormenu[i][B]);
glRecti(1, BOXHEIGHT * i + 1, MENUWIDTH - 1, BOXHEIGHT * (i + 1) - 1);
}
for(i = 0; i < NCOLORS; i++)
{
glColor3f(toolmenu[i][Pencil], toolmenu[i][Line], toolmenu[i][Box]);
glRasterPos3f(0.2, -0.8, -1.5);
}
glFlush();
}

Not sure if you are willing to use a third party solution but I've used the following project with really good results.
NanoGUI Github Project

Related

Region Growing OpenCv c/c++ with onMouse

I am encountering an issue with my code. I aim to generate three seeds at different locations in the image and observe the pixels growing. I am using the onMouse function to select the areas, however, only the last point is being recognized. What changes do I need to make for this code to function correctly?
Pont seed,seed2,seed3;
bool clicked = false;
void onmouse(int event, int x, int y, int flags, void* userdata)
{
if (event == EVENT_LBUTTONDOWN) {
seed = Point2i(y, x);
seed2 = Point2i(y, x);
seed3 = Point2i(y, x);
clicked = true;
}
}
int main() {
string path = "C:/img_4.jpg";
Mat im_gray = imread(path, IMREAD_GRAYSCALE);
Mat im_new;
int threshold = 50;
imshow("Image", im_gray);
setMouseCallback("Image", onmouse, NULL);
while (!clicked) {
waitKey(0);
}
regionGrowing_teste1(im_gray, im_new, seed, seed2, seed3, threshold);
imshow("Segmented", im_new);
waitKey(0);
return 0;
}
Mat regionGrowing_teste1(Mat& src, Mat& dst, Point2i seed1, Point2i seed2, Point2i seed3, int threshold) {
dst = Mat::zeros(src.rows, src.cols, CV_8UC1);
vector<Point2i> queue1, queue2, queue3;
queue1.push_back(seed1);
queue2.push_back(seed2);
queue3.push_back(seed3);
int intensity1 = (int)src.at<uchar>(seed1);
int intensity2 = (int)src.at<uchar>(seed2);
int intensity3 = (int)src.at<uchar>(seed3);
int x, y;
while (!queue1.empty() || !queue2.empty() || !queue3.empty()) {
if (!queue1.empty()) {
Point2i p = queue1.back();
queue1.pop_back();
x = p.x; y = p.y;
if (x > 0 && x < src.rows - 1 && y > 0 && y < src.cols - 1) {
if ((int)dst.at<uchar>(x, y) == 0) {
int intensityNeighbor = (int)src.at<uchar>(x, y);
if (abs(intensity1 - intensityNeighbor) < threshold) {
dst.at<uchar>(x, y) = 255;
queue1.push_back(Point2i(x + 1, y));
queue1.push_back(Point2i(x - 1, y));
queue1.push_back(Point2i(x, y + 1));
queue1.push_back(Point2i(x, y - 1));
}
}
}
}
if (!queue2.empty()) {
Point2i p = queue2.back();
queue2.pop_back();
x = p.x; y = p.y;
if (x > 0 && x < src.rows - 1 && y > 0 && y < src.cols - 1) {
if ((int)dst.at<uchar>(x, y) == 0) {
int intensityNeighbor = (int)src.at<uchar>(x, y);
if (abs(intensity2 - intensityNeighbor) < threshold) {
dst.at<uchar>(x, y) = 255;
queue2.push_back(Point2i(x + 1, y));
queue2.push_back(Point2i(x - 1, y));
queue2.push_back(Point2i(x, y + 1));
queue2.push_back(Point2i(x, y - 1));
}
}
}
}
// process points in queue3
if (!queue3.empty()) {
Point2i p = queue3.back();
queue3.pop_back();
x = p.x; y = p.y;
if (x > 0 && x < src.rows - 1 && y > 0 && y < src.cols - 1) {
if ((int)dst.at<uchar>(x, y) == 0) {
int intensityNeighbor = (int)src.at<uchar>(x, y);
if (abs(intensity3 - intensityNeighbor) < threshold) {
dst.at<uchar>(x, y) = 255;
queue3.push_back(Point2i(x + 1, y));
queue3.push_back(Point2i(x - 1, y));
queue3.push_back(Point2i(x, y + 1));
queue3.push_back(Point2i(x, y - 1));
}
}
}
}
}
for (int i = 0; i < src.rows; i++) {
for (int j = 0; j < src.cols; j++) {
if (dst.at<uchar>(i, j) == 0) {
dst.at<uchar>(i, j) = src.at<uchar>(i, j);
}
}
}
return dst;
}
I hope to see the placement of three points and watch them grow.

Performant Threaded C++ Pixel Rendering: Fastest Way?

My goal is simple: I want to create a rendering system in C++ that can draw thousands of bitmaps on screen. I have been trying to use threads to speed up the process but to no avail. In most cases, I have actually slowed down performance by using multiple threads. I am using this project as an educational exercise by not using hardware acceleration. That said, my question is this:
What is the best way to use several threads to accept a massive list of images to be drawn onto the screen and render them at break-neck speeds? I know that I won’t be able to create a system that can rival hardware accelerated graphics, but I believe that my idea is still feasible because the operation is so simple: copying pixels from one memory location to another.
My renderer design uses three core blitting operations: position, rotation, and scale of a bitmap image. I have it set up to only rotate an image when needed, and only scale an image when needed.
I have gone through several designs for this system. All of them too slow to get the job done (300 64x64 bitmaps at barely 60fps).
Here are the designs I have tried:
Immediately drawing a source bitmap on a destination bitmap for every image on screen (moderate speed).
Creating workers that accept a draw instruction and immediately begin working on it while other workers receive their instructions also (slowest).
Workers that receive packages of several instructions at a time (slower).
Saving all drawing instructions up and then parting them up in one swoop to several workers while other tasks (in theory) are being done (slowest).
Here is the bitmap class I am using to blit bitmaps onto each other:
class Bitmap
{
public:
Bitmap(int w, int h)
{
width = w;
height = h;
size = w * h;
pixels = new unsigned int[size];
}
virtual ~Bitmap()
{
if (pixels != 0)
{
delete[] pixels;
pixels = 0;
}
}
void blit(Bitmap *bmp, float x, float y, float rot, float sclx,
float scly)
{
// Position only
if (rot == 0 && sclx == 1 && scly == 1)
{
blitPos(bmp, x, y);
return;
}
// Rotate only
else if (rot != 0 && sclx == 1 && scly == 1)
{
blitRot(bmp, x, y, rot);
return;
}
// Scale only
else if (rot == 0 && (sclx != 1 || scly != 1))
{
blitScl(bmp, x, y, sclx, scly);
return;
}
/////////////////////////////////////////////////////////////////////////////
// If it is not one of those, you have to do all three... :D
/////////////////////////////////////////////////////////////////////////////
// Create a bitmap that is scaled to the new size.
Bitmap tmp((int)(bmp->width * sclx), (int)(bmp->height * scly));
// Find how much each pixel steps:
float step_x = (float)bmp->width / (float)tmp.width;
float step_y = (float)bmp->height / (float)tmp.height;
// Fill the scaled image with pixels!
float inx = 0;
int xOut = 0;
while (xOut < tmp.width)
{
float iny = 0;
int yOut = 0;
while (yOut < tmp.height)
{
unsigned int sample = bmp->pixels[
(int)(std::floor(inx) + std::floor(iny) * bmp->width)
];
tmp.drawPixel(xOut, yOut, sample);
iny += step_y;
yOut++;
}
inx += step_x;
xOut++;
}
blitRot(&tmp, x, y, rot);
}
void drawPixel(int x, int y, unsigned int color)
{
if (x > width || y > height || x < 0 || y < 0)
return;
if (color == 0x00000000)
return;
int index = x + y * width;
if (index >= 0 && index <= size)
pixels[index] = color;
}
unsigned int getPixel(int x, int y)
{
return pixels[x + y * width];
}
void clear(unsigned int color)
{
std::fill(&pixels[0], &pixels[size], color);
}
private:
void blitPos(Bitmap *bmp, float x, float y)
{
// Don't draw if coordinates are already past edges
if (x > width || y > height || y + bmp->height < 0 || x + bmp->width < 0)
return;
int from;
int to;
int destfrom;
int destto;
for (int i = 0; i < bmp->height; i++)
{
from = i * bmp->width;
to = from + bmp->width;
//////// Caps
// Bitmap is being drawn past the right edge
if (x + bmp->width > width)
{
int cap = bmp->width - ((x + bmp->width) - width);
to = from + cap;
}
// Bitmap is being drawn past the left edge
else if (x + bmp->width < bmp->width)
{
int cap = bmp->width + x;
from += (bmp->width - cap);
to = from + cap;
}
//////// Destination Maths
if (x < 0)
{
destfrom = (y + i) * width;
destto = destfrom + (bmp->width + x);
}
else
{
destfrom = x + (y + i) * width;
destto = destfrom + bmp->width;
}
// Bitmap is being drawn past either top or bottom edges
if (y + i > height - 1)
{
continue;
}
if (destfrom > size || destfrom < 0)
{
continue;
}
memcpy(&pixels[destfrom], &bmp->pixels[from], sizeof(unsigned int) * (to - from));
}
}
void blitRot(Bitmap *bmp, float x, float y, float rot)
{
float sine = std::sin(-rot);
float cosine = std::cos(-rot);
int x1 = (int)(-bmp->height * sine);
int y1 = (int)(bmp->height * cosine);
int x2 = (int)(bmp->width * cosine - bmp->height * sine);
int y2 = (int)(bmp->height * cosine + bmp->width * sine);
int x3 = (int)(bmp->width * cosine);
int y3 = (int)(bmp->width * sine);
int minx = (int)std::min(0, std::min(x1, std::min(x2, x3)));
int miny = (int)std::min(0, std::min(y1, std::min(y2, y3)));
int maxx = (int)std::max(0, std::max(x1, std::max(x2, x3)));
int maxy = (int)std::max(0, std::max(y1, std::max(y2, y3)));
int w = maxx - minx;
int h = maxy - miny;
int srcx;
int srcy;
int dest_x;
int dest_y;
unsigned int color;
for (int sy = miny; sy < maxy; sy++)
{
for (int sx = minx; sx < maxx; sx++)
{
srcx = sx * cosine + sy * sine;
srcy = sy * cosine - sx * sine;
dest_x = x + sx;
dest_y = y + sy;
if (dest_x <= width - 1 && dest_y <= height - 1
&& dest_x >= 0 && dest_y >= 0)
{
color = 0;
// Only grab a pixel if it is inside of the src image
if (srcx < bmp->width && srcy < bmp->height && srcx >= 0 &&
srcy >= 0)
color = bmp->getPixel(srcx, srcy);
// Only this pixel if it is not completely transparent:
if (color & 0xFF000000)
// Only if the pixel is somewhere between 0 and the bmp size
if (0 < srcx < bmp->width && 0 < srcy < bmp->height)
drawPixel(x + sx, y + sy, color);
}
}
}
}
void blitScl(Bitmap *bmp, float x, float y, float sclx, float scly)
{
// Create a bitmap that is scaled to the new size.
int finalwidth = (int)(bmp->width * sclx);
int finalheight = (int)(bmp->height * scly);
// Find how much each pixel steps:
float step_x = (float)bmp->width / (float)finalwidth;
float step_y = (float)bmp->height / (float)finalheight;
// Fill the scaled image with pixels!
float inx = 0;
int xOut = 0;
float iny;
int yOut;
while (xOut < finalwidth)
{
iny = 0;
yOut = 0;
while (yOut < finalheight)
{
unsigned int sample = bmp->pixels[
(int)(std::floor(inx) + std::floor(iny) * bmp->width)
];
drawPixel(xOut + x, yOut + y, sample);
iny += step_y;
yOut++;
}
inx += step_x;
xOut++;
}
}
public:
int width;
int height;
int size;
unsigned int *pixels;
};
Here is some code showing the latest method I have tried: saving up all instructions and then giving them to workers once they have all been received:
class Instruction
{
public:
Instruction() {}
Instruction(Bitmap* out, Bitmap* in, float x, float y, float rot,
float sclx, float scly)
: outbuffer(out), inbmp(in), x(x), y(y), rot(rot),
sclx(sclx), scly(scly)
{ }
~Instruction()
{
outbuffer = nullptr;
inbmp = nullptr;
}
public:
Bitmap* outbuffer;
Bitmap* inbmp;
float x, y, rot, sclx, scly;
};
Layer Class:
class Layer
{
public:
bool empty()
{
return instructions.size() > 0;
}
public:
std::vector<Instruction> instructions;
int pixel_count;
};
Worker Thread Class:
class Worker
{
public:
void start()
{
done = false;
work_thread = std::thread(&Worker::processData, this);
}
void processData()
{
while (true)
{
controller.lock();
if (done)
{
controller.unlock();
break;
}
if (!layers.empty())
{
for (int i = 0; i < layers.size(); i++)
{
for (int j = 0; j < layers[i].instructions.size(); j++)
{
Instruction* inst = &layers[i].instructions[j];
inst->outbuffer->blit(inst->inbmp, inst->x, inst->y, inst->rot, inst->sclx, inst->scly);
}
}
layers.clear();
}
controller.unlock();
}
}
void finish()
{
done = true;
}
public:
bool done;
std::thread work_thread;
std::mutex controller;
std::vector<Layer> layers;
};
Finally, the Render Manager Class:
class RenderManager
{
public:
RenderManager()
{
workers.reserve(std::thread::hardware_concurrency());
for (int i = 0; i < 1; i++)
{
workers.emplace_back();
workers.back().start();
}
}
void layer()
{
layers.push_back(current_layer);
current_layer = Layer();
}
void blit(Bitmap* out, Bitmap* in, float x, float y, float rot, float sclx, float scly)
{
current_layer.instructions.emplace_back(out, in, x, y, rot, sclx, scly);
}
void processInstructions()
{
if (layers.empty())
layer();
lockall();
int index = 0;
for (int i = 0; i < layers.size(); i++)
{
// Evenly distribute the layers in a round-robin fashion
Layer l = layers[i];
workers[index].layers.push_back(layers[i]);
index++;
if (index >= workers.size()) index = 0;
}
layers.clear();
unlockall();
}
void lockall()
{
for (int i = 0; i < workers.size(); i++)
{
workers[i].controller.lock();
}
}
void unlockall()
{
for (int i = 0; i < workers.size(); i++)
{
workers[i].controller.unlock();
}
}
void finish()
{
// Wait until every worker is done rendering
lockall();
// At this point, we know they have nothing more to draw
unlockall();
}
void endRendering()
{
for (int i = 0; i < workers.size(); i++)
{
// Send each one an exit code
workers[i].finish();
}
// Let the workers finish and then return
for (int i = 0; i < workers.size(); i++)
{
workers[i].work_thread.join();
}
}
private:
std::vector<Worker> workers;
std::vector<Layer> layers;
Layer current_layer;
};
Here is a screenshot of what the 3rd method I tried, and it's results:
Sending packages of draw instructions
What would really be helpful is that if someone could simply point me in the right direction in regards to what method I should try. I have tried these four methods and have failed, so I stand before those who have done greater things than I for help. The least intelligent person in the room is the one that does not ask questions because his pride does not permit it. Please keep in mind though, this is my first question ever on Stack Overflow.

Simple Clipping in DirectX 9

I am interested in simple rect clipping in Directx9.
On the top picture you see what I get.
I want to get what is on the bottom picture without changing the coordinates and/or viewport.
Meaning, I will draw the entire circle but Directx9 will just clip it.
It would be preferable that clip rect will be given in WINDOW coordinates, so it will not be affected by current state transformations.
In additions, it should affect everything going from now on to window, including polygons, sprites, textures, text etc.
Can somone suggest how to do this?
You're describing a scissor test, which is built into the directx device.
See Scissor Test
More specifically, you just set the rectangle in screen coordinates using SetScissorRect
And then enable the scissor test by calling
device->SetRenderState( D3DRS_SCISSORTESTENABLE , TRUE );
I had the same question a month ago and I came up with a solution myself after trying to locate a clipping method, so I had to develop my own... This should work:
void Clip(LPDIRECT3DDEVICE9 device, LPDIRECT3DSURFACE9 surface, LPDIRECT3DSURFACE9 backbuffer, int x, int y, int width, int height, int destX, int destY, int destWidth, int destHeight)
{
RECT source;
if (x >= destX && (x+width) <= (destX+destWidth))
{
source.left = 0;
source.right = width;
}
else if ( (x >= destX && x <= (destX+destWidth)) && ((x+width) > (destX+destWidth)))
{
source.left = 0;
source.right = width - ((x+width) - (destX+destWidth));
source.right = abs(source.right);
}
else if (x < destX && (x+width) < (destX+destWidth))
{
source.left = abs(x);
source.right = width;
}
else if ( (x < destX) && ((x+width) > (destX+destWidth)))
{
source.left = abs(x);
source.right = source.left + (destWidth);
}
else
{
return;
}
if (y >= destY && (y+height) <= (destY+destHeight))
{
source.top = 0;
source.bottom = height;
}
else if ( (y >= destY && y <= (destY+destHeight)) && ((y+height) > (destY+destHeight)) )
{
source.top = 0;
source.bottom = height - ((y+height) - (destY+destHeight));
source.bottom = abs(source.bottom);
}
else if (y < destY && (y+height) > destY && (y+height) <= (destY+destHeight))
{
source.top = abs(y);
source.bottom = height;
}
else if ( (y < destY) && ((y+height) > (destY+destHeight)))
{
source.top = abs(y);
source.bottom = source.top + (destHeight);
}
else
{
return;
}
RECT destination;
if (x >= destX && (x+width) <= (destX+destWidth))
{
destination.left = x;
destination.right = x + width;
}
else if ( (x >= destX && x <= (destX+destWidth)) && ((x+width) > (destX+destWidth)))
{
destination.left = x;
destination.right = (destX+destWidth);
}
else if ( (x < destX) && ((x+width) < (destX+destWidth)) && ((x+width) >= x))
{
destination.left = destX;
destination.right = width - abs(x);
}
else if ( (x < destX) && ((x+width) > (destX+destWidth)))
{
destination.left = destX;
destination.right = (destX+destWidth);
}
else
{
return;
}
if (y >= destY && (y+height) <= (destY+destHeight))
{
destination.top = y;
destination.bottom = y + height;
}
else if ( (y >= destY && y <= (destY+destHeight)) && (y+height) > (destY+destHeight))
{
destination.top = y;
destination.bottom = (destY+destHeight);
}
else if (y < destY && (y+height) > destY && (y+height) <= (destY+destHeight))
{
destination.top = destY;
destination.bottom = height - abs(y);
}
else if ( (y < destY) && ((y+height) > (destY+destHeight)))
{
destination.top = destY;
destination.bottom = (destY+destHeight);
}
else
{
return;
}
device->StretchRect(surface, &source, backbuffer, &destination, D3DTEXF_NONE);
DeleteObject(&source);
DeleteObject(&destination);
};

c++ dynamic arrays and pointers

Ok so what I'm trying to do is create an array of pointers that point to vectors that change in size. Also the array of pointers is nestled inside a class that's inside a vector. For some reason I seem to be having problems with memory becoming corrupt. Also if I use vectors I run into the problems with the stack overflowing caused by stuff resizing and calling constructors. Here is an essential layout of what I'm gunning for.
Maybe a little sloppy. But I end up with the problem of memory being currupted in the babyclasses pointers, basically I want to access "linked" babyclasses via the babyclasses vector of babyclasses it's connected to.
Any clever ideas here?
And before anyone tells me this is a silly way to do things, isn't this type of functionality the basis of OO Programming?
class Baby
{
public:
deque<shared_ptr<Baby>> vInputs;
int X;
int Y;
int Z;
Baby()
{
numInputs = 0;
isNull = false;
wasTickled = false;
X,Y,Z = 0;
}
void addInput(shared_ptr<Baby> baby)
{
if(numInputs == 0)
vInputs = deque<shared_ptr<Baby>>(0);
vInputs.push_back(baby);
numInputs++;
}
void setXYZ(int x, int y, int z)
{
X = x;
Y = y;
Z = z;
}
void Tickle()
{
if(!wasTickled)
wasTickled = true;
else
return;
for(int i=0;i<numInputs;i++)
{
vInputs[i]->Tickle();
}
}
void setNull(bool isnull)
{
isNull = isnull;
}
private:
int numInputs;
bool isNull;
bool wasTickled;
};
class BabyLayer
{
public:
int Width;
int Height;
BabyLayer()
{
Width = 0;
Height = 0;
}
BabyLayer(int width, int height)
{
Width = width;
Height = height;
vecBabies = std::deque<deque<Baby>>(0);
for(int i=0;i<height;i++)
{
deque<Baby> row = deque<Baby>(0);
for(int i=0;i<width;i++)
{
row.push_back(Baby());
};
vecBabies.push_back(row);
}
MakeConnections();
}
Baby * getBaby(int x, int y)
{
Baby n = Baby();
n.setNull(true);
if(x >= Width || x <0)
return &n;
if(y >= Height || y < 0)
return &n;
n.setNull(false);
return &vecBabies[y][x];
}
~BabyLayer(void)
{
}
private:
std::deque<deque<Baby>> vecBabies;
void MakeConnections()
{
for(int y=0;y<Height;y++)
{
for(int x=0;x<Width;x++)
{
//Top Right
if(y > 0 && x < Width-1)
vecBabies[y][x].addInput(shared_ptr<Baby>(&vecBabies[y-1][x+1]));
//Middle Right
if(x < Width -1)
vecBabies[y][x].addInput(shared_ptr<Baby>(&vecBabies[y][x+1]));
//Bottom Right
if(x < Width -1 && y < Height-1)
vecBabies[y][x].addInput(shared_ptr<Baby>(&vecBabies[y+1][x+1]));
//Bottom Middle
if(y < Height-1)
vecBabies[y][x].addInput(shared_ptr<Baby>(&vecBabies[y+1][x]));
}
}
}
};
class BabyCube
{
public:
int X;
int Y;
int Z;
BabyCube(int x, int y, int z)
{
X = x;
Y = y;
Z = z;
Layers = deque<BabyLayer>();
for(int i=0;i<z;i++)
{
BabyLayer lay = BabyLayer(x,y);
Layers.push_back(lay);
}
NullBaby = Baby();
NullBaby.setNull(true);
MakeConnections();
}
void MakeConnections()
{
int l = Layers.size();
if(l == 0 || l == 1)
return;
for(int layer=0;layer<l;layer++)
{
BabyLayer * lay = &Layers[layer];
if(layer< l-1)
{
for(int y=0;y<lay->Height;y++)
{
for(int x=0;x<lay->Width;x++)
{
//Top Left
if(x > 0 && y > 0)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x-1,y-1)));
//Top Middle
if(y > 0)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x,y-1)));
//Top Right
if(y > 0 && x+1 < lay->Width-1)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x+1,y-1)));
//Middle Right
if(x+1 < lay->Width -1)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x+1,y)));
//Bottom Right
if(x+1 < lay->Width -1 && y+1 < lay->Height-1)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x+1,y+1)));
//Bottom Middle
if(y+1 < lay->Height-1)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x,y+1)));
//Bottom Left
if(x > 0 && y+1 < lay->Height-1)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x-1,y+1)));
//Middle Left
if(x > 0)
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x-1,y)));
//Middle Middle
Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x,y)));
}
}
}
}
}
Baby * getBaby(int x, int y, int z)
{
if(z >= Layers.size() || z < 0)
return &NullBaby;
if(y >= Layers[z].Height || y < 0)
return &NullBaby;
if(x >= Layers[z].Width || x < 0)
return &NullBaby;
return Layers[z].getBaby(x,y);
}
void Update()
{
}
~BabyCube(void)
{
}
private:
deque<BabyLayer> Layers;
Baby NullBaby;
};
Out of morbid curiosity, I revisited this question to see if anyone had deciphered it.
The only obvious issue I see with the source code is in BabyLayer::GetBaby():
Baby n = Baby();
n.setNull(true);
if(x >= Width || x <0)
return &n; // Bad.
if(y >= Height || y < 0)
return &n; // Bad.
You're declaring a new Baby instance on the stack, then returning a pointer to it. The Baby instance named 'n' gets destructed when GetBaby() returns, and the returned pointer is now invalid.
I don't know what compiler you're using, but Visual Studio 2010 emits, "warning C4172: returning address of local variable or temporary" on these lines. Note that your code sample is incomplete and doesn't actually do anything, I had to declare a BabyCube instance to receive this warning.
Since I can't decipher what your code is supposed to do, and can make no sense of its operation, I can't explain why the memory access exceptions are thrown.

Help with this algorithm

I have an algorithm that can find if a point is inside a polygon.
int CGlEngineFunctions::PointInPoly(int npts, float *xp, float *yp, float x, float y)
{
int i, j, c = 0;
for (i = 0, j = npts-1; i < npts; j = i++) {
if ((((yp[i] <= y) && (y < yp[j])) ||
((yp[j] <= y) && (y < yp[i]))) &&
(x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
c = !c;
}
return c;
}
My only issue with it is it assumes an odd winding rule. What I mean by this is that if the polygon is self intersecting, certain parts that it would considered to be 'empty' will return as false. What I'd need in even if it self intersects, anything inside the polygon will return true.
Thanks
Beware: this answer is wrong. I have no time to fix it right now, but see the comments.
This casts a ray from the point to infinity, and checks for intersections with each of the polygon's edges. Each time an intersection is found, the flag c is toggled:
c = !c;
So an even number of intersections means an even number of toggles, so c will be 0 at the end. An odd number of intersections means an odd number of toggles, so c will be 1.
What you want instead is to set the c flag if any intersection occurs:
c = 1;
And for good measure, you can then eliminate c entirely, and terminate early:
int CGlEngineFunctions::PointInPoly(int npts, float *xp, float *yp, float x, float y)
{
int i, j;
for (i = 0, j = npts-1; i < npts; j = i++) {
if ((((yp[i] <= y) && (y < yp[j])) ||
((yp[j] <= y) && (y < yp[i]))) &&
(x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
return 1;
}
return 0;
}
To translate your original algorithm to english: You're determining if the number of polygon segments to the right of your point are even or odd. If it's even (including zero) your point is outside, if it's odd your point is inside. This means if there are two segments to the right and also two segments to the left, the point is not considered inside the polygon.
What you need to do is change the algorithm so that it checks for segments on both sides; if there's a segment on both sides of the point, then the point is within the polygon.
int CGlEngineFunctions::PointInPoly(int npts, float *xp, float *yp, float x, float y)
{
int i, j;
bool hasSegmentLeft = false;
bool hasSegmentRight = false;
for (i = 0, j = npts-1; i < npts; j = i++) {
if ((((yp[i] <= y) && (y < yp[j])) ||
((yp[j] <= y) && (y < yp[i]))))
{
if (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i])
{
hasSegmentRight = true;
if (hasSegmentLeft) // short circuit early return
return true;
}
else
{
hasSegmentLeft = true;
if (hasSegmentRight) // short circuit early return
return true;
}
}
return hasSegmentLeft && hasSegmentRight;
}
P.S. that for statement construct is a very clever way of dealing with a circular list that wraps around to the beginning; I'd never seen it before.