SimpleOpenGL3App.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  1. #ifndef NO_OPENGL3
  2. #include "SimpleOpenGL3App.h"
  3. #include "ShapeData.h"
  4. #ifdef __APPLE__
  5. #include "MacOpenGLWindow.h"
  6. #else
  7. #ifdef _WIN32
  8. #include "Win32OpenGLWindow.h"
  9. #else
  10. //let's cross the fingers it is Linux/X11
  11. #include "X11OpenGLWindow.h"
  12. #endif //_WIN32
  13. #endif//__APPLE__
  14. #include <stdio.h>
  15. #include "GLPrimitiveRenderer.h"
  16. #include "GLInstancingRenderer.h"
  17. #include "Bullet3Common/b3Vector3.h"
  18. #include "Bullet3Common/b3Logging.h"
  19. #include "fontstash.h"
  20. #include "TwFonts.h"
  21. #include "opengl_fontstashcallbacks.h"
  22. #include <assert.h>
  23. #include "GLRenderToTexture.h"
  24. #include "Bullet3Common/b3Quaternion.h"
  25. #ifdef _WIN32
  26. #define popen _popen
  27. #define pclose _pclose
  28. #endif // _WIN32
  29. struct SimpleInternalData
  30. {
  31. GLuint m_fontTextureId;
  32. GLuint m_largeFontTextureId;
  33. struct sth_stash* m_fontStash;
  34. OpenGL2RenderCallbacks* m_renderCallbacks;
  35. int m_droidRegular;
  36. const char* m_frameDumpPngFileName;
  37. FILE* m_ffmpegFile;
  38. GLRenderToTexture* m_renderTexture;
  39. void* m_userPointer;
  40. int m_upAxis;//y=1 or z=2 is supported
  41. };
  42. static SimpleOpenGL3App* gApp=0;
  43. static void SimpleResizeCallback( float widthf, float heightf)
  44. {
  45. int width = (int)widthf;
  46. int height = (int)heightf;
  47. if (gApp && gApp->m_instancingRenderer)
  48. gApp->m_instancingRenderer->resize(width,height);
  49. if (gApp && gApp->m_primRenderer)
  50. gApp->m_primRenderer->setScreenSize(width,height);
  51. }
  52. static void SimpleKeyboardCallback(int key, int state)
  53. {
  54. if (key==B3G_ESCAPE && gApp && gApp->m_window)
  55. {
  56. gApp->m_window->setRequestExit();
  57. } else
  58. {
  59. //gApp->defaultKeyboardCallback(key,state);
  60. }
  61. }
  62. void SimpleMouseButtonCallback( int button, int state, float x, float y)
  63. {
  64. gApp->defaultMouseButtonCallback(button,state,x,y);
  65. }
  66. void SimpleMouseMoveCallback( float x, float y)
  67. {
  68. gApp->defaultMouseMoveCallback(x,y);
  69. }
  70. void SimpleWheelCallback( float deltax, float deltay)
  71. {
  72. gApp->defaultWheelCallback(deltax,deltay);
  73. }
  74. static GLuint BindFont(const CTexFont *_Font)
  75. {
  76. GLuint TexID = 0;
  77. glGenTextures(1, &TexID);
  78. glBindTexture(GL_TEXTURE_2D, TexID);
  79. glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
  80. glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
  81. glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  82. glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  83. glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  84. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  85. glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, _Font->m_TexWidth, _Font->m_TexHeight, 0, GL_RED, GL_UNSIGNED_BYTE, _Font->m_TexBytes);
  86. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  87. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  88. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  89. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
  90. glBindTexture(GL_TEXTURE_2D, 0);
  91. return TexID;
  92. }
  93. extern unsigned char OpenSansData[];
  94. SimpleOpenGL3App::SimpleOpenGL3App( const char* title, int width,int height, bool allowRetina)
  95. {
  96. gApp = this;
  97. m_data = new SimpleInternalData;
  98. m_data->m_frameDumpPngFileName = 0;
  99. m_data->m_renderTexture = 0;
  100. m_data->m_ffmpegFile = 0;
  101. m_data->m_userPointer = 0;
  102. m_data->m_upAxis = 1;
  103. m_window = new b3gDefaultOpenGLWindow();
  104. m_window->setAllowRetina(allowRetina);
  105. b3gWindowConstructionInfo ci;
  106. ci.m_title = title;
  107. ci.m_width = width;
  108. ci.m_height = height;
  109. m_window->createWindow(ci);
  110. m_window->setWindowTitle(title);
  111. b3Assert(glGetError() ==GL_NO_ERROR);
  112. glClearColor( m_backgroundColorRGB[0],
  113. m_backgroundColorRGB[1],
  114. m_backgroundColorRGB[2],
  115. 1.f);
  116. m_window->startRendering();
  117. width = m_window->getWidth();
  118. height = m_window->getHeight();
  119. b3Assert(glGetError() ==GL_NO_ERROR);
  120. #ifndef __APPLE__
  121. #ifndef _WIN32
  122. //some Linux implementations need the 'glewExperimental' to be true
  123. glewExperimental = GL_TRUE;
  124. #endif
  125. if (glewInit() != GLEW_OK)
  126. exit(1); // or handle the error in a nicer way
  127. if (!GLEW_VERSION_2_1) // check that the machine supports the 2.1 API.
  128. exit(1); // or handle the error in a nicer way
  129. #endif
  130. glGetError();//don't remove this call, it is needed for Ubuntu
  131. b3Assert(glGetError() ==GL_NO_ERROR);
  132. m_parameterInterface = 0;
  133. b3Assert(glGetError() ==GL_NO_ERROR);
  134. m_instancingRenderer = new GLInstancingRenderer(128*1024,128*1024*1024);
  135. m_primRenderer = new GLPrimitiveRenderer(width,height);
  136. m_renderer = m_instancingRenderer ;
  137. m_window->setResizeCallback(SimpleResizeCallback);
  138. m_instancingRenderer->init();
  139. m_instancingRenderer->resize(width,height);
  140. m_primRenderer->setScreenSize(width,height);
  141. b3Assert(glGetError() ==GL_NO_ERROR);
  142. m_instancingRenderer->InitShaders();
  143. m_window->setMouseMoveCallback(SimpleMouseMoveCallback);
  144. m_window->setMouseButtonCallback(SimpleMouseButtonCallback);
  145. m_window->setKeyboardCallback(SimpleKeyboardCallback);
  146. m_window->setWheelCallback(SimpleWheelCallback);
  147. TwGenerateDefaultFonts();
  148. m_data->m_fontTextureId = BindFont(g_DefaultNormalFont);
  149. m_data->m_largeFontTextureId = BindFont(g_DefaultLargeFont);
  150. {
  151. m_data->m_renderCallbacks = new OpenGL2RenderCallbacks(m_primRenderer);
  152. m_data->m_fontStash = sth_create(512,512,m_data->m_renderCallbacks);//256,256);//,1024);//512,512);
  153. b3Assert(glGetError() ==GL_NO_ERROR);
  154. if (!m_data->m_fontStash)
  155. {
  156. b3Warning("Could not create stash");
  157. //fprintf(stderr, "Could not create stash.\n");
  158. }
  159. unsigned char* data2 = OpenSansData;
  160. unsigned char* data = (unsigned char*) data2;
  161. if (!(m_data->m_droidRegular = sth_add_font_from_memory(m_data->m_fontStash, data)))
  162. {
  163. b3Warning("error!\n");
  164. }
  165. b3Assert(glGetError() ==GL_NO_ERROR);
  166. }
  167. }
  168. struct sth_stash* SimpleOpenGL3App::getFontStash()
  169. {
  170. return m_data->m_fontStash;
  171. }
  172. void SimpleOpenGL3App::drawText3D( const char* txt, float worldPosX, float worldPosY, float worldPosZ, float size1)
  173. {
  174. B3_PROFILE("SimpleOpenGL3App::drawText3D");
  175. float viewMat[16];
  176. float projMat[16];
  177. CommonCameraInterface* cam = m_instancingRenderer->getActiveCamera();
  178. cam->getCameraViewMatrix(viewMat);
  179. cam->getCameraProjectionMatrix(projMat);
  180. float camPos[4];
  181. cam->getCameraPosition(camPos);
  182. //b3Vector3 cp= b3MakeVector3(camPos[0],camPos[2],camPos[1]);
  183. //b3Vector3 p = b3MakeVector3(worldPosX,worldPosY,worldPosZ);
  184. //float dist = (cp-p).length();
  185. //float dv = 0;//dist/1000.f;
  186. //
  187. //printf("str = %s\n",unicodeText);
  188. float dx=0;
  189. //int measureOnly=0;
  190. glEnable(GL_BLEND);
  191. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  192. int viewport[4]={0,0,m_instancingRenderer->getScreenWidth(),m_instancingRenderer->getScreenHeight()};
  193. float posX = 450.f;
  194. float posY = 100.f;
  195. float winx,winy, winz;
  196. if (!projectWorldCoordToScreen(worldPosX, worldPosY, worldPosZ,viewMat,projMat,viewport,&winx, &winy, &winz))
  197. {
  198. return;
  199. }
  200. posX = winx;
  201. posY = m_instancingRenderer->getScreenHeight()/2+(m_instancingRenderer->getScreenHeight()/2)-winy;
  202. if (0)//m_useTrueTypeFont)
  203. {
  204. bool measureOnly = false;
  205. float fontSize= 32;//64;//512;//128;
  206. sth_draw_text(m_data->m_fontStash,
  207. m_data->m_droidRegular,fontSize,posX,posY,
  208. txt,&dx, this->m_instancingRenderer->getScreenWidth(),this->m_instancingRenderer->getScreenHeight(),measureOnly,m_window->getRetinaScale());
  209. sth_end_draw(m_data->m_fontStash);
  210. sth_flush_draw(m_data->m_fontStash);
  211. } else
  212. {
  213. //float width = 0.f;
  214. int pos=0;
  215. //float color[]={0.2f,0.2,0.2f,1.f};
  216. glActiveTexture(GL_TEXTURE0);
  217. glBindTexture(GL_TEXTURE_2D,m_data->m_largeFontTextureId);
  218. //float width = r.x;
  219. //float extraSpacing = 0.;
  220. float startX = posX;
  221. float startY = posY-g_DefaultLargeFont->m_CharHeight*size1;
  222. while (txt[pos])
  223. {
  224. int c = txt[pos];
  225. //r.h = g_DefaultNormalFont->m_CharHeight;
  226. //r.w = g_DefaultNormalFont->m_CharWidth[c]+extraSpacing;
  227. float endX = startX+g_DefaultLargeFont->m_CharWidth[c]*size1;
  228. float endY = posY;
  229. float currentColor[]={1.f,0.2,0.2f,1.f};
  230. // m_primRenderer->drawTexturedRect(startX, startY, endX, endY, currentColor,g_DefaultLargeFont->m_CharU0[c],g_DefaultLargeFont->m_CharV0[c],g_DefaultLargeFont->m_CharU1[c],g_DefaultLargeFont->m_CharV1[c]);
  231. float u0 = g_DefaultLargeFont->m_CharU0[c];
  232. float u1 = g_DefaultLargeFont->m_CharU1[c];
  233. float v0 = g_DefaultLargeFont->m_CharV0[c];
  234. float v1 = g_DefaultLargeFont->m_CharV1[c];
  235. float color[4] = {currentColor[0],currentColor[1],currentColor[2],currentColor[3]};
  236. float x0 = startX;
  237. float x1 = endX;
  238. float y0 = startY;
  239. float y1 = endY;
  240. int screenWidth = m_instancingRenderer->getScreenWidth();
  241. int screenHeight = m_instancingRenderer->getScreenHeight();
  242. float z = 2.f*winz-1.f;//*(far
  243. float identity[16]={1,0,0,0,
  244. 0,1,0,0,
  245. 0,0,1,0,
  246. 0,0,0,1};
  247. PrimVertex vertexData[4] = {
  248. { PrimVec4(-1.f+2.f*x0/float(screenWidth), 1.f-2.f*y0/float(screenHeight), z, 1.f ), PrimVec4( color[0], color[1], color[2], color[3] ) ,PrimVec2(u0,v0)},
  249. { PrimVec4(-1.f+2.f*x0/float(screenWidth), 1.f-2.f*y1/float(screenHeight), z, 1.f ), PrimVec4( color[0], color[1], color[2], color[3] ) ,PrimVec2(u0,v1)},
  250. { PrimVec4( -1.f+2.f*x1/float(screenWidth), 1.f-2.f*y1/float(screenHeight), z, 1.f ), PrimVec4(color[0], color[1], color[2], color[3]) ,PrimVec2(u1,v1)},
  251. { PrimVec4( -1.f+2.f*x1/float(screenWidth), 1.f-2.f*y0/float(screenHeight), z, 1.f ), PrimVec4( color[0], color[1], color[2], color[3] ) ,PrimVec2(u1,v0)}
  252. };
  253. m_primRenderer->drawTexturedRect3D(vertexData[0],vertexData[1],vertexData[2],vertexData[3],identity,identity,false);
  254. //DrawTexturedRect(0,r,g_DefaultNormalFont->m_CharU0[c],g_DefaultNormalFont->m_CharV0[c],g_DefaultNormalFont->m_CharU1[c],g_DefaultNormalFont->m_CharV1[c]);
  255. // DrawFilledRect(r);
  256. startX = endX;
  257. //startY = endY;
  258. pos++;
  259. }
  260. glBindTexture(GL_TEXTURE_2D,0);
  261. }
  262. glDisable(GL_BLEND);
  263. }
  264. void SimpleOpenGL3App::drawText( const char* txt, int posXi, int posYi)
  265. {
  266. float posX = (float)posXi;
  267. float posY = (float) posYi;
  268. //
  269. //printf("str = %s\n",unicodeText);
  270. float dx=0;
  271. //int measureOnly=0;
  272. glEnable(GL_BLEND);
  273. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  274. if (1)//m_useTrueTypeFont)
  275. {
  276. bool measureOnly = false;
  277. float fontSize= 64;//512;//128;
  278. sth_draw_text(m_data->m_fontStash,
  279. m_data->m_droidRegular,fontSize,posX,posY,
  280. txt,&dx, this->m_instancingRenderer->getScreenWidth(),
  281. this->m_instancingRenderer->getScreenHeight(),
  282. measureOnly,
  283. m_window->getRetinaScale());
  284. sth_end_draw(m_data->m_fontStash);
  285. sth_flush_draw(m_data->m_fontStash);
  286. } else
  287. {
  288. //float width = 0.f;
  289. int pos=0;
  290. //float color[]={0.2f,0.2,0.2f,1.f};
  291. glActiveTexture(GL_TEXTURE0);
  292. glBindTexture(GL_TEXTURE_2D,m_data->m_largeFontTextureId);
  293. //float width = r.x;
  294. //float extraSpacing = 0.;
  295. float startX = posX;
  296. float startY = posY;
  297. while (txt[pos])
  298. {
  299. int c = txt[pos];
  300. //r.h = g_DefaultNormalFont->m_CharHeight;
  301. //r.w = g_DefaultNormalFont->m_CharWidth[c]+extraSpacing;
  302. float endX = startX+g_DefaultLargeFont->m_CharWidth[c];
  303. float endY = startY+g_DefaultLargeFont->m_CharHeight;
  304. float currentColor[]={0.2f,0.2,0.2f,1.f};
  305. m_primRenderer->drawTexturedRect(startX, startY, endX, endY, currentColor,g_DefaultLargeFont->m_CharU0[c],g_DefaultLargeFont->m_CharV0[c],g_DefaultLargeFont->m_CharU1[c],g_DefaultLargeFont->m_CharV1[c]);
  306. //DrawTexturedRect(0,r,g_DefaultNormalFont->m_CharU0[c],g_DefaultNormalFont->m_CharV0[c],g_DefaultNormalFont->m_CharU1[c],g_DefaultNormalFont->m_CharV1[c]);
  307. // DrawFilledRect(r);
  308. startX = endX;
  309. //startY = endY;
  310. pos++;
  311. }
  312. glBindTexture(GL_TEXTURE_2D,0);
  313. }
  314. glDisable(GL_BLEND);
  315. }
  316. void SimpleOpenGL3App::drawTexturedRect(float x0, float y0, float x1, float y1, float color[4], float u0,float v0, float u1, float v1, int useRGBA)
  317. {
  318. glEnable(GL_BLEND);
  319. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  320. m_primRenderer->drawTexturedRect(x0,y0,x1,y1,color,u0,v0,u1,v1,useRGBA);
  321. glDisable(GL_BLEND);
  322. }
  323. struct GfxVertex
  324. {
  325. float x,y,z,w;
  326. float nx,ny,nz;
  327. float u,v;
  328. };
  329. int SimpleOpenGL3App::registerCubeShape(float halfExtentsX,float halfExtentsY, float halfExtentsZ, int textureIndex, float textureScaling)
  330. {
  331. int strideInBytes = 9*sizeof(float);
  332. int numVertices = sizeof(cube_vertices_textured)/strideInBytes;
  333. int numIndices = sizeof(cube_indices)/sizeof(int);
  334. b3AlignedObjectArray<GfxVertex> verts;
  335. verts.resize(numVertices);
  336. for (int i=0;i<numVertices;i++)
  337. {
  338. verts[i].x = halfExtentsX*cube_vertices_textured[i*9];
  339. verts[i].y = halfExtentsY*cube_vertices_textured[i*9+1];
  340. verts[i].z = halfExtentsZ*cube_vertices_textured[i*9+2];
  341. verts[i].w = cube_vertices_textured[i*9+3];
  342. verts[i].nx = cube_vertices_textured[i*9+4];
  343. verts[i].ny = cube_vertices_textured[i*9+5];
  344. verts[i].nz = cube_vertices_textured[i*9+6];
  345. verts[i].u = cube_vertices_textured[i*9+7]*textureScaling;
  346. verts[i].v = cube_vertices_textured[i*9+8]*textureScaling;
  347. }
  348. int shapeId = m_instancingRenderer->registerShape(&verts[0].x,numVertices,cube_indices,numIndices,B3_GL_TRIANGLES,textureIndex);
  349. return shapeId;
  350. }
  351. void SimpleOpenGL3App::registerGrid(int cells_x, int cells_z, float color0[4], float color1[4])
  352. {
  353. b3Vector3 cubeExtents=b3MakeVector3(0.5,0.5,0.5);
  354. cubeExtents[m_data->m_upAxis] = 0;
  355. int cubeId = registerCubeShape(cubeExtents[0],cubeExtents[1],cubeExtents[2]);
  356. b3Quaternion orn(0,0,0,1);
  357. b3Vector3 center=b3MakeVector3(0,0,0,1);
  358. b3Vector3 scaling=b3MakeVector3(1,1,1,1);
  359. for ( int i = 0; i < cells_x; i++)
  360. {
  361. for (int j = 0; j < cells_z; j++)
  362. {
  363. float* color =0;
  364. if ((i + j) % 2 == 0)
  365. {
  366. color = (float*)color0;
  367. } else {
  368. color = (float*)color1;
  369. }
  370. if (this->m_data->m_upAxis==1)
  371. {
  372. center =b3MakeVector3((i + 0.5f) - cells_x * 0.5f, 0.f, (j + 0.5f) - cells_z * 0.5f);
  373. } else
  374. {
  375. center =b3MakeVector3((i + 0.5f) - cells_x * 0.5f, (j + 0.5f) - cells_z * 0.5f,0.f );
  376. }
  377. m_instancingRenderer->registerGraphicsInstance(cubeId,center,orn,color,scaling);
  378. }
  379. }
  380. }
  381. int SimpleOpenGL3App::registerGraphicsUnitSphereShape(EnumSphereLevelOfDetail lod, int textureId)
  382. {
  383. int strideInBytes = 9*sizeof(float);
  384. int graphicsShapeIndex = -1;
  385. switch (lod)
  386. {
  387. case SPHERE_LOD_POINT_SPRITE:
  388. {
  389. int numVertices = sizeof(point_sphere_vertices)/strideInBytes;
  390. int numIndices = sizeof(point_sphere_indices)/sizeof(int);
  391. graphicsShapeIndex = m_instancingRenderer->registerShape(&point_sphere_vertices[0],numVertices,point_sphere_indices,numIndices,B3_GL_POINTS,textureId);
  392. break;
  393. }
  394. case SPHERE_LOD_LOW:
  395. {
  396. int numVertices = sizeof(low_sphere_vertices)/strideInBytes;
  397. int numIndices = sizeof(low_sphere_indices)/sizeof(int);
  398. graphicsShapeIndex = m_instancingRenderer->registerShape(&low_sphere_vertices[0],numVertices,low_sphere_indices,numIndices,B3_GL_TRIANGLES,textureId);
  399. break;
  400. }
  401. case SPHERE_LOD_MEDIUM:
  402. {
  403. int numVertices = sizeof(medium_sphere_vertices)/strideInBytes;
  404. int numIndices = sizeof(medium_sphere_indices)/sizeof(int);
  405. graphicsShapeIndex = m_instancingRenderer->registerShape(&medium_sphere_vertices[0],numVertices,medium_sphere_indices,numIndices,B3_GL_TRIANGLES,textureId);
  406. break;
  407. }
  408. case SPHERE_LOD_HIGH:
  409. default:
  410. {
  411. int numVertices = sizeof(detailed_sphere_vertices)/strideInBytes;
  412. int numIndices = sizeof(detailed_sphere_indices)/sizeof(int);
  413. graphicsShapeIndex = m_instancingRenderer->registerShape(&detailed_sphere_vertices[0],numVertices,detailed_sphere_indices,numIndices,B3_GL_TRIANGLES,textureId);
  414. break;
  415. }
  416. };
  417. return graphicsShapeIndex;
  418. }
  419. void SimpleOpenGL3App::drawGrid(DrawGridData data)
  420. {
  421. int gridSize = data.gridSize;
  422. float upOffset = data.upOffset;
  423. int upAxis = data.upAxis;
  424. float gridColor[4];
  425. gridColor[0] = data.gridColor[0];
  426. gridColor[1] = data.gridColor[1];
  427. gridColor[2] = data.gridColor[2];
  428. gridColor[3] = data.gridColor[3];
  429. int sideAxis=-1;
  430. int forwardAxis=-1;
  431. switch (upAxis)
  432. {
  433. case 1:
  434. forwardAxis=2;
  435. sideAxis=0;
  436. break;
  437. case 2:
  438. forwardAxis=1;
  439. sideAxis=0;
  440. break;
  441. default:
  442. b3Assert(0);
  443. };
  444. //b3Vector3 gridColor = b3MakeVector3(0.5,0.5,0.5);
  445. b3AlignedObjectArray<unsigned int> indices;
  446. b3AlignedObjectArray<b3Vector3> vertices;
  447. int lineIndex=0;
  448. for(int i=-gridSize;i<=gridSize;i++)
  449. {
  450. {
  451. b3Assert(glGetError() ==GL_NO_ERROR);
  452. b3Vector3 from = b3MakeVector3(0,0,0);
  453. from[sideAxis] = float(i);
  454. from[upAxis] = upOffset;
  455. from[forwardAxis] = float(-gridSize);
  456. b3Vector3 to=b3MakeVector3(0,0,0);
  457. to[sideAxis] = float(i);
  458. to[upAxis] = upOffset;
  459. to[forwardAxis] = float(gridSize);
  460. vertices.push_back(from);
  461. indices.push_back(lineIndex++);
  462. vertices.push_back(to);
  463. indices.push_back(lineIndex++);
  464. // m_instancingRenderer->drawLine(from,to,gridColor);
  465. }
  466. b3Assert(glGetError() ==GL_NO_ERROR);
  467. {
  468. b3Assert(glGetError() ==GL_NO_ERROR);
  469. b3Vector3 from=b3MakeVector3(0,0,0);
  470. from[sideAxis] = float(-gridSize);
  471. from[upAxis] = upOffset;
  472. from[forwardAxis] = float(i);
  473. b3Vector3 to=b3MakeVector3(0,0,0);
  474. to[sideAxis] = float(gridSize);
  475. to[upAxis] = upOffset;
  476. to[forwardAxis] = float(i);
  477. vertices.push_back(from);
  478. indices.push_back(lineIndex++);
  479. vertices.push_back(to);
  480. indices.push_back(lineIndex++);
  481. // m_instancingRenderer->drawLine(from,to,gridColor);
  482. }
  483. }
  484. m_instancingRenderer->drawLines(&vertices[0].x,
  485. gridColor,
  486. vertices.size(),sizeof(b3Vector3),&indices[0],indices.size(),1);
  487. m_instancingRenderer->drawLine(b3MakeVector3(0,0,0),b3MakeVector3(1,0,0),b3MakeVector3(1,0,0),3);
  488. m_instancingRenderer->drawLine(b3MakeVector3(0,0,0),b3MakeVector3(0,1,0),b3MakeVector3(0,1,0),3);
  489. m_instancingRenderer->drawLine(b3MakeVector3(0,0,0),b3MakeVector3(0,0,1),b3MakeVector3(0,0,1),3);
  490. // void GLInstancingRenderer::drawPoints(const float* positions, const float color[4], int numPoints, int pointStrideInBytes, float pointDrawSize)
  491. //we don't use drawPoints because all points would have the same color
  492. // b3Vector3 points[3] = { b3MakeVector3(1, 0, 0), b3MakeVector3(0, 1, 0), b3MakeVector3(0, 0, 1) };
  493. // m_instancingRenderer->drawPoints(&points[0].x, b3MakeVector3(1, 0, 0), 3, sizeof(b3Vector3), 6);
  494. m_instancingRenderer->drawPoint(b3MakeVector3(1,0,0),b3MakeVector3(1,0,0),6);
  495. m_instancingRenderer->drawPoint(b3MakeVector3(0,1,0),b3MakeVector3(0,1,0),6);
  496. m_instancingRenderer->drawPoint(b3MakeVector3(0,0,1),b3MakeVector3(0,0,1),6);
  497. }
  498. void SimpleOpenGL3App::setBackgroundColor(float red, float green, float blue)
  499. {
  500. CommonGraphicsApp::setBackgroundColor(red,green,blue);
  501. glClearColor(m_backgroundColorRGB[0],m_backgroundColorRGB[1],m_backgroundColorRGB[2],1.f);
  502. }
  503. SimpleOpenGL3App::~SimpleOpenGL3App()
  504. {
  505. delete m_instancingRenderer;
  506. delete m_primRenderer ;
  507. sth_delete(m_data->m_fontStash);
  508. delete m_data->m_renderCallbacks;
  509. TwDeleteDefaultFonts();
  510. m_window->closeWindow();
  511. delete m_window;
  512. delete m_data ;
  513. }
  514. void SimpleOpenGL3App::getScreenPixels(unsigned char* rgbaBuffer, int bufferSizeInBytes, float* depthBuffer, int depthBufferSizeInBytes)
  515. {
  516. int width = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenWidth();
  517. int height = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenHeight();
  518. if ((width*height*4) == bufferSizeInBytes)
  519. {
  520. glReadPixels(0,0,width, height, GL_RGBA, GL_UNSIGNED_BYTE, rgbaBuffer);
  521. int glstat = glGetError();
  522. b3Assert(glstat==GL_NO_ERROR);
  523. }
  524. if ((width*height*sizeof(float)) == depthBufferSizeInBytes)
  525. {
  526. glReadPixels(0,0,width, height, GL_DEPTH_COMPONENT, GL_FLOAT, depthBuffer);
  527. int glstat = glGetError();
  528. b3Assert(glstat==GL_NO_ERROR);
  529. }
  530. }
  531. //#define STB_IMAGE_WRITE_IMPLEMENTATION
  532. #include "stb_image_write.h"
  533. static void writeTextureToFile(int textureWidth, int textureHeight, const char* fileName, FILE* ffmpegVideo)
  534. {
  535. int numComponents = 4;
  536. //glPixelStorei(GL_PACK_ALIGNMENT,1);
  537. b3Assert(glGetError()==GL_NO_ERROR);
  538. //glReadBuffer(GL_BACK);//COLOR_ATTACHMENT0);
  539. float* orgPixels = (float*)malloc(textureWidth*textureHeight*numComponents*4);
  540. glReadPixels(0,0,textureWidth, textureHeight, GL_RGBA, GL_FLOAT, orgPixels);
  541. //it is useful to have the actual float values for debugging purposes
  542. //convert float->char
  543. char* pixels = (char*)malloc(textureWidth*textureHeight*numComponents);
  544. assert(glGetError()==GL_NO_ERROR);
  545. for (int j=0;j<textureHeight;j++)
  546. {
  547. for (int i=0;i<textureWidth;i++)
  548. {
  549. pixels[(j*textureWidth+i)*numComponents] = char(orgPixels[(j*textureWidth+i)*numComponents]*255.f);
  550. pixels[(j*textureWidth+i)*numComponents+1]=char(orgPixels[(j*textureWidth+i)*numComponents+1]*255.f);
  551. pixels[(j*textureWidth+i)*numComponents+2]=char(orgPixels[(j*textureWidth+i)*numComponents+2]*255.f);
  552. pixels[(j*textureWidth+i)*numComponents+3]=char(orgPixels[(j*textureWidth+i)*numComponents+3]*255.f);
  553. }
  554. }
  555. if (ffmpegVideo)
  556. {
  557. fwrite(pixels, textureWidth*textureHeight*numComponents, 1, ffmpegVideo);
  558. //fwrite(pixels, 100,1,ffmpegVideo);//textureWidth*textureHeight*numComponents, 1, ffmpegVideo);
  559. } else
  560. {
  561. if (1)
  562. {
  563. //swap the pixels
  564. unsigned char tmp;
  565. for (int j=0;j<textureHeight/2;j++)
  566. {
  567. for (int i=0;i<textureWidth;i++)
  568. {
  569. for (int c=0;c<numComponents;c++)
  570. {
  571. tmp = pixels[(j*textureWidth+i)*numComponents+c];
  572. pixels[(j*textureWidth+i)*numComponents+c]=
  573. pixels[((textureHeight-j-1)*textureWidth+i)*numComponents+c];
  574. pixels[((textureHeight-j-1)*textureWidth+i)*numComponents+c] = tmp;
  575. }
  576. }
  577. }
  578. }
  579. stbi_write_png(fileName, textureWidth,textureHeight, numComponents, pixels, textureWidth*numComponents);
  580. }
  581. free(pixels);
  582. free(orgPixels);
  583. }
  584. void SimpleOpenGL3App::swapBuffer()
  585. {
  586. if (m_data->m_frameDumpPngFileName)
  587. {
  588. int width = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenWidth();
  589. int height = (int) m_window->getRetinaScale()*this->m_instancingRenderer->getScreenHeight();
  590. writeTextureToFile(width,
  591. height,m_data->m_frameDumpPngFileName,
  592. m_data->m_ffmpegFile);
  593. m_data->m_renderTexture->disable();
  594. if (m_data->m_ffmpegFile==0)
  595. {
  596. m_data->m_frameDumpPngFileName = 0;
  597. }
  598. }
  599. m_window->endRendering();
  600. m_window->startRendering();
  601. }
  602. // see also http://blog.mmacklin.com/2013/06/11/real-time-video-capture-with-ffmpeg/
  603. void SimpleOpenGL3App::dumpFramesToVideo(const char* mp4FileName)
  604. {
  605. int width = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenWidth();
  606. int height = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenHeight();
  607. char cmd[8192];
  608. #ifdef _WIN32
  609. sprintf(cmd, "ffmpeg -r 60 -f rawvideo -pix_fmt rgba -s %dx%d -i - "
  610. "-threads 0 -y -b 50000k -t 20 -c:v libx264 -preset slow -crf 22 -an -pix_fmt yuv420p -vf vflip %s", width, height, mp4FileName);
  611. //sprintf(cmd, "ffmpeg -r 60 -f rawvideo -pix_fmt rgba -s %dx%d -i - "
  612. // "-y -crf 0 -b:v 1500000 -an -vcodec h264 -vf vflip %s", width, height, mp4FileName);
  613. #else
  614. sprintf(cmd, "ffmpeg -r 60 -f rawvideo -pix_fmt rgba -s %dx%d -i - "
  615. "-threads 0 -y -b 50000k -t 20 -c:v libx264 -preset slow -crf 22 -an -pix_fmt yuv420p -vf vflip %s", width, height, mp4FileName);
  616. #endif
  617. //sprintf(cmd,"ffmpeg -r 60 -f rawvideo -pix_fmt rgba -s %dx%d -i - "
  618. // "-threads 0 -y -crf 0 -b 50000k -vf vflip %s",width,height,mp4FileName);
  619. // sprintf(cmd,"ffmpeg -r 60 -f rawvideo -pix_fmt rgba -s %dx%d -i - "
  620. // "-threads 0 -preset fast -y -crf 21 -vf vflip %s",width,height,mp4FileName);
  621. if (m_data->m_ffmpegFile)
  622. {
  623. pclose(m_data->m_ffmpegFile);
  624. }
  625. if (mp4FileName)
  626. {
  627. m_data->m_ffmpegFile = popen(cmd, "w");
  628. m_data->m_frameDumpPngFileName = mp4FileName;
  629. }
  630. }
  631. void SimpleOpenGL3App::dumpNextFrameToPng(const char* filename)
  632. {
  633. // open pipe to ffmpeg's stdin in binary write mode
  634. m_data->m_frameDumpPngFileName = filename;
  635. //you could use m_renderTexture to allow to render at higher resolutions, such as 4k or so
  636. if (!m_data->m_renderTexture)
  637. {
  638. m_data->m_renderTexture = new GLRenderToTexture();
  639. GLuint renderTextureId;
  640. glGenTextures(1, &renderTextureId);
  641. // "Bind" the newly created texture : all future texture functions will modify this texture
  642. glBindTexture(GL_TEXTURE_2D, renderTextureId);
  643. // Give an empty image to OpenGL ( the last "0" )
  644. //glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, g_OpenGLWidth,g_OpenGLHeight, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0);
  645. //glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA32F, g_OpenGLWidth,g_OpenGLHeight, 0,GL_RGBA, GL_FLOAT, 0);
  646. glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA32F,
  647. m_instancingRenderer->getScreenWidth()*m_window->getRetinaScale(),m_instancingRenderer->getScreenHeight()*m_window->getRetinaScale()
  648. , 0,GL_RGBA, GL_FLOAT, 0);
  649. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  650. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  651. //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  652. //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  653. m_data->m_renderTexture->init(m_instancingRenderer->getScreenWidth()*m_window->getRetinaScale(),this->m_instancingRenderer->getScreenHeight()*m_window->getRetinaScale(),renderTextureId, RENDERTEXTURE_COLOR);
  654. }
  655. m_data->m_renderTexture->enable();
  656. }
  657. void SimpleOpenGL3App::setUpAxis(int axis)
  658. {
  659. b3Assert((axis == 1)||(axis==2));//only Y or Z is supported at the moment
  660. m_data->m_upAxis = axis;
  661. }
  662. int SimpleOpenGL3App::getUpAxis() const
  663. {
  664. return m_data->m_upAxis;
  665. }
  666. #endif//#ifndef NO_OPENGL3