gpt4 book ai didi

c - 卡在交互式 openGL 程序中

转载 作者:太空宇宙 更新时间:2023-11-04 08:10:43 28 4
gpt4 key购买 nike

每次尝试用鼠标输入两个顶点时,我都会崩溃。我最近改变了组织每个形状的方式,以确保新形状与旧形状重叠。

这个项目的想法是制作各种交互式 Canvas 。用户可以在直线、三角形和矩形之间进行选择,然后选择颜色和其他一些特征。

我知道直线和三角形的代码有效,矩形应该有效,但由于崩溃我无法测试它。

我认为我的问题出在鼠标左键释放区域。特别是将形状 ID 添加到“StructArray”数组中的每个结构。我确定它只是我忽略的东西。

还有一个补充说明,我的类(class)使用的是旧的 openGL,因此程序中已有的任何 openGL 代码都需要保留,我不能使用新的东西或基于着色器的东西。

如果您需要任何说明,请告诉我。

我已经包含了 C 文件和头文件(UPDATE V2):

#include <stdlib.h>
#include <math.h>
#include <stdio.h>

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <OpenGL/glu.h>

#include "lineseg.h"
#include "triseg.h"
#include "rectseg.h"
#include "colors.h"

#define MAXLINES 100

typedef struct shapes{
int id;
} shapes;

enum {LINE, TRIANGLE, RECTANGLE};

shapes *ShapeArray[MAXLINES];


int currentcolor = BLACK;
GLfloat drawingcolor[][3] = {{0.0, 0.0, 0.0},
{1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{0.0, 0.0, 1.0}};
char *colorword[] = {"black", "red", "green", "blue"};

int shapenum = 0; // Number of shapes drawn
int linenum = 0;

Ln *LineSegments[MAXLINES]; // LineSegments is an array of pointers to Ln
Tri *TriangleSegments[MAXLINES]; // TriangleSegments is an array of pointers to Tri
Rect *RectangleSegments[MAXLINES]; // RectangelSegments is an array of pointers to Rect

int NumVertex = 2;

GLint currentx, currenty; // Used to store cursor coordinates
GLdouble dx, dy; // Passed to GetCursorPos, which needs pointers to doubles
GLint winwidth = 700, winheight = 700; // Window width and height
V2d *firstvert = NULL, *secondvert = NULL, *thirdvert = NULL, *fourthvert = NULL; // Pointers to vertices currently being drawn

V2d *make_vertex(int x, int y) {
V2d *tmp;

tmp = (V2d *) malloc(sizeof(V2d));
if (tmp == NULL) {
printf("Out of memory\n");
exit(0);
}
tmp->x = x;
tmp->y = y;

return tmp;
}

Ln *make_line(V2d v1, V2d v2) {
Ln *tmp;

tmp = (Ln *) malloc(sizeof(Ln));
if (tmp == NULL) {
printf("Out of memory\n");
exit(0);
}
tmp->v1 = v1;
tmp->v2 = v2;

return tmp;
}
Tri *make_triangle(V2d v1, V2d v2, V2d v3){
Tri *tmp;

tmp = (Tri *) malloc(sizeof(Tri));
if (tmp == NULL) {
printf("Out of memory\n");
exit(0);
}
tmp->v1 = v1;
tmp->v2 = v2;
tmp->v3 = v3;

return tmp;
}

Rect *make_rectangle(V2d v1, V2d v2){
Rect *tmp;

tmp = (Rect *) malloc(sizeof(Rect));
if (tmp == NULL) {
printf("Out of memory\n");
exit(0);
}
tmp->v1 = v1;
tmp->v2 = v2;

return tmp;
}

void myInit(void)
{
glViewport(0, 0, winwidth, winheight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, winwidth, 0.0, winheight);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClearColor(1.0, 1.0, 1.0, 1.0);
glPointSize(5.0); // size used when rendering points
glLineWidth(2.0); // width used when rendering lines
glLineStipple(2, 0xAAAA); // stippling pattern used when drawing a dotted line

printf("Drawing in %s\n", colorword[currentcolor]);

}

void draw(void){

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < shapenum; i++){
if (ShapeArray[i]->id == LINE) {
// Draw all lines that are already drawn and stored in the array LineSegments
glColor3fv(drawingcolor[LineSegments[i]->color]);
glBegin(GL_LINES);
glVertex2i(LineSegments[i]->v1.x, LineSegments[i]->v1.y);
glVertex2i(LineSegments[i]->v2.x, LineSegments[i]->v2.y);
glEnd();

// Draw the segment that is currently being drawn
if (firstvert != NULL) {
glColor3fv(drawingcolor[currentcolor]);
glBegin(GL_POINTS);
glVertex2i(firstvert->x, firstvert->y);
glEnd();
}

if (secondvert != NULL) {
glColor3fv(drawingcolor[currentcolor]);
glBegin(GL_POINTS);
glVertex2i(secondvert->x, secondvert->y);
glEnd();
glEnable(GL_LINE_STIPPLE);
glBegin(GL_LINES);
glVertex2i(firstvert->x, firstvert->y);
glVertex2i(secondvert->x, secondvert->y);
glEnd();
glDisable(GL_LINE_STIPPLE);
}
}
else if (ShapeArray[i]->id == TRIANGLE){
glColor3fv(drawingcolor[TriangleSegments[i]->color]);
glBegin(GL_LINE_LOOP);
glVertex2i(TriangleSegments[i]->v1.x, TriangleSegments[i]->v1.y);
glVertex2i(TriangleSegments[i]->v2.x, TriangleSegments[i]->v2.y);
glVertex2i(TriangleSegments[i]->v3.x, TriangleSegments[i]->v3.y);
glEnd();

if (firstvert != NULL) {
glColor3fv(drawingcolor[currentcolor]);
glBegin(GL_POINTS);
glVertex2i(firstvert->x, firstvert->y);
glEnd();
}

if (secondvert != NULL) {
glColor3fv(drawingcolor[currentcolor]);
glBegin(GL_POINTS);
glVertex2i(secondvert->x, secondvert->y);
glEnd();
glEnable(GL_LINE_STIPPLE);
glBegin(GL_LINE_LOOP);
glVertex2i(firstvert->x, firstvert->y);
glVertex2i(secondvert->x, secondvert->y);
glVertex2i(thirdvert->x, thirdvert->y);
glEnd();
glDisable(GL_LINE_STIPPLE);
}
}
else if (ShapeArray[i]->id == RECTANGLE){
glColor3fv(drawingcolor[RectangleSegments[i]->color]);
glBegin(GL_LINE_LOOP);
glVertex2i(RectangleSegments[i]->v1.x, RectangleSegments[i]->v1.y);
glVertex2i(RectangleSegments[i]->v2.x, RectangleSegments[i]->v1.y);
glVertex2i(RectangleSegments[i]->v2.x, RectangleSegments[i]->v2.y);
glVertex2i(RectangleSegments[i]->v1.x, RectangleSegments[i]->v2.y);
glEnd();

if (firstvert != NULL) {
glColor3fv(drawingcolor[currentcolor]);
glBegin(GL_POINTS);
glVertex2i(firstvert->x, firstvert->y);
glEnd();
}

if (secondvert != NULL) {
glColor3fv(drawingcolor[currentcolor]);
glBegin(GL_POINTS);
glVertex2i(secondvert->x, secondvert->y);
glEnd();
glEnable(GL_LINE_STIPPLE);
glBegin(GL_LINE_LOOP);
glVertex2i(firstvert->x, firstvert->y);
glVertex2i(secondvert->x, secondvert->y);
glEnd();
glDisable(GL_LINE_STIPPLE);
}
}
}
}

void keyboard(GLFWwindow *w, int key, int scancode, int action, int mods) {
if (action == GLFW_PRESS)
switch (key) {
case GLFW_KEY_R:
currentcolor = (currentcolor != RED)?RED:BLACK;
printf("Now drawing in %s\n", colorword[currentcolor]);
break;
case GLFW_KEY_G:
currentcolor = (currentcolor != GREEN)?GREEN:BLACK;
printf("Now drawing in %s\n", colorword[currentcolor]);
break;
case GLFW_KEY_B:
currentcolor = (currentcolor != BLUE)?BLUE:BLACK;
printf("Now drawing in %s\n", colorword[currentcolor]);
break;
case GLFW_KEY_ESCAPE:
case GLFW_KEY_Q:
printf("Exiting Program!\n");
glfwSetWindowShouldClose(w, GL_TRUE);
break;
case GLFW_KEY_C:
printf("Now clearing window!\n");
shapenum = 0; //clear shapes
for (int i = 0; i < MAXLINES; i++){
free(ShapeArray[i]);
}
break;
case GLFW_KEY_F:
printf("Fill mode selected\n");

break;
case GLFW_KEY_F1:
printf("Line mode selected\n");
NumVertex = 2; //Line mode
break;
case GLFW_KEY_F2:
printf("Triangle mode selected\n");
NumVertex = 3; //Triangle mode
break;
case GLFW_KEY_F3:
printf("Rectangle mode selected\n");
NumVertex = 4; //rectangle mode
break;
}
}

// Cursor motion callback. Used only when mousebutton is pressed
// for first vertex and not released

void cursor(GLFWwindow *w, GLdouble cursorx, GLdouble cursory) {
/* As the mouse moves, the second vertex is updated constantly. */
/* Free old copies of secondvert before updating */

currentx = (GLint)cursorx;
currenty = (GLint)cursory;

free(secondvert);
secondvert = make_vertex(currentx, winheight - currenty);
}

// Mouse button callback

void mouse(GLFWwindow *w, int button, int action, int mods) {
if (button == GLFW_MOUSE_BUTTON_LEFT) {
if (action == GLFW_PRESS) {
printf("%d\n",shapenum);
glfwGetCursorPos(w, &dx, &dy);
currentx = (GLint)dx;
currenty = (GLint)dy;
if (NumVertex == 2){
if (firstvert == NULL) {/* save first vertex and register cursor motion callback for rubberbanding effect */
firstvert = make_vertex(currentx, winheight - currenty);
glfwSetCursorPosCallback(w, cursor); // Set cursor motion callback
}

else /* save second vertex of segment */
secondvert = make_vertex(currentx, winheight - currenty);
}

else if (NumVertex == 3){
if (firstvert == NULL) {/* save first vertex and register cursor motion callback for rubberbanding effect */
firstvert = make_vertex(currentx, winheight - currenty);
//glfwSetCursorPosCallback(w, cursor); // Set cursor motion callback
}

else if (secondvert == NULL){/* save second vertex of segment */
secondvert = make_vertex(currentx, winheight - currenty);
//glfwSetCursorPosCallback(w, cursor);
}

else if (thirdvert == NULL){
thirdvert = make_vertex(currentx, winheight - currenty);
//glfwSetCursorPosCallback(w, cursor);
}
}
else if (NumVertex == 4){
if (firstvert == NULL) {/* save first vertex and register cursor motion callback for rubberbanding effect */
firstvert = make_vertex(currentx, winheight - currenty);
glfwSetCursorPosCallback(w, cursor); // Set cursor motion callback
}

else{/* save second vertex of segment */
secondvert = make_vertex(currentx, winheight - currenty);
}
}

} /* end mouse press action */

else { // -----------------------------------------------NEED TO WORK OUT-----------------
if (action == GLFW_RELEASE) {
glfwSetCursorPosCallback(w, NULL); /* When button is released, disable cursor motion callback */
if (NumVertex == 2){
if (secondvert != NULL) {
/* create a new line and put it in array (if size not exceeded). Set its color and id */
if (shapenum < MAXLINES) {
LineSegments[shapenum] = make_line(*firstvert, *secondvert);
LineSegments[shapenum]->color = currentcolor;
LineSegments[shapenum]->id = shapenum;
ShapeArray[shapenum]->id = LINE;
shapenum++;
firstvert = NULL;
secondvert = NULL;
}
else
printf("Maximum of %d reached. Cannot draw any more lines.\n", MAXLINES);
}
}
else if (NumVertex == 3){
if (thirdvert != NULL) {
if (shapenum < MAXLINES) {
TriangleSegments[shapenum] = make_triangle(*firstvert, *secondvert, *thirdvert);
TriangleSegments[shapenum]->color = currentcolor;
TriangleSegments[shapenum]->id = shapenum;
ShapeArray[shapenum]->id = TRIANGLE;
shapenum++;
firstvert = NULL;
secondvert = NULL;
thirdvert = NULL;
}
else
printf("Maximum of %d reached. Cannot draw any more lines.\n", MAXLINES);
}
}
else if (NumVertex == 4){
if (secondvert != NULL) {
if (shapenum < MAXLINES) {
RectangleSegments[shapenum] = make_rectangle(*firstvert, *secondvert);
RectangleSegments[shapenum]->color = currentcolor;
RectangleSegments[shapenum]->id = shapenum;
ShapeArray[shapenum]->id = RECTANGLE;
shapenum++;
firstvert = NULL;
secondvert = NULL;
}
else
printf("Maximum of %d reached. Cannot draw any more lines.\n", MAXLINES);
}
}
}
} /* end mouse release action */
} /* end left mouse click action */
}


int main(int argc, char** argv) {
GLFWwindow* window;
const GLubyte* renderer;
const GLubyte* version;

/* Initialize the library */
if (!glfwInit())
return -1;

/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(winwidth, winheight, "HW_1", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}

for (int i = 0; i < MAXLINES; i++){
ShapeArray[i] = malloc(sizeof *ShapeArray[i]);

}

/* Make the window's context current */
glfwMakeContextCurrent(window);

/* get version info */
renderer = glGetString (GL_RENDERER); /* get renderer string */
version = glGetString (GL_VERSION); /* version as a string */
printf ("Renderer: %s\n", renderer);
printf ("OpenGL version supported %s\n", version);

myInit();
glfwSetKeyCallback(window, keyboard); /* Callback functions */
glfwSetMouseButtonCallback(window, mouse);

/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
draw();

/* Swap front and back buffers */
glfwSwapBuffers(window);

/* Poll for and process events */
glfwPollEvents();
}

glfwTerminate();
return 0;
}

triseg.h

// struct for triangle segments
typedef struct triangle {
V2d v1;
V2d v2;
V2d v3;
int color;
int id;
} Tri;

Tri *make_triangle(V2d v1, V2d v2, V2d v3);

颜色.h

enum {BLACK, RED, GREEN, BLUE};

rectseg.h

// struct for rectangle segments
typedef struct rectangle {
V2d v1;
V2d v2;
V2d v3;
V2d v4;
int color;
int id;
} Rect;

Rect *make_rectangle(V2d v1, V2d v2, V2d v3, V2d v4);

线段.h

// struct for two dimensional vertex
typedef struct vertex2d {
int x;
int y;
} V2d;

// struct for line segments
typedef struct line {
V2d v1;
V2d v2;
int color;
int id;
} Ln;

V2d *make_vertex(int x, int y);
Ln *make_line(V2d v1, V2d v2);

最佳答案

您将 ShapeArray 创建为指针数组,

shapes *ShapeArray[MAXLINES];

但我没有看到任何代码,您实际为数组中的 shapes 分配内存。所以当你这样做时:

ShapeArray[shapenum]->id = LINE;

我怀疑您是通过 NULL 指针访问的。

也许你应该这样声明 ShapeArray:

shapes ShapeArray[MAXLINES];

然后像这样访问:

ShapeArray[shapenum].id = LINE;

或者只是为某处的shapes malloc 空间。

我还注意到您的 draw 函数似乎有点困惑。您目前使用 i 作为两个嵌套循环中的循环迭代器,这不会达到您的预期。

我认为内部循环不是必需的,所以如果我们只看函数的头部,你应该做更像这样的事情:

void draw(void){
// Clear screen ahead of drawing all shapes
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Loop over each shape.
for (int i = 0; i < shapenum; i++){
// Is THIS shape a LINE?
if (ShapeArray[i]->id == LINE) {
// It is! Lets draw ONE line shape.
glColor3fv(drawingcolor[LineSegments[i]->color]);
glBegin(GL_LINES);
glVertex2i(LineSegments[i]->v1.x, LineSegments[i]->v1.y);
glVertex2i(LineSegments[i]->v2.x, LineSegments[i]->v2.y);
glEnd();
}

// .... rest of function also needs fixing ...

关于c - 卡在交互式 openGL 程序中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39761224/

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