gpt4 book ai didi

c++ - OpenGL 洪水填充无法识别边界

转载 作者:行者123 更新时间:2023-11-30 03:16:08 24 4
gpt4 key购买 nike

我正在尝试在 OpenGL 中实现洪水填充算法,但我遇到了一个错误。错误是算法不会在边界处停止,而是一直持续到窗口的边缘,最终因错误的内存访问错误而崩溃。我正在使用 MacOS Mojave 10.14.4。

我认为我的实现逻辑是正确的,但是,我已经从 getPixel 中打印出每个像素的颜色,而且它始终是白色(背景色),即使在获取边界像素。

下面的代码使用 Bresenham 的直线算法(中点算法)绘制了一个圆,然后用洪水填充它(未成功)。

#include <GLUT/GLUT.h>
#include <iostream>


struct Color {
GLubyte r;
GLubyte g;
GLubyte b;
};

Color getPixelColor(GLint x, GLint y) {
Color color;
glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &color);
return color;
}

void setPixel (GLint x, GLint y) {
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
Color color = getPixelColor(x, y);
}


void setPixelColor(GLint x, GLint y, Color color) {
glColor3ub(color.r, color.g, color.b);
setPixel(x, y);
glEnd();
glFlush();
}

void floodFill4 (GLint x, GLint y, Color fillColor, Color interiorColor) {
Color color = getPixelColor(x, y);
if (color.r == interiorColor.r && color.g == interiorColor.g &&
color.b == interiorColor.b) {
setPixelColor(x, y, fillColor);
floodFill4 (x + 1, y, fillColor, interiorColor);
floodFill4 (x - 1, y, fillColor, interiorColor);
floodFill4 (x, y + 1, fillColor, interiorColor);
floodFill4 (x, y - 1, fillColor, interiorColor);
}
}

void drawCirclePoint(GLint x, GLint y, GLint cx, GLint cy) {
setPixel(cx+x, cy+y);
setPixel(cx+y, cy+x);
setPixel(cx-y, cy+x);
setPixel(cx-x, cy+y);
setPixel(cx-x, cy-y);
setPixel(cx-y, cy-x);
setPixel(cx+y, cy-x);
setPixel(cx+x, cy-y);
}

void drawCircle(GLint cx, GLint cy, GLint radius) {
int p = 1 - radius;
GLint x = 0;
GLint y = radius;
while (x < y) {
drawCirclePoint(x, y, cx, cy);
if (p < 0) {
x++;
p += (2 * x) + 1;
} else {
x++;
y--;
p += (2 * x) + 1 - (2 * y);
}
}
}


void displayMe(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3ub(0, 0, 0);
GLint cx = 0;
GLint cy = 0;
GLint radius = 200;
// Draw head
glColor3ub(0, 0, 0);
drawCircle(cx, cy, radius);
glEnd();
glFlush();
Color interiorColor = {255, 255, 255};
Color fillColor = {0, 0, 255};
// floodFill4(100, 100, fillColor, interiorColor);
}

void init (void) {
glClearColor(1.0, 1.0, 1.0, 0.0); // Set display-window color to white.
glMatrixMode(GL_PROJECTION); // Set projection parameters.
glLoadIdentity();
gluOrtho2D(-1000.0, 1000.0, -1000.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(1000, 1000);
glutInitWindowPosition(100, 100);
glutCreateWindow("My Drawing");
init();
glutDisplayFunc(displayMe);
glutMainLoop();
return 0;
}

我看过this post ,这看起来很相似,但找不到解决方案。

最佳答案

如果您要坚持使用 glVertex() 进行点绘图,请确保您设置了矩阵堆栈变换 (GL_PROJECTION/GL_MODELVIEW) 所以它们匹配 glReadPixels() 坐标系:

glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D( 0, glutGet(GLUT_WINDOW_WIDTH), 0, glutGet(GLUT_WINDOW_HEIGHT) );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

或者为 setPixel*() 切换到 glRasterPos() + glDrawPixels()

更好的是,在主机端执行填充逻辑并将结果上传到 GL 纹理以供显示。

无论哪种方式,即使是在相当合理大小的输入上,你都会遇到使用该递归解决方案的堆栈溢出,因此你可能希望切换到显式堆栈/queue :

void floodFill4( GLint aX, GLint aY, Color fillColor, Color interiorColor )
{
typedef std::pair< GLint, GLint > Location;
std::queue< Location > locations;

locations.push( Location( aX, aY ) );
while( !locations.empty() )
{
const Location loc = locations.front();
locations.pop();

GLint x = loc.first;
GLint y = loc.second;

Color color = getPixelColor( x, y );
if( color.r == interiorColor.r &&
color.g == interiorColor.g &&
color.b == interiorColor.b )
{
setPixelColor( x, y, fillColor );
locations.push( Location( x, y - 1 ) );
locations.push( Location( x, y + 1 ) );
locations.push( Location( x - 1, y ) );
locations.push( Location( x + 1, y ) );
}
}
}

关于c++ - OpenGL 洪水填充无法识别边界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56554822/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com