Плоский массив из массива структур? - PullRequest
2 голосов
/ 18 апреля 2011

Привет, ребята. Спасибо за клик.

Это проблема, с которой я сталкиваюсь при кодировании OpenGL, но в целом это довольно общая проблема - так что ничего специфического для графики.

У меня есть структура (не класс, а просто структура), Particle.

typedef struct
{
    float x;
    float y;
    float z;
}float3;

typedef struct
{
   float3 position;
   float3 velocity;
   //...other stuff
}Particle;

И я работаю с кучей частиц (Particle * частиц []), но у меня есть функция, которая требует float * позиций, упакованных в порядке x, y, z.

Итак, краткое изложение моей проблемы:

Мои данные:

//I have this in a bunch of encapsulated structs
[... {1.0f, 2.0f, 3.0f,} ... {4.0f, 5.0f, 6.0f} ...]

//I want...
[1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f]

Моя проблема ... У меня уже есть все данные! Я не хочу снова использовать malloc / memcpy. Есть ли способ использовать данные, которые уже есть? Любая акробатика указателя C? Я также беспокоюсь о таких вещах, как выравнивание / заполнение.

(float3 - это структура, определенная в CUDA, если кому-то интересно).

Ответы [ 4 ]

6 голосов
/ 18 апреля 2011

glVertexAttribPointer имеет параметр stride, предназначенный именно для этой ситуации.

Обычно вы загружаете массив из Particle объектов в VBO, а затем, с привязкой к VBO:

glVertexAttribPointer(shader_arg_position, 3, GL_FLOAT, GL_FALSE, sizeof (Particle), offsetof(Particle, position));
0 голосов
/ 18 апреля 2011

Как насчет реинтерпретации приведения и большой осторожности здесь?

Particle* pP[];
// Fill your array of particles
// And now at your own risk (memory accesses and so on... :)
float* pF = reinterpret_cast<float*>(&pP[0]);
float x = pF[0];
float y = pF[1];
float z = pF[2];
pF = reinterpret_cast<float*>(&pP[1]);
// ..

Если у вас есть массив Particle *, но вы хотите работать с ним, как если бы это был массив позиций с плавающей точкой, выможно написать что-то вроде этого:

float getNthFloat(size_t n)
{
  size_t i = n / 3;
  size_t j = n % 3;
  float* pF = reinterpret_cast<float*>(&pP[i]);
  return pF[j];
}
// This would get 6th element in your virtual float array
// That is, second z position
size_t foo = 5;
float blah = getNthFloat(5);

И пойти еще дальше;Вы, вероятно, могли бы переписать это так, чтобы это выглядело как доступ к массиву вместо вызова функции.

0 голосов
/ 18 апреля 2011

Мое решение в большей степени ориентировано на C.

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

Просто сделайте float* index, чтобы указать наначало вашей векторной структуры, где вы держите все точки.Используя index, теперь вы можете проходить его как угодно, однако будьте осторожны, когда останавливаетесь с движением указателя.


Чтобы объяснить немного:

struct {
  float3 position;
  float3 velocity;
  float3 more_data;
} Particle;

Когда вы выделите эту структуру, память будет выглядеть так:

3 floats for position ||3 floats for velocity ||3 floats for whatever data

Возьмите float* по адресу position.x и увеличьте его через ваши частицы, учитывая, какие данные вы хотите обработать (положение, скорость и т. Д.).

Относительновыравнивание, это зависит от того, какое выравнивание вы хотите, чтобы ваша структура имела.

0 голосов
/ 18 апреля 2011

Идеальное решение - уволить любого, кто спроектировал float3, и заменить эту структуру простыми массивами по всем направлениям.

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

И еще одно решение:

typedef struct {
    float elem[3];
} float3;
#define x elem[0]
#define y elem[1]
#define z elem[2]

К сожалению, имена x, y и z могут быть проблематичными для определения в качестве макросов, подобных этому. Это одна из причин, по которой многие классические структуры C используют префиксные имена для элементов структуры, такие как st_dev, tv_sec, si_uid и т. Д. *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...