SimpleOpenGL3App.cpp 24 KB

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