Я недавно реализовал интерфейс btIDebugDraw из библиотеки движка пули, я использую C ++.
Когда я запускаю приложение, ничего не рисуется, ни одна линия. Затем я вставил несколько вызовов печати в стандартный вывод, чтобы проверить, был ли вызван метод drawLine, и, как ни странно, его никогда не вызывают.
Единственный вызываемый метод - это draw3dText ... и я даже не хочу чтобы сделать это сейчас.
Что не так с моим кодом? PS: я протестировал свою функцию drawLine вне класса, и она работает.
Вот код:
Реализация btIDebugDraw
#include "debugDraw.hpp"
DebugDraw::DebugDraw() :
debug_mode(btIDebugDraw::DBG_DrawWireframe),
line_shader("../shaders/line/vertex.glsl", "../shaders/line/fragment.glsl", "../shaders/line/geometry.glsl")
{
// line VAO and VBO
glGenVertexArrays(1, &line_VAO);
glBindVertexArray(line_VAO);
glGenBuffers(1, &line_VBO);
glBindBuffer(GL_ARRAY_BUFFER, line_VBO);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), nullptr, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
std::cout << "debug draw constructor" << std::endl;
}
void DebugDraw::drawLine(const btVector3 & from, const btVector3 & to, const btVector3 & color)
{
line_shader.use();
float vertices[] = {from.x(), from.y(), from.z(), to.x(), to.y(), to.z()};
glBindVertexArray(line_VAO);
glBindBuffer(GL_ARRAY_BUFFER, line_VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glDrawArrays(GL_LINES, 0, 2);
glBindVertexArray(0);
std::cout << "draw line" << std::endl;
}
void DebugDraw::drawContactPoint(const btVector3 & PointOnB, const btVector3 & normalOnB, btScalar distance, int lifeTime, const btVector3 & color)
{
std::cout << "draw contact point" << std::endl;
}
void DebugDraw::reportErrorWarning(const char * warningString)
{
std::cout << "-=-=-=- Debug Draw ERROR -=-=-=-" << std::endl;
std::cout << warningString << std::endl;
std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-" << std::endl;
}
void DebugDraw::draw3dText(const btVector3 & location, const char * textString)
{
std::cout << "draw 3d text" << std::endl;
}
void DebugDraw::setDebugMode(int debugMode)
{
std::cout << "set debug mode" << std::endl;
debug_mode = debugMode;
}
int DebugDraw::getDebugMode() const { return debug_mode; }
main
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include "object.hpp"
#include "mesh.hpp"
#include "shader.hpp"
#include "camera.hpp"
#include "debugDraw.hpp"
#include <iostream>
#include <cmath>
#include <omp.h>
#include <string>
#include <btBulletDynamicsCommon.h>
/*
#include <BulletCollision/BroadphaseCollision/btDispatcher.h>
#include <btGImpactCollisionAlgorithm.h>
#include <btGImpactShape.h>
*/
#define SCREEN_W 1560
#define SCREEN_H 780
// -----global-----
struct UserActions user_actions;
bool app = true;
// -----prototypes-----
SDL_Window* createWindow(int w, int h, const std::string & title);
void check_events(SDL_Event& event, const Uint8* keyboardState, Uint32& mouseButtonBitMask, int& mouseX_rel, int& mouseY_rel);
glm::mat4 bullet2glmMatrix(btScalar* matrix);
void draw_line(glm::vec3 from, glm::vec3 to, Shader & shader, GLuint & lineVAO, GLuint & lineVBO);
// -----functions-----
SDL_Window* createWindow(int w, int h, const std::string & title)
{
SDL_Window* window = nullptr;
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cerr << SDL_GetError() << std::endl;
return nullptr;
}
// OpenGL Version
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
// Double Buffer
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if(window == nullptr)
{
std::cerr << SDL_GetError() << std::endl;
return nullptr;
}
return window;
}
void check_events(SDL_Event& event, const Uint8* keyboardState, Uint32& mouseButtonBitMask, int& mouseX_rel, int& mouseY_rel)
{
keyboardState = SDL_GetKeyboardState(nullptr);
mouseButtonBitMask = SDL_GetRelativeMouseState(&mouseX_rel, &mouseY_rel);
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
app = false;
}
if(event.type == SDL_MOUSEWHEEL)
{
user_actions.mouse_scroll = true;
user_actions.scroll_direction = event.wheel.y;
}
else
{
user_actions.mouse_scroll = false;
user_actions.scroll_direction = 0;
}
if(event.type == SDL_MOUSEMOTION)
{
user_actions.mouseX = event.motion.x;
user_actions.mouseY = event.motion.y;
}
}
if(SDL_BUTTON(mouseButtonBitMask) == SDL_BUTTON_MIDDLE)
{
user_actions.xRel = mouseX_rel;
user_actions.yRel = mouseY_rel;
user_actions.mouse_middle = true;
}
else
{
user_actions.xRel = 0;
user_actions.yRel = 0;
user_actions.mouse_middle = false;
}
if(SDL_BUTTON(mouseButtonBitMask) == SDL_BUTTON_LEFT)
user_actions.mouse_left = true;
else
user_actions.mouse_left = false;
if(keyboardState[SDL_SCANCODE_LSHIFT])
user_actions.key_shift = true;
else
user_actions.key_shift = false;
if(keyboardState[SDL_SCANCODE_DOWN])
user_actions.key_down = true;
else
user_actions.key_down = false;
if(keyboardState[SDL_SCANCODE_UP])
user_actions.key_up = true;
else
user_actions.key_up = false;
if(keyboardState[SDL_SCANCODE_LEFT])
user_actions.key_left = true;
else
user_actions.key_left = false;
if(keyboardState[SDL_SCANCODE_RIGHT])
user_actions.key_right = true;
else
user_actions.key_right = false;
}
glm::mat4 bullet2glmMatrix(btScalar* matrix)
{
return glm::mat4(
matrix[0], matrix[1], matrix[2], matrix[3],
matrix[4], matrix[5], matrix[6], matrix[7],
matrix[8], matrix[9], matrix[10], matrix[11],
matrix[12], matrix[13], matrix[14], matrix[15]);
}
void draw_line(glm::vec3 from, glm::vec3 to, Shader & shader, GLuint & lineVAO, GLuint & lineVBO)
{
shader.use();
float vertices[] = {from.x, from.y, from.z, to.x, to.y, to.z};
glBindVertexArray(lineVAO);
glBindBuffer(GL_ARRAY_BUFFER, lineVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glDrawArrays(GL_LINES, 0, 2);
glBindVertexArray(0);
}
// -----main-----
int main(int argc, char* argv[])
{
// create an opengl window
SDL_Window * window = createWindow(SCREEN_W, SCREEN_H, "test bullet-physics");
// create OpenGL context
SDL_GLContext glContext = SDL_GL_CreateContext(window);
// Glew init
glewExperimental = true;
GLenum err = glewInit();
if(err != GLEW_OK)
{
std::cerr << glewGetErrorString(err) << std::endl;
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
SDL_Quit();
std::exit(-1);
}
// OpenGL states
glViewport(0, 0, SCREEN_W, SCREEN_H);
glEnable(GL_DEPTH_TEST);
glLineWidth(2.5f);
SDL_GL_SetSwapInterval(1);
// lineVAO and lineVBO
GLuint lineVAO, lineVBO;
glGenVertexArrays(1, &lineVAO);
glBindVertexArray(lineVAO);
glGenBuffers(1, &lineVBO);
glBindBuffer(GL_ARRAY_BUFFER, lineVBO);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), nullptr, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// create camera
Camera* cam = new Camera(60.0f, SCREEN_W, SCREEN_H);
// sunshine
glm::vec3 sun_dir(1.0f, -1.0f, 1.0f);
glm::vec3 sun_color(1.0, 1.0, 1.0);
// line shader
Shader* line_shader = new Shader("../shaders/line/vertex.glsl", "../shaders/line/fragment.glsl", "../shaders/line/geometry.glsl");
line_shader->use();
line_shader->set_Matrix("model", glm::mat4(1.0f));
// basic shader
Shader* basic = new Shader("../shaders/vertex.glsl", "../shaders/fragment.glsl", "../shaders/geometry.glsl");
basic->use();
basic->set_Matrix("model", glm::mat4(1.0f));
basic->set_Matrix("view", cam->get_view());
basic->set_Matrix("proj", cam->get_projection());
basic->set_vec3f("sun.dir", sun_dir);
basic->set_vec3f("sun.color", sun_color);
// load ground
Object* ground = new Object("../assets/ground.obj", true);
// load suzy
Object* suzy = new Object("../assets/suzanne.obj", true);
// ----- bullet initialization start -----
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
dynamicsWorld->setGravity(btVector3(0, -10, 0));
btIDebugDraw * debug = new DebugDraw();
dynamicsWorld->setDebugDrawer(debug);
//btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher);
// ----- bullet initialization end -----
// array of rigid bodies
btAlignedObjectArray<btCollisionShape*> collisionShapes;
// ----- ground static rigid body
{
std::vector<Mesh*> meshes = ground->get_mesh_collection();
for(int i = 0; i < meshes.size(); i++)
{
Mesh* m = meshes.at(i);
const std::vector<Vertex> & vertices = m->get_vertex_list();
const std::vector<int> & indices = m->get_index_list();
btTriangleMesh* striding_interface = new btTriangleMesh();
for(int j = 0; j < indices.size(); j += 3)
{
btVector3 v0(vertices.at(indices.at(j)).position.x, vertices.at(indices.at(j)).position.y, vertices.at(indices.at(j)).position.z);
btVector3 v1(vertices.at(indices.at(j+1)).position.x, vertices.at(indices.at(j+1)).position.y, vertices.at(indices.at(j+1)).position.z);
btVector3 v2(vertices.at(indices.at(j+2)).position.x, vertices.at(indices.at(j+2)).position.y, vertices.at(indices.at(j+2)).position.z);
striding_interface->addTriangle(v0, v1, v2, true);
}
//btCollisionShape* groundShape = new btGImpactMeshShape(striding_interface);
btCollisionShape* groundShape = new btBvhTriangleMeshShape(striding_interface, true);
collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0, 0, 0));
btScalar mass(0.0);
btVector3 localInertia(0, 0, 0);
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, groundShape, localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
// add the body to the dynamics world
dynamicsWorld->addRigidBody(body);
}
}
// suzy dynamic rigid body
{
std::vector<Mesh*> meshes = suzy->get_mesh_collection();
for(int i = 0; i < meshes.size(); i++)
{
Mesh* m = meshes.at(i);
const std::vector<Vertex> & vertices = m->get_vertex_list();
const std::vector<int> & indices = m->get_index_list();
btTriangleMesh* striding_interface = new btTriangleMesh();
for(int j = 0; j < indices.size(); j += 3)
{
btVector3 v0(vertices.at(indices.at(j)).position.x, vertices.at(indices.at(j)).position.y, vertices.at(indices.at(j)).position.z);
btVector3 v1(vertices.at(indices.at(j+1)).position.x, vertices.at(indices.at(j+1)).position.y, vertices.at(indices.at(j+1)).position.z);
btVector3 v2(vertices.at(indices.at(j+2)).position.x, vertices.at(indices.at(j+2)).position.y, vertices.at(indices.at(j+2)).position.z);
striding_interface->addTriangle(v0, v1, v2, true);
}
//btCollisionShape* suzyShape = new btGImpactMeshShape(striding_interface);
btCollisionShape* suzyShape = new btBvhTriangleMeshShape(striding_interface, true);
collisionShapes.push_back(suzyShape);
btTransform suzyTransform;
suzyTransform.setIdentity();
suzyTransform.setOrigin(btVector3(0, 0, 0));
btScalar mass(1.0);
btVector3 localInertia(0, 0, 0);
suzyShape->calculateLocalInertia(mass, localInertia);
btDefaultMotionState* myMotionState = new btDefaultMotionState(suzyTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, suzyShape, localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
// add the body to the dynamics world
dynamicsWorld->addRigidBody(body);
}
}
// main loop
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
SDL_Event event;
const Uint8 * keyboardState = nullptr;
Uint32 mouseButtonBitMask;
int mouseX_rel = 0, mouseY_rel = 0;
double delta = 0.0;
double current_time = 0.0;
double last_time = 0.0;
while(app)
{
// compute delta
last_time = current_time;
current_time = omp_get_wtime();
delta = current_time - last_time;
// update camera data
check_events(event, keyboardState, mouseButtonBitMask, mouseX_rel, mouseY_rel);
cam->update_view(user_actions, delta);
// clear screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// physics simulations
dynamicsWorld->stepSimulation(1.0f/60.0f, 10);
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[1];
btRigidBody* body = btRigidBody::upcast(obj);
btTransform trans;
if(body && body->getMotionState())
body->getMotionState()->getWorldTransform(trans);
else
trans = obj->getWorldTransform();
btScalar matrix[16];
trans.getOpenGLMatrix(matrix);
glm::mat4 bullet_model = bullet2glmMatrix(matrix);
// draw
/*
basic->use();
basic->set_Matrix("model", glm::mat4(1.0f));
basic->set_Matrix("view", cam->get_view());
basic->set_Matrix("proj", cam->get_projection());
ground->draw(*basic);
basic->set_Matrix("model", bullet_model);
suzy->draw(*basic);
// draw some lines
line_shader->use();
line_shader->set_Matrix("view", cam->get_view());
line_shader->set_Matrix("proj", cam->get_projection());
draw_line(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 25.0f, 0.0f), *line_shader, lineVAO, lineVBO);
draw_line(glm::vec3(0.0f, 25.0f, 0.0f), glm::vec3(25.0f, 25.0f, 0.0f), *line_shader, lineVAO, lineVBO);
draw_line(glm::vec3(25.0f, 25.0f, 0.0f), glm::vec3(25.0f, 0.0f, 0.0f), *line_shader, lineVAO, lineVBO);
*/
// debug draw
dynamicsWorld->debugDrawWorld();
SDL_GL_SwapWindow(window);
}
// clean
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Спасибо!