2013-06-29 2 views
1

Я использую Eigen3 2-мерный вектор в виде 2D точки для рисования OpenGL, сохраняя их в списке:указатель на `станд :: list` Эйгена DATAS

typedef Eigen::Vector2d Vec2D; 
std::list<Vec2D> points; 

Теперь мне нужен массив из GLfloat передать всю структуру данных необработанного поплавка значения координат в графическую карту:

glEnableClientState(GL_VERTEX_ARRAY); 
glEnableClientState(GL_COLOR_ARRAY); 

_vertex = new GLfloat[points.size()*2]; 
_colors = new GLfloat[points.size()*4]; 

std::list<Vec2D>::const_iterator it; 
int i=0, j=0; 
for(it=points.begin(); it!=points.end(); ++it) { 
    _vertex[i] = it->x()+2; 
    _vertex[i+1] = it->y()+2; 
    i+=2; 

    _colors[j] = getRed(j/4.0f, it); 
    _colors[j+1] = getGreen(j/4.0f, it); 
    _colors[j+2] = getBlue(j/4.0f, it); 
    _colors[j+3] = getAlpha(j/4.0f, it); 
    j+=4; 
} 

glColorPointer(4, GL_FLOAT, 0, _colors); 
glVertexPointer(2, GL_FLOAT, 0, _vertex); 
glDrawArrays(GL_LINE_STRIP, 0, points.size()); 

glDisableClientState(GL_VERTEX_ARRAY); 
glDisableClientState(GL_COLOR_ARRAY); 

delete _vertex; 
delete _colors; 

есть ли более ЭФФЕКТИВНЫЙ способ для создания массивов для передачи графических карт? например, пройти points.begin() и узнать, что такое смещение и не пропустить все точки?

Я имею в виду, что в памяти координаты x и y Eigen::Vector2d должны храниться в некотором последовательном пространстве .. так что я думаю, что могу передать его прямо на графическую карту .. но я не могу нестандартный как.

+0

Вам нужен пользовательский буфер gl? –

+0

что жаль? Мне нужно - из opengl документации 'glVertexPointer': __a указатель на первую координату первой вершины в массиве .__ – nkint

+0

Я также изменил название ответа, надеюсь немного более ясно – nkint

ответ

3

std :: list не хранит данные в смежной памяти, для этого нужен std :: vector (или std :: array, если вы знаете размер во время компиляции, но, вероятно, нет). Вектор имеет метод data(), который возвращает указатель на базовые данные. Однако, если вы храните внутренне Eigen :: vec2d, вы не можете передать его openGl, так как это динамическая структура, и ваши данные будут по всей вашей памяти. Вам нужна структура, которая хранит данные на месте (и btw более читабельна, чем vec2d, что в этом контексте является нечетным). Например:

struct VertexData 
{ 
    GLfloat x; 
    GLfloat y; 
    GLfloat red; 
    GLfloat green; 
    GLfloat blue; 
    GLfloat alpha;  
} 

И затем использовать glVertexPointer передать его OPENGL используя SizeOf (VertexData) в качестве шага

Для удаления new'ed массивов необходимо использовать

delete [] _vertex; 

нормальных удаляют, освободите только первый элемент. Или еще лучше, вы можете использовать смарт-указатели, станд :: unique_ptr будет лучше в этом случае

std::unique_ptr<GLfloat[]> _vertex(new GLfloat[points.size() * sizeof(GLfloat)]); 

Он будет автоматически освободить память, когда он выходит из области видимости (в конце блока)

+0

благодарю вас за ответ. но .. можете ли вы предоставить мне минимальный иллюстративный фрагмент для умного указателя или удаления? и как насчет собственной памяти? Я думаю, что у Vec2D probb есть некоторые проблемы ... как узнать это? – nkint

+1

Может быть, 'sizeof (Vec2D)! = 2 * sizeof (GLfloat)' действительно. Вы можете проверить это с помощью cout. Если это так, вам нужно использовать 'sizeof (Vec2D)' как 'stride' в ваших вызовах gl, иначе даже с' .data() 'это не сработает. –

+0

Vec2D, вероятно, динамичен, поэтому вы не можете просто передать кучу тех, что были в ogl. Я отредактировал свой ответ – aryjczyk

2

points - std::list, поэтому он не содержит непрерывного массива данных.

Если вы используете вместо этого std::vector, то в C++ 11 вы можете получить доступ к массиву, используемому внутренне с points.data(). Это значит, что вам больше не нужно _vertex.

Знайте, что, в качестве альтернативы, вы можете даже пойти дальше и иметь класс (с именем, например, Vertex), который содержит как положение вершины и ее цвет, а затем использовать метод data() на вашем std::vector<Vertex> в сочетании с glInterleavedArraysstride=sizeof(Vertex)).

+0

Почему бы не 'glDrawArrays'? это также позволяет мне указать смещение/шаг. Antway, thansk. Ваш голос должен использовать пользовательскую структуру вместо 'Eigen :: vector2d'. – nkint

+0

Да, вы можете добиться того же самого с помощью нескольких вызовов' glDrawArrays', я не хотел вникать в это, чтобы сохранить простой ответ. :) Честно говоря, пользовательская структура или нет, это действительно зависит от того, что вы хотите делать с цветами здесь. Однако попытайтесь избавиться от 'new/delete' в вашем коде, так или иначе, как сказал aryjczyk. В вашем примере вы могли бы, например, ввести массивы 2 _ .. как 'std :: vector ' или 'std :: unique_ptr ' вместо указателей '' GLfloat * '. –