Как реализовать интерфейс btIDebugDraw Bullet в OpenGL 4.0

Bullet имеет реализацию интерфейса btIDebugDraw в старом OpenGL, который используется для рисования физического мира для отладки. Интерфейс такой:

class GLDebugDrawer : public btIDebugDraw
{
int m_debugMode;

public:

GLDebugDrawer();
virtual ~GLDebugDrawer(); 

virtual void    drawLine(const btVector3& from,const btVector3& to,const btVector3&  fromColor, const btVector3& toColor);

virtual void    drawLine(const btVector3& from,const btVector3& to,const btVector3& color);

virtual void    drawSphere (const btVector3& p, btScalar radius, const btVector3& color);

virtual void    drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha);

virtual void    drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color);

virtual void    reportErrorWarning(const char* warningString);

virtual void    draw3dText(const btVector3& location,const char* textString);

virtual void    setDebugMode(int debugMode);

virtual int     getDebugMode() const { return m_debugMode;}

};

Реализация OpenGL 1.1 работает в непосредственном режиме, отправляя вершины на GPU при каждом вызове функции. например. вот DrawLine()

void    GLDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& fromColor, const btVector3& toColor)
{

    glBegin(GL_LINES);
        glColor3f(fromColor.getX(), fromColor.getY(), fromColor.getZ());
        glVertex3d(from.getX(), from.getY(), from.getZ());
        glColor3f(toColor.getX(), toColor.getY(), toColor.getZ());
        glVertex3d(to.getX(), to.getY(), to.getZ());
    glEnd();
}

Чтобы преобразовать это в OpenGL 4.0, я думаю об использовании объекта массива вершин, определенного как член этого класса, скажем, mVAO и VBO также будут членами. Я настрою VAO в ctor GLDebugDrawer, а затем сгенерирую и отправлю вершины в VBO, а также отрисую их в drawLine().

drawLine()
{
    // Update buffers
    // Bind and render the buffer
}

Но поскольку я буду отправлять вершины каждый раз, когда вызывается drawLine(), кажется, что я не использую мощь VAO, а вместо этого довольно плохо имитирую немедленный режим!

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

Я хочу использовать этот код в своем приложении для Android позже, чтобы проверить свою физику, поэтому я переписываю интерфейс в OpenGL 4.0, который, как я полагаю, будет легче преобразовать в openGLES 2.0.

Я думал о записи вершин в векторе при каждом вызове drawLine(), а затем обновлении VBO после завершения всех вызовов Bullet функций btIDebugDraw. Тогда мне не нужно было бы периодически отправлять пары вершин на GPU, поскольку Bullet вызывает функции btIDebugDraw.

У меня есть некоторая информация об управлении данными вершин: noreferrer">http://developer.apple.com/library/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html


person safe_malloc    schedule 23.12.2012    source источник
comment
На самом деле нет хорошего способа сделать это, когда они дают вам вершины по одной и меняют каждый кадр. В любом случае это просто функция отладки, поэтому я бы просто продолжил имитировать немедленный режим, как вы, и отключил режим отладки, за исключением случаев, когда он вам нужен для отладки.   -  person Tim    schedule 23.12.2012
comment
Спасибо, тогда я постараюсь оптимизировать его, собрав точки в структуре данных и выполнив всего 1 вызов обновления VBO.   -  person safe_malloc    schedule 23.12.2012
comment
@safe_malloc Я также пытаюсь реализовать это в OpenGL 4.4. В моей функции drawLine я собираю все вершины from и to в std::vector. Затем передайте этот вектор в VBO, и в моей функции рендеринга я рисую, используя GL_LINES. Перед следующим шагом Simulation() я очищаю свою векторную структуру и VBO. Но мой код выглядит не так, как должен. Вы сделали свой код общедоступным где-нибудь, например, на GitHub и т. д. Это было бы полезно.   -  person Manmohan Bishnoi    schedule 21.08.2014


Ответы (1)


Не рисуйте сразу на drawLine(). :)
Вместо этого поместите Вершины/Цвета в буфер в Хосте/ОЗУ.

После вызова dynamicsWorld->debugDrawWorld() вы знаете, что ваш DebugDrawer получил все строки для кадра, поэтому вы можете сделать:

  1. обновить VBO один раз
  2. glDraw ...
  3. очистить буфер хоста
person paroj    schedule 01.04.2013
comment
Спасибо, да, именно так я сейчас и делаю. Таким образом, VBO обновляются при каждом вызове debugDrawWorld() или, я думаю, за кадр. Вероятно, я также могу уменьшить объем данных, отправляемых в VBO, выполнив сравнение вершин, чтобы найти измененные вершины и отправить только их. - person safe_malloc; 03.04.2013