#define USE_OPENGL2 #ifdef USE_OPENGL2 #include "OpenGLWindow/SimpleOpenGL2App.h" typedef SimpleOpenGL2App SimpleOpenGLApp; #else #include "OpenGLWindow/SimpleOpenGL3App.h" typedef SimpleOpenGL3App SimpleOpenGLApp; #endif //USE_OPENGL2 #include "Bullet3Common/b3Quaternion.h" #include "Bullet3Common/b3CommandLineArgs.h" #include "assert.h" #include char* gVideoFileName = 0; char* gPngFileName = 0; static b3WheelCallback sOldWheelCB = 0; static b3ResizeCallback sOldResizeCB = 0; static b3MouseMoveCallback sOldMouseMoveCB = 0; static b3MouseButtonCallback sOldMouseButtonCB = 0; static b3KeyboardCallback sOldKeyboardCB = 0; //static b3RenderCallback sOldRenderCB = 0; float gWidth = 1024; float gHeight = 768; SimpleOpenGLApp* app = 0; float gMouseX = 0; float gMouseY = 0; float g_MouseWheel = 0.0f; int g_MousePressed[3] = {0}; int g_MousePressed2[3] = {0}; #define B3_USE_IMGUI #ifdef B3_USE_IMGUI #include "OpenGLWindow/OpenGLInclude.h" #include "ThirdPartyLibs/imgui/imgui.h" static GLuint g_FontTexture = 0; void ImGui_ImplBullet_CreateDeviceObjects() { { GLint err = glGetError(); assert(err == GL_NO_ERROR); } ImGuiIO& io = ImGui::GetIO(); unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. // Upload texture to graphics system GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGenTextures(1, &g_FontTexture); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } glBindTexture(GL_TEXTURE_2D, g_FontTexture); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // Store our identifier io.Fonts->TexID = (void*)(intptr_t)g_FontTexture; // Restore state glBindTexture(GL_TEXTURE_2D, last_texture); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } } void ImGui_ImplBullet_RenderDrawLists(ImDrawData* draw_data) { { GLint err = glGetError(); assert(err == GL_NO_ERROR); } glEnable(GL_COLOR_MATERIAL); // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x); int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y); if (fb_width == 0 || fb_height == 0) return; draw_data->ScaleClipRects(io.DisplayFramebufferScale); // We are using the OpenGL fixed pipeline to make the example code simpler to read! // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnable(GL_TEXTURE_2D); glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context { GLint err = glGetError(); assert(err == GL_NO_ERROR); } // Setup viewport, orthographic projection matrix glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } // Render command lists #define OFFSETOF(TYPE, ELEMENT) ((size_t) & (((TYPE*)0)->ELEMENT)) for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, pos))); glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, uv))); glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, col))); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer); } idx_buffer += pcmd->ElemCount; } } #undef OFFSETOF // Restore modified state glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } #endif //B3_USE_IMGUI void MyWheelCallback(float deltax, float deltay) { g_MouseWheel += deltax + deltay; if (sOldWheelCB) sOldWheelCB(deltax, deltay); } void MyResizeCallback(float width, float height) { gWidth = width; gHeight = height; if (sOldResizeCB) sOldResizeCB(width, height); } void MyMouseMoveCallback(float x, float y) { printf("Mouse Move: %f, %f\n", x, y); gMouseX = x; gMouseY = y; if (sOldMouseMoveCB) sOldMouseMoveCB(x, y); } void MyMouseButtonCallback(int button, int state, float x, float y) { gMouseX = x; gMouseY = y; { if (button >= 0 && button < 3) { if (state) { g_MousePressed[button] = state; } g_MousePressed2[button] = state; } } if (sOldMouseButtonCB) sOldMouseButtonCB(button, state, x, y); } void MyKeyboardCallback(int keycode, int state) { //keycodes are in examples/CommonInterfaces/CommonWindowInterface.h //for example B3G_ESCAPE for escape key //state == 1 for pressed, state == 0 for released. // use app->m_window->isModifiedPressed(...) to check for shift, escape and alt keys printf("MyKeyboardCallback received key:%c in state %d\n", keycode, state); if (sOldKeyboardCB) sOldKeyboardCB(keycode, state); } bool ImGui_ImplGlfw_Init() { #if 0 ImGuiIO& io = ImGui::GetIO(); io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; io.RenderDrawListsFn = ImGui_ImplGlfw_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; io.ClipboardUserData = g_Window; #ifdef _WIN32 io.ImeWindowHandle = glfwGetWin32Window(g_Window); #endif #endif return true; } int main(int argc, char* argv[]) { { b3CommandLineArgs myArgs(argc, argv); app = new SimpleOpenGLApp("SimpleOpenGLApp", gWidth, gHeight); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } ImGui::CreateContext(); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } app->m_renderer->getActiveCamera()->setCameraDistance(13); app->m_renderer->getActiveCamera()->setCameraPitch(0); app->m_renderer->getActiveCamera()->setCameraTargetPosition(0, 0, 0); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } sOldKeyboardCB = app->m_window->getKeyboardCallback(); app->m_window->setKeyboardCallback(MyKeyboardCallback); sOldMouseMoveCB = app->m_window->getMouseMoveCallback(); app->m_window->setMouseMoveCallback(MyMouseMoveCallback); sOldMouseButtonCB = app->m_window->getMouseButtonCallback(); app->m_window->setMouseButtonCallback(MyMouseButtonCallback); sOldWheelCB = app->m_window->getWheelCallback(); app->m_window->setWheelCallback(MyWheelCallback); sOldResizeCB = app->m_window->getResizeCallback(); app->m_window->setResizeCallback(MyResizeCallback); myArgs.GetCmdLineArgument("mp4_file", gVideoFileName); if (gVideoFileName) app->dumpFramesToVideo(gVideoFileName); myArgs.GetCmdLineArgument("png_file", gPngFileName); char fileName[1024]; int textureWidth = 128; int textureHeight = 128; unsigned char* image = new unsigned char[textureWidth * textureHeight * 4]; int textureHandle = app->m_renderer->registerTexture(image, textureWidth, textureHeight); int cubeIndex = app->registerCubeShape(1, 1, 1); b3Vector3 pos = b3MakeVector3(0, 0, 0); b3Quaternion orn(0, 0, 0, 1); b3Vector3 color = b3MakeVector3(1, 0, 0); b3Vector3 scaling = b3MakeVector3(1, 1, 1); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } app->m_renderer->registerGraphicsInstance(cubeIndex, pos, orn, color, scaling); app->m_renderer->writeTransforms(); { bool dark = false; ImGuiStyle& style = ImGui::GetStyle(); if (dark) { ImGui::StyleColorsDark(&style); } else { ImGui::StyleColorsLight(&style); } } { GLint err = glGetError(); assert(err == GL_NO_ERROR); } do { static int frameCount = 0; frameCount++; if (gPngFileName) { printf("gPngFileName=%s\n", gPngFileName); sprintf(fileName, "%s%d.png", gPngFileName, frameCount++); app->dumpNextFrameToPng(fileName); } { GLint err = glGetError(); assert(err == GL_NO_ERROR); } //update the texels of the texture using a simple pattern, animated using frame index for (int y = 0; y < textureHeight; ++y) { const int t = (y + frameCount) >> 4; unsigned char* pi = image + y * textureWidth * 3; for (int x = 0; x < textureWidth; ++x) { const int s = x >> 4; const unsigned char b = 180; unsigned char c = b + ((s + (t & 1)) & 1) * (255 - b); pi[0] = pi[1] = pi[2] = pi[3] = c; pi += 3; } } { GLint err = glGetError(); assert(err == GL_NO_ERROR); } app->m_renderer->activateTexture(textureHandle); app->m_renderer->updateTexture(textureHandle, image); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } //float color[4] = { 255, 1, 1, 1 }; //app->m_primRenderer->drawTexturedRect(100, 200, gWidth / 2 - 50, gHeight / 2 - 50, color, 0, 0, 1, 1, true); app->m_renderer->init(); app->m_renderer->updateCamera(1); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } app->m_renderer->renderScene(); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } //app->drawGrid(); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } char bla[1024]; sprintf(bla, "Simple test frame %d", frameCount); //app->drawText(bla, 10, 10); #ifdef B3_USE_IMGUI { bool show_test_window = true; bool show_another_window = false; ImVec4 clear_color = ImColor(114, 144, 154); // Start the frame ImGuiIO& io = ImGui::GetIO(); if (!g_FontTexture) ImGui_ImplBullet_CreateDeviceObjects(); io.DisplaySize = ImVec2((float)gWidth, (float)gHeight); io.DisplayFramebufferScale = ImVec2(gWidth > 0 ? ((float)1.) : 0, gHeight > 0 ? ((float)1.) : 0); io.DeltaTime = (float)(1.0f / 60.0f); io.MousePos = ImVec2((float)gMouseX, (float)gMouseY); io.RenderDrawListsFn = ImGui_ImplBullet_RenderDrawLists; for (int i = 0; i < 3; i++) { io.MouseDown[i] = g_MousePressed[i] | g_MousePressed2[i]; g_MousePressed[i] = false; } io.MouseWheel = g_MouseWheel; ImGui::NewFrame(); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } { {static float f = 0.0f; static int counter = 0; ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color //ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state ImGui::Checkbox("Another Window", &show_another_window); if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) counter++; ImGui::SameLine(); ImGui::Text("counter = %d", counter); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } } //ImGui::ShowTestWindow(); //ImGui::ShowMetricsWindow(); { GLint err = glGetError(); assert(err == GL_NO_ERROR); } #if 0 static float f = 0.0f; ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); #endif ImGui::Render(); } #endif //B3_USE_IMGUI { GLint err = glGetError(); assert(err == GL_NO_ERROR); } app->swapBuffer(); } while (!app->m_window->requestedExit()) ; ImGui::DestroyContext(); delete app; delete[] image; } return 0; }