- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
每次尝试用鼠标输入两个顶点时,我都会崩溃。我最近改变了组织每个形状的方式,以确保新形状与旧形状重叠。
这个项目的想法是制作各种交互式 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/
在 OpenGL/ES 中,在实现渲染到纹理功能时,您必须小心,不要引起反馈循环(从正在写入的同一纹理中读取像素)。由于显而易见的原因,当您读取和写入纹理的相同像素时,行为是未定义的。但是,如果您正在
正如我们最终都知道的那样,规范是一回事,实现是另一回事。大多数错误是我们自己造成的,但有时情况并非如此。 我相信列出以下内容会很有用: GPU 驱动程序中当前已知的与最新版本的 OpenGL 和 GL
很难说出这里问的是什么。这个问题是模棱两可的、模糊的、不完整的、过于宽泛的或修辞的,无法以目前的形式得到合理的回答。为了帮助澄清这个问题以便可以重新打开它,visit the help center
我正在学习 OpenGL,非常想知道与显卡的交互如何。 我觉得了解它是如何在图形驱动程序中实现的,会让我了解 opengl 的完整内部结构(通过这个我可以知道哪些阶段/因素影响我对 opengl 性能
我正在尝试绘制到大于屏幕尺寸(即 320x480)的渲染缓冲区 (512x512)。 执行 glReadPixels 后,图像看起来是正确的,除非图像的尺寸超过屏幕尺寸——在本例中,超过 320 水平
我正在 Windows 中制作一个 3D 小行星游戏(使用 OpenGL 和 GLUT),您可以在其中穿过一堆障碍物在太空中移动并生存下来。我正在寻找一种方法来针对无聊的 bg 颜色选项设置图像背景。
如果我想要一个包含 100 个 10*10 像素 Sprite 的 Sprite 表,是否可以将它们全部排成一排来制作 1,000*10 像素纹理?还是 GPU 对不那么窄的纹理表现更好?这对性能有什
这个问题在这里已经有了答案: Rendering 2D sprites in a 3D world? (7 个答案) 关闭 6 年前。 我如何概念化让图像始终面对相机。我尝试将三角函数与 arcta
是否可以在 OpenGL 中增加缓冲区? 假设我想使用实例化渲染。每次在世界上生成一个新对象时,我都必须用实例化数据更新缓冲区。 在这种情况下,我有一个 3 个 float 的缓冲区 std::v
有人可以向我解释为什么下面的代码没有绘制任何东西,但如果我使用 GL_LINE_LOOP 它确实形成了一个闭环吗? glBegin(GL_POLYGON); for(int i = 0; i <= N
正如标题所说,OpenGL 中的渲染目标是什么?我对 OpenGL 很陌生,我看到的所有网站都让我很困惑。 它只是一个缓冲区,我在其中放置稍后将用于渲染的东西吗? 如果您能提供一个很好的引用来阅读它,
当使用 OpenGL 1.4 固定功能多纹理时,每个纹理阶段的输出在传递到下一个阶段之前是否都固定在 [0, 1]? spec说(第 153 页): If the value of TEXTURE_E
我比较了 2 个函数 openGL ES 和 openGL gvec4 texelFetchOffset(gsampler2DArray sampler, ivec3 P, int lod, ivec
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 10 年前。 Improve thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
那么当你调用opengl函数时,比如glDraw或者gLBufferData,是否会导致程序线程停止等待GL完成调用呢? 如果不是,那么 GL 如何处理调用像 glDraw 这样的重要函数,然后立即更
我正在尝试实现级联阴影贴图,当我想访问我的视锥体的每个分区的相应深度纹理时,我遇到了一个错误。 更具体地说,当我想选择正确的阴影纹理时会出现我的问题,如果我尝试下面的代码,我会得到一个像 this 中
我想为OpenGL ES和OpenGL(Windows)使用相同的着色器源。为此,我想定义自定义数据类型并仅使用OpenGL ES函数。 一种方法是定义: #define highp #define
我尝试用 6 个位图映射立方体以实现天空盒效果。我的问题是一个纹理映射到立方体的每个面。我已经检查了 gDEBugger,在立方体纹理内存中我只有一个 图像(因为我尝试加载六个图像)。 代码准备纹理:
在 OpenGL 中偏移深度的最佳方法是什么?我目前每个多边形都有索引顶点属性,我将其传递给 OpenGL 中的顶点着色器。我的目标是在深度上偏移多边形,其中最高索引始终位于较低索引的前面。我目前有这
我是一名优秀的程序员,十分优秀!