我有一个基于OpenGL GLUT的C++程序(是的,我知道,GLUT很古老),它交替打印出一个蓝色矩形和一个红色正方形,位于GLUT窗口中用户单击鼠标的位置。这很好用。
然而,当我试图修改上面的程序,使上面提到的形状在初始动画后仍保留在画布上时,我遇到了令人难以置信的麻烦。
我创建了一个Shape类,它包含诸如顶点数量、颜色、坐标等信息。当程序一次只绘制一个形状时,该类似乎完全可用。
为了同时解决多个形状的问题,我创建了一个std::list<Shape>
链表。然而,当我通过std::list<Shape>::iterator
机制遍历链表时,对象似乎在内存中绑定在一起。也就是说,迭代为链表中的每个索引生成完全相同的形状对象、坐标等等。
我尝试了以下解决方案:
使链接列表为std::list<Shape*>
而不是std::list<Shape>
,
- 利用堆经由CCD_ 5进行对象分配
- 并将上述两种方法相结合
这是我的void display()
GLUT函数,以及相关的全局变量和类定义/声明:
class Shape
{
public:
Shape();
Shape(int, double[], int[]);
int type; //0 = rectangle, 1 = circle, 2 = triangle
int numVertices; //stores total number of vertices in the 2D object.
double* vertexArray; //a dynamic array that stores each vertex's (x, y)-coordinates in alternating successive indices
int* rgb; //an array that contains the 3 rgb values s.t. rgb = {r, g, b}
double* center; //an array that contains the (x, y)-coordinates of the shape's center on the 2d plane.
int velocity[2]; //a array of size 2 that holds the object's x-velocity in index 0 and the object's y-velocity in index 1
};
//default Shape constructor
Shape::Shape()
{
}
//Shape constructor
Shape::Shape(int shapeType, double vertices[], int color[]) //constructor for creating a stationary 2D shape
{
type = shapeType;
if (shapeType!=1) //as long as shape is NOT a circle, interpret the second constructor parameter as a list of vertices
{
vertexArray = vertices;
}
rgb = color;
if (shapeType==0) //shape is a rectangle
{
numVertices = 4;
}
else if(shapeType==1) //shape is a circle
{
//shape is a circle, therefore the second array param is in fact an array of size 2 containing the (x, y)-coordinates of the circle origin...
center = vertices;
}
else if (shapeType==2) //shape is a triangle
{
numVertices = 3;
}
}
std::list<Shape> shapeList;
void my_display(void)
{
/* clear the buffer */
glClear(GL_COLOR_BUFFER_BIT);
//altFlag is just a value to allow alternating between rectangles/circles being printed
if (altFlag==1)
{
printf("Drawing rectangle at: (%g, %g)n", my_x, my_y);
/*instantiate a Shape() object representing a blue rectangle*/
int rgbColor[3] = {0, 0, 1};
double vertices[4] = {my_x/window_w, my_y/window_h, my_x/window_w + my_rect_w, my_y/window_h + my_rect_h};
Shape my_rectangle(0, vertices, rgbColor); //uses constructor (shape type, list of vertex coordinates, length of coordinate list, color)
glColor3f((GLfloat)my_rectangle.rgb[0], (GLfloat)my_rectangle.rgb[1], (GLfloat)my_rectangle.rgb[2]) ; /* (Red, Green, Blue); so here we ask for Blue */
glRectf(my_rectangle.vertexArray[0], my_rectangle.vertexArray[1], my_rectangle.vertexArray[2], my_rectangle.vertexArray[3]); //call to function to draw a rectangle
altFlag=0;
shapeList.push_front(my_rectangle);
}
else
{
/*instantiate a Shape() object representing a red circle*/
int circleColor[3] = {1, 0, 0};
double circleCenter[2] = {(my_x), (my_y)}; //{center x coord, center y coord}
//Shape* my_circle = new Shape(1, circleCenter, circleColor);
Shape my_circle(1, circleCenter, circleColor);
glColor3f(my_circle.rgb[0], my_circle.rgb[1], my_circle.rgb[2]);
glCirclef(my_circle.center[0], my_circle.center[1]); //call to function to draw pseudocircle
altFlag=1;
shapeList.push_front(my_circle);
}
//iterate over shapeList, print out values of the rgb array.
for (std::list<Shape>::iterator iter = shapeList.begin(); iter != shapeList.end(); iter++)
{
printf("%d, %d, %dn", iter->rgb[0], iter->rgb[1], iter->rgb[2]);
}
glutSwapBuffers();
return;
虽然这是作业的一部分,但问题与所使用的语言有关,而不是作为课程重点的图形库。
Shape
的参数化构造函数可以执行以下操作:
vertexArray = vertices;
其中vertices
是声明为double vertices[]
的函数参数。这是double *vertices
的语法糖,即,您正在复制指针(因为数组在传递给函数时会衰减为指针)。
CCD_ 11被定义为类内部的指针。您甚至提到它是一个"动态数组",但随后您使用堆栈上分配的数组(display()
中的局部变量)对其进行初始化。这会使指针悬空。
您必须使vertexArray
成为一个数组并复制数据,而不仅仅是指针。类似这样的东西:
class Shape
{
// ...
double vertexArray[4];
// ...
};
Shape::Shape(int shapeType, double vertices[], int color[])
{
type = shapeType;
if (shapeType==0) //shape is a rectangle
{
numVertices = 4;
}
else if(shapeType==1) //shape is a circle
{
//shape is a circle, therefore the second array param is in fact an array of size 2 containing the (x, y)-coordinates of the circle origin...
center = vertices;
}
else if (shapeType==2) //shape is a triangle
{
numVertices = 3;
}
if (shapeType!=1) //as long as shape is NOT a circle, interpret the second constructor parameter as a list of vertices
{
std::copy(vertices, vertices + numVertices, vertexArray);
}
}
当然,与color
类似。
额外建议
当然,使用std::vector
或类似的代码会更好,而不是使用普通数组,使用和enum
而不是int
来表示shapeType
等。我建议您选择一本好的C++书。