2016-01-04 2 views
-1

Я пишу небольшой игрушечный игровой движок, используя Tinyobjloader для загрузки файлов .obj. Я храню данные вершин и все, используя glm :: vecX, чтобы все упростилось.std :: vector <float> to std :: vector <glm::vecX> без копирования

Tinyobjloader дает мне std::vector<float>, когда я хочу std::vector<glm::vecX>. Как мне это сделать без копирования?

Чтобы быть ясным, a glm::vecX является простой структурой, содержащей, например, float членов x, y, z.

Я думал, что поскольку структуры могут вести себя как массивы, то std::move будет работать, но не повезло.

Спасибо!

Редактировать: Я знаю, что я был неясно об этом, извините. Я хотел бы либо переместить std::vector<float> в std::vector<glm::vecX>, либо передать его как std::vector<glm::vecX>&.

Копирование данных с использованием std::memcpy работает отлично, но оно копирует данные, которых я бы хотел избежать.

+1

Вы должны создать свою собственную функцию для достижения этой цели (это будет стоить вам 1 для) –

+0

Что такое определение 'glm :: vecX'? –

+1

Каковы типы членов 'x',' y' и 'z'? Какими должны быть соответствующие значения «float»? –

ответ

1

Возможно, может интерпретировать содержимое вектора как экземпляра структуры без копирования данных. Если вы можете гарантировать совместимость представления, то есть. Содержимое vector<float> выложено в память как последовательность значений поплавка, непосредственно следуя друг за другом (массив) без дополнительного заполнения, в то время как содержимое vector<glm::vecX> выложено в виде последовательности vecX. Таким образом, вам необходимо обеспечить следующие условия:

  • То, что glm::vecX - это точно размер X поплавков без прокладки. В зависимости от объявления структуры это может быть зависящим от платформы.
  • То, что содержимое vector<float> находится в правильной последовательности, то есть как [x1, y1, z1, x2, y2, z2, ...] для vec3 вместо [x1, x2, ..., xN, y1, y2 ...].

В этом случае, вы можете безопасно переосмысливать указатель данных вектора поплавка как указатель на массив vecX как в этом примере:

std::vector<float> myObjData = ...; 
auto nVecs = myObjData.size()/3; // You should check that there are no remainders! 
glm::vec3* vecs = reinterpret_cast<glm::vec3*>(myObjData.data()); 
std::cout << vecs[0]; // Use vecs[0..nVecs-1] 

Вы не можете, однако, благополучно перетолковывать вектор сам по себе как вектор glm :: vecX, даже не как const-вектор, поскольку количество элементов, хранящихся в векторе, может быть непротиворечивым после переинтерпретации.Это зависит от того, сохраняет ли vector<T> код число элементов непосредственно, или количество выделенных байт (а затем размер() делит на SizeOf (T)):

// Don't do this, the result of .size() and .end() may be wrong! 
const std::vector<glm::vec3>& bad = *reinterpret_cast<std::vector<glm::vec3>*>(&myObjData); 
bad[bad.size()-1].z = 0; // Potential BOOM! 

Большую часть времени, однако, не нужно передавать фактический вектор, так как большинство функций в стандартной библиотеке принимают диапазон контейнеров , который легко дать для массивов, подобных тому, который показан в первом примере. Таким образом, если вы хотите, чтобы отсортировать массив Vec3 на основе г позиции, а затем распечатать его вы могли бы сделать:

// nVecs and vecs from the first example 
std::sort(vecs, vecs+nVecs, // Sort by Z position 
    [](const glm::vec3& a, const glm::vec3& b) { return a.z < b.z; }); 
std::copy(vecs, vecs+nVecs, std::ostream_iterator<glm::vec3>(std::cout, "\n")); 
+0

Оооо, фантазия! Так как 'glm :: vecX' должен быть без padding (это точка glm). Теперь, конечно, как вы сказали, это может быть зависящим от платформы, поэтому я буду проверять это до его использования. [Проверьте это] (http://stackoverflow.com/questions/13571898/c-opengl-glm-and-struct-padding) и [это] (http://stackoverflow.com/questions/33058927/how-does -opengl-fill-buffers-and-read-them-back) для получения дополнительной информации об этом. – fordcars

0

Вкратце: Это, насколько мне известно, невозможно без копирования.

И, на мой взгляд, std::memcpy не имеет отношения к std::vector.

+0

Да, вы, вероятно, правы. – fordcars

Смежные вопросы