Сжатое хранение данных атомарной модели для программы OpenGL - PullRequest
2 голосов
/ 17 февраля 2010

Я хочу иметь возможность хранить атомарную модель в программе OpenGL, которую я пишу. Ничего фантастического; только постоянные значения вершин сетки, хранящиеся как GLfloat[3], плюс простые текстуры. Я также хочу, чтобы модель могла свободно перемещаться и вращаться как один объект. Вот что у меня есть:

typedef struct _coordnode {
 GLfloat    *pts;           /* XYZ (vertex) or XY (texture) */
 struct _coordnode *next;
} coordnode;

typedef struct _facenode {
 GLfloat    *norm;          /* XYZ */
 coordnode  *vertices;      /* head of linked list */
 GLfloat    *color;         /* RGBA */
 coordnode  *textures;      /* head of linked list */
 struct _facenode *next;
} facenode;

typedef struct _model {
 GLenum     mode;
 facenode   *faces;         /* head of linked list */
 GLfloat    *rot;           /* delta-XYZ from Theta-origin */
 GLfloat    *rot_delta;     /* delta-delta-XYZ */
 GLfloat    *trans;         /* delta-XYZ from origin */
 GLfloat    *trans_delta;   /* delta-delta-XYZ from origin */
} model;

Это настраивается таким образом, что модель имеет связанные списки facenode, каждый из которых имеет два связанных списка своих вершин и координат текстуры соответственно.

Поскольку это моя первая программа на C, мой вопрос к опытным программистам заключается в том, представляет ли этот конкретный метод какие-либо несоответствия или неэффективность, или же он хранит достаточно данных.

Дополнительная информация, не обязательно соответствующая:

  • В памяти будет только несколько объектов, и два из них будут задействованы в обнаружении столкновений.
  • Одна модель будет иметь частичную прозрачность.
  • У одной модели будет рендеринг визуализированного текста, нанесенного на грани модели, и перемещение в соответствии с вектором силы тяжести.
  • Две модели будут вращаться как одна на основе внешнего ввода.

1 Ответ

2 голосов
/ 17 февраля 2010

Предполагая, что вы работаете с 32-битной архитектурой, и GLgloat является typedef'd для 32-битной плавающей запятой этой структуры

typedef struct _coordnode {
 GLfloat   *pts;            /* XYZ (vertex) or XY (texture) */
 struct _coordnode *next;
} coordnode;

будет использовать 8 байт памяти. Затем, если я правильно понимаю, pts будет указывать на отдельное выделение, которое будет иметь 2 или 3 GlFloats, что составляет 8 или 12 байтов памяти. это 16 или 20 байтов в двух распределениях. пока это

typedef struct _coordnode {
 GLfloat   pts[3];           /* XYZ (vertex) or XY (texture) */
 struct _coordnode *next;
} coordnode;

Всегда 16 байтов, плюс на одну точку отказа меньше, так как это одно выделение, а не два.

Так что, даже если ваш распределитель имеет нулевые накладные расходы (а это не так). Помещение 3-х GLfloats в координатный узел (даже если вы используете только 2 из них) занимает меньше памяти, чем массив GLfloat для отдельного размещения. Кроме того, если вы сделаете это единое распределение, вы получите лучшую согласованность кэша, что в большинстве случаев приводит к повышению производительности.

Такой же анализ может быть выполнен для других ваших структур.

Еще одна вещь, которую я бы сказал, это то, что если вы всегда ставите указатель next первым в каждой из ваших структур, то один набор функций связанных списков может обрабатывать все ваши списки, так что IMO это лучше

typedef struct _coordnode {
 struct _coordnode *next;
 GLfloat   pts[3];           /* XYZ (vertex) or XY (texture) */
} coordnode;

Если вы когда-нибудь перейдете на удвоение для GLFloat или перейдете на 64-битную архитектуру, ваши указатели больше не будут иметь такой же размер, как ваши GLFloat. В этом случае было бы лучше использовать память для группировки поплавков и указателей вместе.

typedef struct _facenode {
 struct _facenode *next;
 coordnode  *vertices;      /* head of linked list */
 coordnode  *textures;      /* head of linked list */
 GLfloat   *norm;           // XYZ (it might be better to make this an array)
 GLfloat   *color;          // RGBA (it might be better to make this an array)
} facenode;
...