1 
2 
3 #define USE_OPENGL2
4 #ifdef USE_OPENGL2
5 #include "OpenGLWindow/SimpleOpenGL2App.h"
6 typedef SimpleOpenGL2App SimpleOpenGLApp;
7 
8 #else
9 #include "OpenGLWindow/SimpleOpenGL3App.h"
10 typedef SimpleOpenGL3App SimpleOpenGLApp;
11 
12 #endif  //USE_OPENGL2
13 
14 #include "Bullet3Common/b3Quaternion.h"
15 #include "Bullet3Common/b3CommandLineArgs.h"
16 #include "assert.h"
17 #include <stdio.h>
18 
19 char* gVideoFileName = 0;
20 char* gPngFileName = 0;
21 
22 static b3WheelCallback sOldWheelCB = 0;
23 static b3ResizeCallback sOldResizeCB = 0;
24 static b3MouseMoveCallback sOldMouseMoveCB = 0;
25 static b3MouseButtonCallback sOldMouseButtonCB = 0;
26 static b3KeyboardCallback sOldKeyboardCB = 0;
27 //static b3RenderCallback sOldRenderCB = 0;
28 
29 float gWidth = 1024;
30 float gHeight = 768;
31 SimpleOpenGLApp* app = 0;
32 float gMouseX = 0;
33 float gMouseY = 0;
34 float g_MouseWheel = 0.0f;
35 int g_MousePressed[3] = {0};
36 int g_MousePressed2[3] = {0};
37 
38 #define B3_USE_IMGUI
39 #ifdef B3_USE_IMGUI
40 #include "OpenGLWindow/OpenGLInclude.h"
41 #include "ThirdPartyLibs/imgui/imgui.h"
42 static GLuint g_FontTexture = 0;
43 
ImGui_ImplBullet_CreateDeviceObjects()44 void ImGui_ImplBullet_CreateDeviceObjects()
45 {
46 	{
47 		GLint err = glGetError();
48 		assert(err == GL_NO_ERROR);
49 	}
50 
51 	ImGuiIO& io = ImGui::GetIO();
52 
53 	unsigned char* pixels;
54 	int width, height;
55 	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.
56 
57 	// Upload texture to graphics system
58 	GLint last_texture;
59 	glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
60 	glGenTextures(1, &g_FontTexture);
61 	{
62 		GLint err = glGetError();
63 		assert(err == GL_NO_ERROR);
64 	}
65 	glBindTexture(GL_TEXTURE_2D, g_FontTexture);
66 	{
67 		GLint err = glGetError();
68 		assert(err == GL_NO_ERROR);
69 	}
70 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
71 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
72 	{
73 		GLint err = glGetError();
74 		assert(err == GL_NO_ERROR);
75 	}
76 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
77 
78 	// Store our identifier
79 	io.Fonts->TexID = (void*)(intptr_t)g_FontTexture;
80 
81 	// Restore state
82 	glBindTexture(GL_TEXTURE_2D, last_texture);
83 
84 	{
85 		GLint err = glGetError();
86 		assert(err == GL_NO_ERROR);
87 	}
88 }
89 
ImGui_ImplBullet_RenderDrawLists(ImDrawData * draw_data)90 void ImGui_ImplBullet_RenderDrawLists(ImDrawData* draw_data)
91 {
92 	{
93 		GLint err = glGetError();
94 		assert(err == GL_NO_ERROR);
95 	}
96 
97 	glEnable(GL_COLOR_MATERIAL);
98 	// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
99 	ImGuiIO& io = ImGui::GetIO();
100 	int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
101 	int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
102 	if (fb_width == 0 || fb_height == 0)
103 		return;
104 	draw_data->ScaleClipRects(io.DisplayFramebufferScale);
105 
106 	// We are using the OpenGL fixed pipeline to make the example code simpler to read!
107 	// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
108 	GLint last_texture;
109 	glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
110 	GLint last_viewport[4];
111 	glGetIntegerv(GL_VIEWPORT, last_viewport);
112 	GLint last_scissor_box[4];
113 	glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
114 	glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
115 	glEnable(GL_BLEND);
116 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
117 	glDisable(GL_CULL_FACE);
118 	glDisable(GL_DEPTH_TEST);
119 	glEnable(GL_SCISSOR_TEST);
120 	glEnableClientState(GL_VERTEX_ARRAY);
121 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
122 	glEnableClientState(GL_COLOR_ARRAY);
123 	glEnable(GL_TEXTURE_2D);
124 	glUseProgram(0);  // You may want this if using this code in an OpenGL 3+ context
125 
126 	{
127 		GLint err = glGetError();
128 		assert(err == GL_NO_ERROR);
129 	}
130 
131 	// Setup viewport, orthographic projection matrix
132 	glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
133 	glMatrixMode(GL_PROJECTION);
134 	glPushMatrix();
135 	glLoadIdentity();
136 	glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f);
137 	glMatrixMode(GL_MODELVIEW);
138 	glPushMatrix();
139 	glLoadIdentity();
140 
141 	{
142 		GLint err = glGetError();
143 		assert(err == GL_NO_ERROR);
144 	}
145 
146 // Render command lists
147 #define OFFSETOF(TYPE, ELEMENT) ((size_t) & (((TYPE*)0)->ELEMENT))
148 	for (int n = 0; n < draw_data->CmdListsCount; n++)
149 	{
150 		const ImDrawList* cmd_list = draw_data->CmdLists[n];
151 		const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
152 		const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
153 		glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, pos)));
154 		glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, uv)));
155 		glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, col)));
156 
157 		for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
158 		{
159 			const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
160 			if (pcmd->UserCallback)
161 			{
162 				pcmd->UserCallback(cmd_list, pcmd);
163 			}
164 			else
165 			{
166 				glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
167 				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));
168 				glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
169 			}
170 			idx_buffer += pcmd->ElemCount;
171 		}
172 	}
173 #undef OFFSETOF
174 
175 	// Restore modified state
176 	glDisableClientState(GL_COLOR_ARRAY);
177 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
178 	glDisableClientState(GL_VERTEX_ARRAY);
179 	glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
180 	glMatrixMode(GL_MODELVIEW);
181 	glPopMatrix();
182 	glMatrixMode(GL_PROJECTION);
183 	glPopMatrix();
184 	glPopAttrib();
185 	glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
186 	glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
187 }
188 #endif  //B3_USE_IMGUI
189 
MyWheelCallback(float deltax,float deltay)190 void MyWheelCallback(float deltax, float deltay)
191 {
192 	g_MouseWheel += deltax + deltay;
193 	if (sOldWheelCB)
194 		sOldWheelCB(deltax, deltay);
195 }
MyResizeCallback(float width,float height)196 void MyResizeCallback(float width, float height)
197 {
198 	gWidth = width;
199 	gHeight = height;
200 
201 	if (sOldResizeCB)
202 		sOldResizeCB(width, height);
203 }
MyMouseMoveCallback(float x,float y)204 void MyMouseMoveCallback(float x, float y)
205 {
206 	printf("Mouse Move: %f, %f\n", x, y);
207 	gMouseX = x;
208 	gMouseY = y;
209 
210 	if (sOldMouseMoveCB)
211 		sOldMouseMoveCB(x, y);
212 }
MyMouseButtonCallback(int button,int state,float x,float y)213 void MyMouseButtonCallback(int button, int state, float x, float y)
214 {
215 	gMouseX = x;
216 	gMouseY = y;
217 	{
218 		if (button >= 0 && button < 3)
219 		{
220 			if (state)
221 			{
222 				g_MousePressed[button] = state;
223 			}
224 			g_MousePressed2[button] = state;
225 		}
226 	}
227 
228 	if (sOldMouseButtonCB)
229 		sOldMouseButtonCB(button, state, x, y);
230 }
231 
MyKeyboardCallback(int keycode,int state)232 void MyKeyboardCallback(int keycode, int state)
233 {
234 	//keycodes are in examples/CommonInterfaces/CommonWindowInterface.h
235 	//for example B3G_ESCAPE for escape key
236 	//state == 1 for pressed, state == 0 for released.
237 	// use app->m_window->isModifiedPressed(...) to check for shift, escape and alt keys
238 	printf("MyKeyboardCallback received key:%c in state %d\n", keycode, state);
239 	if (sOldKeyboardCB)
240 		sOldKeyboardCB(keycode, state);
241 }
242 
ImGui_ImplGlfw_Init()243 bool ImGui_ImplGlfw_Init()
244 {
245 #if 0
246     ImGuiIO& io = ImGui::GetIO();
247     io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB;                     // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
248     io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
249     io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
250     io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
251     io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN;
252     io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP;
253     io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
254     io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
255     io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
256     io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
257     io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
258     io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER;
259     io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE;
260     io.KeyMap[ImGuiKey_A] = GLFW_KEY_A;
261     io.KeyMap[ImGuiKey_C] = GLFW_KEY_C;
262     io.KeyMap[ImGuiKey_V] = GLFW_KEY_V;
263     io.KeyMap[ImGuiKey_X] = GLFW_KEY_X;
264     io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y;
265     io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z;
266 
267     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.
268     io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
269     io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
270     io.ClipboardUserData = g_Window;
271 #ifdef _WIN32
272     io.ImeWindowHandle = glfwGetWin32Window(g_Window);
273 #endif
274 
275 #endif
276 
277 	return true;
278 }
279 
main(int argc,char * argv[])280 int main(int argc, char* argv[])
281 {
282 	{
283 		b3CommandLineArgs myArgs(argc, argv);
284 
285 		app = new SimpleOpenGLApp("SimpleOpenGLApp", gWidth, gHeight);
286 
287 		{
288 			GLint err = glGetError();
289 			assert(err == GL_NO_ERROR);
290 		}
291 
292 		ImGui::CreateContext();
293 
294 		{
295 			GLint err = glGetError();
296 			assert(err == GL_NO_ERROR);
297 		}
298 
299 		app->m_renderer->getActiveCamera()->setCameraDistance(13);
300 		app->m_renderer->getActiveCamera()->setCameraPitch(0);
301 		app->m_renderer->getActiveCamera()->setCameraTargetPosition(0, 0, 0);
302 
303 		{
304 			GLint err = glGetError();
305 			assert(err == GL_NO_ERROR);
306 		}
307 
308 		sOldKeyboardCB = app->m_window->getKeyboardCallback();
309 		app->m_window->setKeyboardCallback(MyKeyboardCallback);
310 		sOldMouseMoveCB = app->m_window->getMouseMoveCallback();
311 		app->m_window->setMouseMoveCallback(MyMouseMoveCallback);
312 		sOldMouseButtonCB = app->m_window->getMouseButtonCallback();
313 		app->m_window->setMouseButtonCallback(MyMouseButtonCallback);
314 		sOldWheelCB = app->m_window->getWheelCallback();
315 		app->m_window->setWheelCallback(MyWheelCallback);
316 		sOldResizeCB = app->m_window->getResizeCallback();
317 		app->m_window->setResizeCallback(MyResizeCallback);
318 
319 		myArgs.GetCmdLineArgument("mp4_file", gVideoFileName);
320 		if (gVideoFileName)
321 			app->dumpFramesToVideo(gVideoFileName);
322 
323 		myArgs.GetCmdLineArgument("png_file", gPngFileName);
324 		char fileName[1024];
325 
326 		int textureWidth = 128;
327 		int textureHeight = 128;
328 
329 		unsigned char* image = new unsigned char[textureWidth * textureHeight * 4];
330 
331 		int textureHandle = app->m_renderer->registerTexture(image, textureWidth, textureHeight);
332 
333 		int cubeIndex = app->registerCubeShape(1, 1, 1);
334 
335 		b3Vector3 pos = b3MakeVector3(0, 0, 0);
336 		b3Quaternion orn(0, 0, 0, 1);
337 		b3Vector3 color = b3MakeVector3(1, 0, 0);
338 		b3Vector3 scaling = b3MakeVector3(1, 1, 1);
339 		{
340 			GLint err = glGetError();
341 			assert(err == GL_NO_ERROR);
342 		}
343 
344 		app->m_renderer->registerGraphicsInstance(cubeIndex, pos, orn, color, scaling);
345 		app->m_renderer->writeTransforms();
346 
347 		{
348 			bool dark = false;
349 			ImGuiStyle& style = ImGui::GetStyle();
350 			if (dark)
351 			{
352 				ImGui::StyleColorsDark(&style);
353 			}
354 			else
355 			{
356 				ImGui::StyleColorsLight(&style);
357 			}
358 		}
359 
360 		{
361 			GLint err = glGetError();
362 			assert(err == GL_NO_ERROR);
363 		}
364 		do
365 		{
366 			static int frameCount = 0;
367 			frameCount++;
368 			if (gPngFileName)
369 			{
370 				printf("gPngFileName=%s\n", gPngFileName);
371 
372 				sprintf(fileName, "%s%d.png", gPngFileName, frameCount++);
373 				app->dumpNextFrameToPng(fileName);
374 			}
375 
376 			{
377 				GLint err = glGetError();
378 				assert(err == GL_NO_ERROR);
379 			}
380 
381 			//update the texels of the texture using a simple pattern, animated using frame index
382 			for (int y = 0; y < textureHeight; ++y)
383 			{
384 				const int t = (y + frameCount) >> 4;
385 				unsigned char* pi = image + y * textureWidth * 3;
386 				for (int x = 0; x < textureWidth; ++x)
387 				{
388 					const int s = x >> 4;
389 					const unsigned char b = 180;
390 					unsigned char c = b + ((s + (t & 1)) & 1) * (255 - b);
391 					pi[0] = pi[1] = pi[2] = pi[3] = c;
392 					pi += 3;
393 				}
394 			}
395 
396 			{
397 				GLint err = glGetError();
398 				assert(err == GL_NO_ERROR);
399 			}
400 
401 			app->m_renderer->activateTexture(textureHandle);
402 			app->m_renderer->updateTexture(textureHandle, image);
403 
404 			{
405 				GLint err = glGetError();
406 				assert(err == GL_NO_ERROR);
407 			}
408 
409 			//float color[4] = { 255, 1, 1, 1 };
410 			//app->m_primRenderer->drawTexturedRect(100, 200, gWidth / 2 - 50, gHeight / 2 - 50, color, 0, 0, 1, 1, true);
411 
412 			app->m_renderer->init();
413 			app->m_renderer->updateCamera(1);
414 
415 			{
416 				GLint err = glGetError();
417 				assert(err == GL_NO_ERROR);
418 			}
419 
420 			app->m_renderer->renderScene();
421 			{
422 				GLint err = glGetError();
423 				assert(err == GL_NO_ERROR);
424 			}
425 			//app->drawGrid();
426 			{
427 				GLint err = glGetError();
428 				assert(err == GL_NO_ERROR);
429 			}
430 
431 			char bla[1024];
432 			sprintf(bla, "Simple test frame %d", frameCount);
433 
434 			//app->drawText(bla, 10, 10);
435 
436 #ifdef B3_USE_IMGUI
437 			{
438 				bool show_test_window = true;
439 				bool show_another_window = false;
440 				ImVec4 clear_color = ImColor(114, 144, 154);
441 
442 				// Start the frame
443 				ImGuiIO& io = ImGui::GetIO();
444 				if (!g_FontTexture)
445 					ImGui_ImplBullet_CreateDeviceObjects();
446 
447 				io.DisplaySize = ImVec2((float)gWidth, (float)gHeight);
448 				io.DisplayFramebufferScale = ImVec2(gWidth > 0 ? ((float)1.) : 0, gHeight > 0 ? ((float)1.) : 0);
449 				io.DeltaTime = (float)(1.0f / 60.0f);
450 				io.MousePos = ImVec2((float)gMouseX, (float)gMouseY);
451 				io.RenderDrawListsFn = ImGui_ImplBullet_RenderDrawLists;
452 
453 				for (int i = 0; i < 3; i++)
454 				{
455 					io.MouseDown[i] = g_MousePressed[i] | g_MousePressed2[i];
456 					g_MousePressed[i] = false;
457 				}
458 
459 				io.MouseWheel = g_MouseWheel;
460 
461 				ImGui::NewFrame();
462 
463 				{
464 					GLint err = glGetError();
465 					assert(err == GL_NO_ERROR);
466 				}
467 
468 				{
469 					{static float f = 0.0f;
470 				static int counter = 0;
471 				ImGui::Text("Hello, world!");                            // Display some text (you can use a format string too)
472 				ImGui::SliderFloat("float", &f, 0.0f, 1.0f);             // Edit 1 float using a slider from 0.0f to 1.0f
473 				ImGui::ColorEdit3("clear color", (float*)&clear_color);  // Edit 3 floats representing a color
474 
475 				//ImGui::Checkbox("Demo Window", &show_demo_window);      // Edit bools storing our windows open/close state
476 				ImGui::Checkbox("Another Window", &show_another_window);
477 
478 				if (ImGui::Button("Button"))  // Buttons return true when clicked (NB: most widgets return true when edited/activated)
479 					counter++;
480 				ImGui::SameLine();
481 				ImGui::Text("counter = %d", counter);
482 
483 				ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
484 			}
485 		}
486 		//ImGui::ShowTestWindow();
487 		//ImGui::ShowMetricsWindow();
488 		{
489 			GLint err = glGetError();
490 			assert(err == GL_NO_ERROR);
491 		}
492 
493 #if 0
494 				static float f = 0.0f;
495 				ImGui::Text("Hello, world!");
496 				ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
497 				ImGui::ColorEdit3("clear color", (float*)&clear_color);
498 				if (ImGui::Button("Test Window")) show_test_window ^= 1;
499 				if (ImGui::Button("Another Window")) show_another_window ^= 1;
500 				ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
501 #endif
502 		ImGui::Render();
503 	}
504 #endif  //B3_USE_IMGUI
505 
506 	{
507 		GLint err = glGetError();
508 		assert(err == GL_NO_ERROR);
509 	}
510 
511 	app->swapBuffer();
512 }
513 while (!app->m_window->requestedExit())
514 	;
515 
516 ImGui::DestroyContext();
517 
518 delete app;
519 
520 delete[] image;
521 }
522 return 0;
523 }
524