1

ユーザーがマウスをクリックした GLUT ウィンドウ内のポイントにある、青い四角形と赤い四角形を交互に出力する OpenGL GLUT ベースの (はい、GLUT は古いものです) C++ プログラムがあります。これはうまくいっています。

ただし、上記のプログラムを変更して、最初のアニメーションの後に前述の形状がキャンバス上に残るようにしようとすると、気が遠くなるような問題が発生しました。

頂点の数、色、座標などの情報を保持する Shape クラスを作成しました。プログラムが一度に 1 つの図形だけを描画する場合、このクラスは完全に機能しているように見えます。

一度に複数の形状の問題を解決するために、std::list<Shape>リンクされたリストを作成しました。ただし、メカニズムを介してリンクされたリストを反復処理するとstd::list<Shape>::iterator、オブジェクトがメモリ内で結合されているように見えます。つまり、反復により、リンク リスト内の各インデックスに対して、まったく同じ形状オブジェクト、座標、およびすべてが生成されます。

次の解決策を試しました。

リンクされたリストを のstd::list<Shape*>代わりにstd::list<Shape>

  • Shape* my_shape = new Shape(params)を介してオブジェクトの割り当てにヒープを利用する
  • 上記の2つの方法を組み合わせます。

これは、関連するグローバル変数とクラス定義/宣言とともに、私の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, %d\n", iter->rgb[0], iter->rgb[1], iter->rgb[2]);
  }

  glutSwapBuffers();

  return;

これは課題の一部ですが、質問は、コースの焦点であるグラフィック ライブラリとは対照的に、使用されている言語に関するものです。

4

1 に答える 1

2

パラメータ化されたコンストラクターShapeはこれを行います:

vertexArray = vertices;

verticesとして宣言された関数パラメータはどこにありますかdouble vertices[]。これは へのシンタックス シュガーdouble *verticesです。つまり、ポインタをコピーしています(関数に渡されると、配列はポインタに崩壊するため)。

vertexArrayクラス内でポインタとして定義されています。「動的配列」であるとさえ述べていますが、スタックに割り当てられた配列( 内のローカル変数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、単純な配列の代わりに or に似たものを使用したり、 forenumの代わりにand を使用したりする方がはるかに優れています。良い C++ の本を手に取ることをお勧めします。intshapeType

于 2013-08-29T11:55:40.873 に答える