Advertisement
Guest User

Untitled

a guest
Oct 19th, 2017
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 57.32 KB | None | 0 0
  1. /*
  2. Copyright 2011-2017 Daniel S. Buckstein
  3.  
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7.  
  8. http://www.apache.org/licenses/LICENSE-2.0
  9.  
  10. Unless required by applicable law or agreed to in writing, software
  11. distributed under the License is distributed on an "AS IS" BASIS,
  12. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. See the License for the specific language governing permissions and
  14. limitations under the License.
  15. */
  16.  
  17. /*
  18. animal3D SDK: Minimal 3D Animation Framework
  19. By Daniel S. Buckstein
  20.  
  21. a3_DemoState.c/.cpp
  22. Demo state function implementations.
  23.  
  24. ********************************************
  25. *** THIS IS YOUR DEMO'S MAIN SOURCE FILE ***
  26. *** Implement your demo logic here. ***
  27. ********************************************
  28. */
  29.  
  30.  
  31. #include "a3_DemoState.h"
  32.  
  33.  
  34. //-----------------------------------------------------------------------------
  35.  
  36. // OpenGL
  37. #ifdef _WIN32
  38. #include <Windows.h>
  39. #include <GL/GL.h>
  40. #else // !_WIN32
  41. #include <OpenGL/gl3.h>
  42. #endif // _WIN32
  43.  
  44.  
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47.  
  48.  
  49. //-----------------------------------------------------------------------------
  50. // SETUP AND TERMINATION UTILITIES
  51.  
  52. // set default GL state
  53. void a3demo_setDefaultGraphicsState()
  54. {
  55. const float lineWidth = 2.0f;
  56. const float pointSize = 4.0f;
  57.  
  58. // lines and points
  59. glLineWidth(lineWidth);
  60. glPointSize(pointSize);
  61.  
  62. // backface culling
  63. glEnable(GL_CULL_FACE);
  64. glCullFace(GL_BACK);
  65.  
  66. // alpha blending
  67. // result = ( new*[new alpha] ) + ( old*[1 - new alpha] )
  68. glEnable(GL_BLEND);
  69. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  70.  
  71. // textures
  72. glEnable(GL_TEXTURE_2D);
  73.  
  74. // background
  75. glClearColor(0.0f, 0.0f, 0.0, 0.0f);
  76. }
  77.  
  78.  
  79. //-----------------------------------------------------------------------------
  80.  
  81. // utility to load textures
  82. void a3demo_loadTextures(a3_DemoState *demoState)
  83. {
  84. // pointer to texture
  85. a3_Texture *tex;
  86. unsigned int i;
  87.  
  88. // list of texture files to load
  89. const char *texFiles[] = {
  90. "../../../../resource/tex/sprite/checker.png",
  91. "../../../../resource/tex/earth/2k/earth_dm_2k.png",
  92. "../../../../resource/tex/earth/2k/earth_sm_2k.png",
  93. };
  94. const unsigned int numTextures = sizeof(texFiles) / sizeof(const char *);
  95.  
  96. for (i = 0; i < numTextures; ++i)
  97. {
  98. tex = demoState->texture + i;
  99. a3textureCreateFromFile(tex, texFiles[i]);
  100. }
  101.  
  102. // change settings on a per-texture basis
  103. a3textureActivate(demoState->tex_checker, a3tex_unit00);
  104. a3textureDefaultSettings(); // nearest filtering, repeat on both axes
  105.  
  106. a3textureActivate(demoState->tex_earth_dm, a3tex_unit00);
  107. a3textureChangeRepeatMode(a3tex_repeatNormal, a3tex_repeatClamp); // repeat on U, clamp V
  108. a3textureChangeFilterMode(a3tex_filterLinear); // linear pixel blending
  109.  
  110. a3textureActivate(demoState->tex_earth_sm, a3tex_unit00);
  111. a3textureChangeRepeatMode(a3tex_repeatNormal, a3tex_repeatClamp);
  112. a3textureChangeFilterMode(a3tex_filterLinear);
  113.  
  114.  
  115. // done
  116. a3textureDeactivate(a3tex_unit00);
  117. }
  118.  
  119. // utility to load geometry
  120. void a3demo_loadGeometry(a3_DemoState *demoState)
  121. {
  122. // static model transformations
  123. static const p3mat4 downscale20x = {
  124. +0.05f, 0.0f, 0.0f, 0.0f,
  125. 0.0f, +0.05f, 0.0f, 0.0f,
  126. 0.0f, 0.0f, +0.05f, 0.0f,
  127. 0.0f, 0.0f, 0.0f, +1.0f,
  128. };
  129.  
  130. // pointer to shared vbo/ibo
  131. a3_VertexBuffer *vbo_ibo;
  132. a3_VertexArrayDescriptor *vao;
  133. a3_VertexDrawable *currentDrawable;
  134. unsigned int sharedVertexStorage = 0, sharedIndexStorage = 0;
  135. unsigned int numVerts = 0;
  136. unsigned int i;
  137.  
  138.  
  139. // file streaming (if requested)
  140. a3_FileStream fileStream[1] = { 0 };
  141. const char *const geometryStream = "./data/geom_waypoints.dat";
  142.  
  143. // geometry data
  144. a3_GeometryData sceneShapesData[2] = { 0 };
  145. a3_GeometryData overlayShapesData[6] = { 0 };
  146. a3_GeometryData proceduralShapesData[1] = { 0 };
  147. a3_GeometryData loadedModelsData[1] = { 0 };
  148. const unsigned int sceneShapesCount = sizeof(sceneShapesData) / sizeof(a3_GeometryData);
  149. const unsigned int overlayShapesCount = sizeof(overlayShapesData) / sizeof(a3_GeometryData);
  150. const unsigned int proceduralShapesCount = sizeof(proceduralShapesData) / sizeof(a3_GeometryData);
  151. const unsigned int loadedModelsCount = sizeof(loadedModelsData) / sizeof(a3_GeometryData);
  152.  
  153. // common index format
  154. a3_IndexFormatDescriptor sceneCommonIndexFormat[1] = { 0 };
  155.  
  156.  
  157. // procedural scene objects
  158. // attempt to load stream if requested
  159. if (demoState->streaming && a3fileStreamOpenRead(fileStream, geometryStream))
  160. {
  161. // read from stream
  162.  
  163. // static scene objects
  164. for (i = 0; i < sceneShapesCount; ++i)
  165. a3fileStreamReadObject(fileStream, sceneShapesData + i, (a3_FileStreamReadFunc)a3geometryLoadDataBinary);
  166.  
  167. // overlay scene objects
  168. for (i = 0; i < overlayShapesCount; ++i)
  169. a3fileStreamReadObject(fileStream, overlayShapesData + i, (a3_FileStreamReadFunc)a3geometryLoadDataBinary);
  170.  
  171. // procedural models
  172. for (i = 0; i < proceduralShapesCount; ++i)
  173. a3fileStreamReadObject(fileStream, proceduralShapesData + i, (a3_FileStreamReadFunc)a3geometryLoadDataBinary);
  174.  
  175. // loaded models
  176. for (i = 0; i < loadedModelsCount; ++i)
  177. a3fileStreamReadObject(fileStream, loadedModelsData + i, (a3_FileStreamReadFunc)a3geometryLoadDataBinary);
  178.  
  179. // done
  180. a3fileStreamClose(fileStream);
  181. }
  182. // not streaming or stream doesn't exist
  183. else if (!demoState->streaming || a3fileStreamOpenWrite(fileStream, geometryStream))
  184. {
  185. // create new data
  186. a3_ProceduralGeometryDescriptor sceneShapes[2] = { a3geomShape_none };
  187. a3_ProceduralGeometryDescriptor overlayShapes[6] = { a3geomShape_none };
  188. a3_ProceduralGeometryDescriptor proceduralShapes[1] = { a3geomShape_none };
  189.  
  190. // static scene procedural objects
  191. // (axes and grid)
  192. a3proceduralCreateDescriptorAxes(sceneShapes + 0, a3geomFlag_wireframe, 0.0f, 1);
  193. a3proceduralCreateDescriptorPlane(sceneShapes + 1, a3geomFlag_wireframe, a3geomAxis_default, 32.0f, 32.0f, 32, 32);
  194. for (i = 0; i < sceneShapesCount; ++i)
  195. {
  196. a3proceduralGenerateGeometryData(sceneShapesData + i, sceneShapes + i);
  197. a3fileStreamWriteObject(fileStream, sceneShapesData + i, (a3_FileStreamWriteFunc)a3geometrySaveDataBinary);
  198. }
  199.  
  200.  
  201. // single-vertex shape for curve segment drawing
  202. {
  203. // create vertex format
  204. a3_GeometryData *pointData = overlayShapesData + 0;
  205. a3geometryCreateVertexFormat(pointData->vertexFormat, 0, 0);
  206. pointData->primType = a3prim_points;
  207. pointData->numVertices = 1;
  208. pointData->attribData[0] = pointData->data = malloc(3 * sizeof(float));
  209. memset(pointData->data, 0, 3 * sizeof(float));
  210. a3fileStreamWriteObject(fileStream, pointData, (a3_FileStreamWriteFunc)a3geometrySaveDataBinary);
  211. }
  212.  
  213. // static overlay objects
  214. // first, "node" or "waypoint" object, just a low-resolution sphere
  215. // next, a background sphere and torus or ring for a gimbal
  216. // finally, bone and node shapes
  217. a3proceduralCreateDescriptorSphere(overlayShapes + 1, a3geomFlag_vanilla, a3geomAxis_default, 0.1f, 8, 4);
  218. a3proceduralCreateDescriptorSphere(overlayShapes + 2, a3geomFlag_vanilla, a3geomAxis_default, 1.0f, 16, 12);
  219. a3proceduralCreateDescriptorCircle(overlayShapes + 3, a3geomFlag_wireframe, a3geomAxis_default, 1.0f, 16, 1);
  220. a3proceduralCreateDescriptorCone(overlayShapes + 4, a3geomFlag_wireframe, a3geomAxis_default, 0.05f, 1.0f, 4, 1, 1);
  221. a3proceduralCreateDescriptorSphere(overlayShapes + 5, a3geomFlag_wireframe, a3geomAxis_default, 0.05f, 4, 2);
  222. for (i = 1; i < overlayShapesCount; ++i)
  223. {
  224. a3proceduralGenerateGeometryData(overlayShapesData + i, overlayShapes + i);
  225. a3fileStreamWriteObject(fileStream, overlayShapesData + i, (a3_FileStreamWriteFunc)a3geometrySaveDataBinary);
  226. }
  227.  
  228.  
  229. // procedural
  230. a3proceduralCreateDescriptorSphere(proceduralShapes + 0, a3geomFlag_tangents, a3geomAxis_default, 1.0f, 24, 16);
  231. for (i = 0; i < proceduralShapesCount; ++i)
  232. {
  233. a3proceduralGenerateGeometryData(proceduralShapesData + i, proceduralShapes + i);
  234. a3fileStreamWriteObject(fileStream, proceduralShapesData + i, (a3_FileStreamWriteFunc)a3geometrySaveDataBinary);
  235. }
  236.  
  237. // loaded models
  238. a3modelLoadOBJ(loadedModelsData + 0, "../../../../resource/obj/teapot/teapot.obj", a3model_calculateVertexTangents, downscale20x.mm);
  239. for (i = 0; i < loadedModelsCount; ++i)
  240. a3fileStreamWriteObject(fileStream, loadedModelsData + i, (a3_FileStreamWriteFunc)a3geometrySaveDataBinary);
  241.  
  242. // done
  243. a3fileStreamClose(fileStream);
  244. }
  245.  
  246.  
  247. // GPU data upload process:
  248. // - determine storage requirements
  249. // - allocate buffer
  250. // - create vertex arrays using unique formats
  251. // - create drawable and upload data
  252.  
  253. // get storage size
  254. sharedVertexStorage = numVerts = 0;
  255. for (i = 0; i < sceneShapesCount; ++i)
  256. {
  257. sharedVertexStorage += a3geometryGetVertexBufferSize(sceneShapesData + i);
  258. numVerts += sceneShapesData[i].numVertices;
  259. }
  260. for (i = 0; i < overlayShapesCount; ++i)
  261. {
  262. sharedVertexStorage += a3geometryGetVertexBufferSize(overlayShapesData + i);
  263. numVerts += overlayShapesData[i].numVertices;
  264. }
  265. for (i = 0; i < proceduralShapesCount; ++i)
  266. {
  267. sharedVertexStorage += a3geometryGetVertexBufferSize(proceduralShapesData + i);
  268. numVerts += proceduralShapesData[i].numVertices;
  269. }
  270. for (i = 0; i < loadedModelsCount; ++i)
  271. {
  272. sharedVertexStorage += a3geometryGetVertexBufferSize(loadedModelsData + i);
  273. numVerts += loadedModelsData[i].numVertices;
  274. }
  275.  
  276. // common index format required for shapes that share vertex formats
  277. a3geometryCreateIndexFormat(sceneCommonIndexFormat, numVerts);
  278. sharedIndexStorage = 0;
  279. for (i = 0; i < sceneShapesCount; ++i)
  280. sharedIndexStorage += a3indexStorageSpaceRequired(sceneCommonIndexFormat, sceneShapesData[i].numIndices);
  281. for (i = 0; i < overlayShapesCount; ++i)
  282. sharedIndexStorage += a3indexStorageSpaceRequired(sceneCommonIndexFormat, overlayShapesData[i].numIndices);
  283. for (i = 0; i < proceduralShapesCount; ++i)
  284. sharedIndexStorage += a3indexStorageSpaceRequired(sceneCommonIndexFormat, proceduralShapesData[i].numIndices);
  285. for (i = 0; i < loadedModelsCount; ++i)
  286. sharedIndexStorage += a3indexStorageSpaceRequired(sceneCommonIndexFormat, loadedModelsData[i].numIndices);
  287.  
  288.  
  289. // create shared buffer
  290. vbo_ibo = demoState->vbo_staticSceneObjectDrawBuffer;
  291. a3bufferCreateSplit(vbo_ibo, a3buffer_vertex, sharedVertexStorage, sharedIndexStorage, 0, 0);
  292. sharedVertexStorage = 0;
  293.  
  294.  
  295. // create vertex formats and drawables
  296. // axes
  297. vao = demoState->vao_position_color;
  298. a3geometryGenerateVertexArray(vao, sceneShapesData + 0, vbo_ibo, sharedVertexStorage);
  299. currentDrawable = demoState->draw_axes;
  300. sharedVertexStorage += a3geometryGenerateDrawable(currentDrawable, sceneShapesData + 0, vao, vbo_ibo, sceneCommonIndexFormat, 0, 0);
  301.  
  302. // grid: position attribute only
  303. // overlay objects are also just position
  304. vao = demoState->vao_position;
  305. a3geometryGenerateVertexArray(vao, sceneShapesData + 1, vbo_ibo, sharedVertexStorage);
  306. currentDrawable = demoState->draw_grid;
  307. sharedVertexStorage += a3geometryGenerateDrawable(currentDrawable, sceneShapesData + 1, vao, vbo_ibo, sceneCommonIndexFormat, 0, 0);
  308. currentDrawable = demoState->draw_curve;
  309. sharedVertexStorage += a3geometryGenerateDrawable(currentDrawable, overlayShapesData + 0, vao, vbo_ibo, sceneCommonIndexFormat, 0, 0);
  310. currentDrawable = demoState->draw_node;
  311. sharedVertexStorage += a3geometryGenerateDrawable(currentDrawable, overlayShapesData + 1, vao, vbo_ibo, sceneCommonIndexFormat, 0, 0);
  312. currentDrawable = demoState->draw_gimbal;
  313. sharedVertexStorage += a3geometryGenerateDrawable(currentDrawable, overlayShapesData + 2, vao, vbo_ibo, sceneCommonIndexFormat, 0, 0);
  314. currentDrawable = demoState->draw_ring;
  315. sharedVertexStorage += a3geometryGenerateDrawable(currentDrawable, overlayShapesData + 3, vao, vbo_ibo, sceneCommonIndexFormat, 0, 0);
  316. currentDrawable = demoState->draw_bone;
  317. sharedVertexStorage += a3geometryGenerateDrawable(currentDrawable, overlayShapesData + 4, vao, vbo_ibo, sceneCommonIndexFormat, 0, 0);
  318. currentDrawable = demoState->draw_joint;
  319. sharedVertexStorage += a3geometryGenerateDrawable(currentDrawable, overlayShapesData + 5, vao, vbo_ibo, sceneCommonIndexFormat, 0, 0);
  320.  
  321. // models: procedural and loaded have the same format, so they can share
  322. // a vertex format
  323. vao = demoState->vao_tangentBasis;
  324. a3geometryGenerateVertexArray(vao, proceduralShapesData + 0, vbo_ibo, sharedVertexStorage);
  325. currentDrawable = demoState->draw_sphere;
  326. sharedVertexStorage += a3geometryGenerateDrawable(currentDrawable, proceduralShapesData + 0, vao, vbo_ibo, sceneCommonIndexFormat, 0, 0);
  327. currentDrawable = demoState->draw_teapot;
  328. sharedVertexStorage += a3geometryGenerateDrawable(currentDrawable, loadedModelsData + 0, vao, vbo_ibo, sceneCommonIndexFormat, 0, 0);
  329.  
  330. // release data when done
  331. for (i = 0; i < sceneShapesCount; ++i)
  332. a3geometryReleaseData(sceneShapesData + i);
  333. for (i = 0; i < overlayShapesCount; ++i)
  334. a3geometryReleaseData(overlayShapesData + i);
  335. for (i = 0; i < proceduralShapesCount; ++i)
  336. a3geometryReleaseData(proceduralShapesData + i);
  337. for (i = 0; i < loadedModelsCount; ++i)
  338. a3geometryReleaseData(loadedModelsData + i);
  339. }
  340.  
  341.  
  342. // utility to load shaders
  343. void a3demo_loadShaders(a3_DemoState *demoState)
  344. {
  345. // direct to demo programs
  346. a3_DemoStateShaderProgram *currentDemoProg;
  347. int *currentUnif, uLocation;
  348. unsigned int i, j;
  349.  
  350. // list of uniform names: align with uniform list in demo struct!
  351. const char *uniformNames[demoStateMaxCount_shaderProgramUniform] = {
  352. // common vertex
  353. "uMVP",
  354. "uLocal",
  355. "uLightPos_obj",
  356. "uEyePos_obj",
  357.  
  358. // common geometry
  359. "uWaypoints",
  360. "uWaypointHandles",
  361. "uWaypointCount",
  362. "uWaypointIndex",
  363. "uLineColor",
  364. "uCurveColor",
  365.  
  366. // common fragment
  367. "uColor",
  368. "uTex_dm",
  369. "uTex_sm",
  370. };
  371.  
  372.  
  373. // some default uniform values
  374. const float defaultColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
  375. const int defaultTexUnits[] = { 0, 1 };
  376.  
  377.  
  378. // list of all unique shaders
  379. // this is a good idea to avoid multi-loading
  380. // those that are shared between programs
  381. union {
  382. struct {
  383. // vertex shaders
  384. a3_Shader passInstanceID_vs[1];
  385. a3_Shader passthru_transform_vs[1];
  386. a3_Shader passthru_transform_instanced_vs[1];
  387. a3_Shader passColor_transform_vs[1];
  388. a3_Shader passColor_transform_instanced_vs[1];
  389. a3_Shader passTexcoord_transform_vs[1];
  390. a3_Shader passPhong_obj_transform_vs[1];
  391.  
  392. // geometry shaders
  393. a3_Shader drawLine_gs[1];
  394. a3_Shader drawHermite_gs[1];
  395.  
  396. // fragment shaders
  397. a3_Shader drawColorUnif_fs[1];
  398. a3_Shader drawColorAttrib_fs[1];
  399. a3_Shader drawTexture_fs[1];
  400. a3_Shader drawPhong_obj_fs[1];
  401. };
  402. } shaderList = { 0 };
  403. a3_Shader *const shaderListPtr = (a3_Shader *)(&shaderList);
  404. const unsigned int numUniqueShaders = sizeof(shaderList) / sizeof(a3_Shader);
  405.  
  406. // descriptors to help load shaders; aligned with above list
  407. struct {
  408. a3_ShaderType shaderType;
  409. const char *filePath;
  410. } shaderDescriptor[] = {
  411. { a3shader_vertex, "../../../../resource/glsl/4x/vs/passInstanceID_vs4x.glsl" },
  412. { a3shader_vertex, "../../../../resource/glsl/4x/vs/passthru_transform_vs4x.glsl" },
  413. { a3shader_vertex, "../../../../resource/glsl/4x/vs/passthru_transform_instanced_vs4x.glsl" },
  414. { a3shader_vertex, "../../../../resource/glsl/4x/vs/passColor_transform_vs4x.glsl" },
  415. { a3shader_vertex, "../../../../resource/glsl/4x/vs/passColor_transform_instanced_vs4x.glsl" },
  416. { a3shader_vertex, "../../../../resource/glsl/4x/vs/passTexcoord_transform_vs4x.glsl" },
  417. { a3shader_vertex, "../../../../resource/glsl/4x/vs/passPhong_obj_transform_vs4x.glsl" },
  418.  
  419. { a3shader_geometry, "../../../../resource/glsl/4x/gs/drawLine_gs4x.glsl" },
  420. { a3shader_geometry, "../../../../resource/glsl/4x/gs/drawHermite_gs4x.glsl" },
  421.  
  422. { a3shader_fragment, "../../../../resource/glsl/4x/fs/drawColorUnif_fs4x.glsl" },
  423. { a3shader_fragment, "../../../../resource/glsl/4x/fs/drawColorAttrib_fs4x.glsl" },
  424. { a3shader_fragment, "../../../../resource/glsl/4x/fs/drawTexture_fs4x.glsl" },
  425. { a3shader_fragment, "../../../../resource/glsl/4x/fs/drawPhong_obj_fs4x.glsl" },
  426. };
  427.  
  428. // loading files and shaders
  429. a3_Stream shaderFile[1] = { 0 };
  430.  
  431. // load unique shaders:
  432. // - load file contents
  433. // - create and compile shader object
  434. // - release file contents
  435. for (i = 0; i < numUniqueShaders; ++i)
  436. {
  437. a3streamLoadContents(shaderFile, shaderDescriptor[i].filePath);
  438. a3shaderCreateFromSource(shaderListPtr + i, shaderDescriptor[i].shaderType, shaderFile->contents);
  439. a3streamReleaseContents(shaderFile);
  440. }
  441.  
  442.  
  443. // setup programs:
  444. // - create program object
  445. // - attach shader objects
  446.  
  447. // color attrib program
  448. currentDemoProg = demoState->prog_drawColor;
  449. a3shaderProgramCreate(currentDemoProg->program);
  450. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.passColor_transform_vs);
  451. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.drawColorAttrib_fs);
  452.  
  453. // color attrib instanced program
  454. currentDemoProg = demoState->prog_drawColorInstanced;
  455. a3shaderProgramCreate(currentDemoProg->program);
  456. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.passColor_transform_instanced_vs);
  457. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.drawColorAttrib_fs);
  458.  
  459. // uniform color program
  460. currentDemoProg = demoState->prog_drawColorUnif;
  461. a3shaderProgramCreate(currentDemoProg->program);
  462. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.passthru_transform_vs);
  463. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.drawColorUnif_fs);
  464.  
  465. // uniform color instanced program
  466. currentDemoProg = demoState->prog_drawColorUnifInstanced;
  467. a3shaderProgramCreate(currentDemoProg->program);
  468. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.passthru_transform_instanced_vs);
  469. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.drawColorUnif_fs);
  470.  
  471. // texturing program
  472. currentDemoProg = demoState->prog_drawTexture;
  473. a3shaderProgramCreate(currentDemoProg->program);
  474. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.passTexcoord_transform_vs);
  475. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.drawTexture_fs);
  476.  
  477. // lighting program
  478. currentDemoProg = demoState->prog_drawPhong_obj;
  479. a3shaderProgramCreate(currentDemoProg->program);
  480. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.passPhong_obj_transform_vs);
  481. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.drawPhong_obj_fs);
  482.  
  483. // draw line program
  484. currentDemoProg = demoState->prog_drawLine;
  485. a3shaderProgramCreate(currentDemoProg->program);
  486. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.passInstanceID_vs);
  487. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.drawLine_gs);
  488. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.drawColorAttrib_fs);
  489.  
  490. // draw curve program
  491. currentDemoProg = demoState->prog_drawCurve;
  492. a3shaderProgramCreate(currentDemoProg->program);
  493. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.passInstanceID_vs);
  494. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.drawHermite_gs);
  495. a3shaderProgramAttachShader(currentDemoProg->program, shaderList.drawColorAttrib_fs);
  496.  
  497.  
  498. // activate a primitive for validation
  499. // makes sure the specified geometry can draw using programs
  500. // good idea to activate the drawable with the most attributes
  501. a3vertexActivateDrawable(demoState->draw_axes);
  502.  
  503. // link and validate all programs
  504. for (i = 0; i < demoStateMaxCount_shaderProgram; ++i)
  505. {
  506. currentDemoProg = demoState->shaderProgram + i;
  507. a3shaderProgramLink(currentDemoProg->program);
  508. a3shaderProgramValidate(currentDemoProg->program);
  509. }
  510.  
  511. // if linking fails, contingency plan goes here
  512. // otherwise, release shaders
  513. for (i = 0; i < numUniqueShaders; ++i)
  514. a3shaderRelease(shaderListPtr + i);
  515.  
  516.  
  517. // prepare uniforms algorithmically instead of manually for all programs
  518. for (i = 0; i < demoStateMaxCount_shaderProgram; ++i)
  519. {
  520. // activate program
  521. currentDemoProg = demoState->shaderProgram + i;
  522. a3shaderProgramActivate(currentDemoProg->program);
  523.  
  524. // get uniform locations
  525. currentUnif = currentDemoProg->uniformLocation;
  526. for (j = 0; j < demoStateMaxCount_shaderProgramUniform; ++j)
  527. currentUnif[j] = a3shaderUniformGetLocation(currentDemoProg->program, uniformNames[j]);
  528.  
  529. // set default values for all programs that have a uniform that will
  530. // either never change or is consistent for all programs
  531. if ((uLocation = currentDemoProg->uMVP) >= 0)
  532. a3shaderUniformSendFloatMat(a3unif_mat4, 0, uLocation, 1, p3identityMat4.mm);
  533. if ((uLocation = currentDemoProg->uLocal) >= 0)
  534. a3shaderUniformSendFloatMat(a3unif_mat4, 0, uLocation, 1, p3identityMat4.mm);
  535. if ((uLocation = currentDemoProg->uLightPos_obj) >= 0)
  536. a3shaderUniformSendFloat(a3unif_vec4, uLocation, 1, p3wVec4.v);
  537. if ((uLocation = currentDemoProg->uEyePos_obj) >= 0)
  538. a3shaderUniformSendFloat(a3unif_vec4, uLocation, 1, p3wVec4.v);
  539. if ((uLocation = currentDemoProg->uLineColor) >= 0)
  540. a3shaderUniformSendFloat(a3unif_vec4, uLocation, 1, defaultColor);
  541. if ((uLocation = currentDemoProg->uCurveColor) >= 0)
  542. a3shaderUniformSendFloat(a3unif_vec4, uLocation, 1, defaultColor);
  543. if ((uLocation = currentDemoProg->uColor) >= 0)
  544. a3shaderUniformSendFloat(a3unif_vec4, uLocation, 1, defaultColor);
  545. if ((uLocation = currentDemoProg->uTex_dm) >= 0)
  546. a3shaderUniformSendInt(a3unif_single, uLocation, 1, defaultTexUnits + 0);
  547. if ((uLocation = currentDemoProg->uTex_sm) >= 0)
  548. a3shaderUniformSendInt(a3unif_single, uLocation, 1, defaultTexUnits + 1);
  549. }
  550.  
  551. //done
  552. a3shaderProgramDeactivate();
  553. a3vertexDeactivateDrawable();
  554. }
  555.  
  556.  
  557. //-----------------------------------------------------------------------------
  558. // release objects
  559. // this is where the union array style comes in handy; don't need a single
  560. // release statement for each and every object... just iterate and release!
  561.  
  562. // utility to unload textures
  563. void a3demo_unloadTextures(a3_DemoState *demoState)
  564. {
  565. a3_Texture *currentTex = demoState->texture,
  566. *const endTex = currentTex + demoStateMaxCount_texture;
  567.  
  568. while (currentTex < endTex)
  569. a3textureRelease(currentTex++);
  570. }
  571.  
  572. // utility to unload geometry
  573. void a3demo_unloadGeometry(a3_DemoState *demoState)
  574. {
  575. a3_BufferObject *currentBuff = demoState->drawDataBuffer,
  576. *const endBuff = currentBuff + demoStateMaxCount_drawDataBuffer;
  577. a3_VertexArrayDescriptor *currentVAO = demoState->vertexArray,
  578. *const endVAO = currentVAO + demoStateMaxCount_vertexArray;
  579. a3_VertexDrawable *currentDraw = demoState->drawable,
  580. *const endDraw = currentDraw + demoStateMaxCount_drawable;
  581.  
  582. while (currentBuff < endBuff)
  583. a3bufferRelease(currentBuff++);
  584. while (currentVAO < endVAO)
  585. a3vertexArrayReleaseDescriptor(currentVAO++);
  586. while (currentDraw < endDraw)
  587. a3vertexReleaseDrawable(currentDraw++);
  588. }
  589.  
  590.  
  591. // utility to unload shaders
  592. void a3demo_unloadShaders(a3_DemoState *demoState)
  593. {
  594. a3_DemoStateShaderProgram *currentProg = demoState->shaderProgram,
  595. *const endProg = currentProg + demoStateMaxCount_shaderProgram;
  596.  
  597. while (currentProg < endProg)
  598. a3shaderProgramRelease((currentProg++)->program);
  599. }
  600.  
  601.  
  602. //-----------------------------------------------------------------------------
  603.  
  604. // load animation
  605. void a3demo_loadAnimation(a3_DemoState *demoState)
  606. {
  607. unsigned int i;
  608.  
  609. // file streaming (if requested)
  610. a3_FileStream fileStream[1] = { 0 };
  611. const char *const animationStream = "./data/anim_skeletal.dat";
  612. //FILE *fp;
  613.  
  614. a3_HierarchyNodePose tmpPose[1];
  615.  
  616.  
  617. if (demoState->streaming && a3fileStreamOpenRead(fileStream, animationStream))
  618. {
  619. // load hierarchies
  620. a3fileStreamReadObject(fileStream, demoState->skeleton, (a3_FileStreamReadFunc)a3hierarchyLoadBinary);
  621.  
  622. // load base poses
  623. /*fp = (FILE *)fileStream->stream;
  624. fileStream->bytes += (unsigned int)fread(demoState->skeletonBaseOffsets, sizeof(p3vec3), sizeof(demoState->skeletonBaseOffsets) / sizeof(p3vec3), fp);*/
  625. }
  626. else if (!demoState->streaming || a3fileStreamOpenWrite(fileStream, animationStream))
  627. {
  628. // initialize skeletons and states
  629. p3vec3 skeletonBaseOffsets[64];
  630. // humanoid:
  631. // 0 __ root
  632. // 1 |\_ spine
  633. // 2 | \_ neck
  634. // 3 | |\_ head
  635. // 4 | |\_ r shoulder
  636. // 5 | | \_ r elbow
  637. // 6 | | \_ r wrist
  638. // 7 | | \_ r hand
  639. // 8 | \_ l shoulder
  640. // 9 | \_ l elbow
  641. // 10 | \_ l wrist
  642. // 11 | \_ l hand
  643. // 12 |\_ r hip
  644. // 13 | \_ r knee
  645. // 14 | \_ r ankle
  646. // 15 | \_ r foot
  647. // 16 \_ l hip
  648. // 17 \_ l knee
  649. // 18 \_ l ankle
  650. // 19 \_ l foot
  651. // count = 20
  652.  
  653. // ****TO-DO:
  654. // initialize and link skeleton
  655. a3hierarchyCreate(demoState->skeleton, 20, 0);
  656.  
  657. a3hierarchySetNode(demoState->skeleton, 0, -1, "root");
  658. a3hierarchySetNode(demoState->skeleton, 1, 0, "spine");
  659. a3hierarchySetNode(demoState->skeleton, 2, 1, "neck");
  660. a3hierarchySetNode(demoState->skeleton, 3, 2, "head");
  661. a3hierarchySetNode(demoState->skeleton, 4, 1, "r shoulder");
  662. a3hierarchySetNode(demoState->skeleton, 5, 4, "r elbow");
  663. a3hierarchySetNode(demoState->skeleton, 20, 5, "r wing");
  664. a3hierarchySetNode(demoState->skeleton, 6, 5, "r wrist");
  665. a3hierarchySetNode(demoState->skeleton, 7, 6, "r hand");
  666. a3hierarchySetNode(demoState->skeleton, 8, 1, "l shoulder");
  667. a3hierarchySetNode(demoState->skeleton, 9, 8, "l elbow");
  668. a3hierarchySetNode(demoState->skeleton, 21, 8, "l wing");
  669. a3hierarchySetNode(demoState->skeleton, 10, 9, "l wrist");
  670. a3hierarchySetNode(demoState->skeleton, 11, 10, "l hand");
  671. a3hierarchySetNode(demoState->skeleton, 12, 0, "r hip");
  672. a3hierarchySetNode(demoState->skeleton, 13, 12, "r knee");
  673. a3hierarchySetNode(demoState->skeleton, 14, 13, "r ankle");
  674. a3hierarchySetNode(demoState->skeleton, 15, 14, "r foot");
  675. a3hierarchySetNode(demoState->skeleton, 16, 0, "l hip");
  676. a3hierarchySetNode(demoState->skeleton, 17, 16, "l knee");
  677. a3hierarchySetNode(demoState->skeleton, 18, 17, "l ankle");
  678. a3hierarchySetNode(demoState->skeleton, 19, 18, "l foot");
  679.  
  680. // ****TO-DO:
  681. // set skeleton base pose offsets (just translate for now)
  682. // note: local relationships can be denoted like this: child -> parent
  683. // root -> world
  684. // spine -> root
  685. // neck -> spine
  686. // head -> neck
  687. // r shoulder -> neck
  688. // r elbow -> r shoulder
  689. // r wrist -> r elbow
  690. // r hand -> r wrist
  691. // l shoulder -> neck
  692. // l elbow -> l shoulder
  693. // l wrist -> l elbow
  694. // l hand -> l wrist
  695. // r hip -> root
  696. // r knee -> r hip
  697. // r ankle -> r knee
  698. // r foot -> r ankle
  699. // l hip -> root
  700. // l knee -> l hip
  701. // l ankle -> l knee
  702. // l foot -> l ankle
  703.  
  704.  
  705. // init pose set
  706. a3hierarchyPoseSetCreate(demoState->skeletonPoses, demoState->skeleton, 4);
  707.  
  708.  
  709. {
  710. //unsigned int j;
  711.  
  712. // spinal column
  713. p3real3Set(skeletonBaseOffsets[0].v, 0, 0, 4);
  714. p3real3Set(skeletonBaseOffsets[1].v, 0, .25, 2);
  715. p3real3Set(skeletonBaseOffsets[2].v, 0, -.25, 5);
  716. p3real3Set(skeletonBaseOffsets[3].v, 0, .5, 1);
  717.  
  718. // right ar
  719. p3real3Set(skeletonBaseOffsets[4].v, 1, 0, 0);
  720. p3real3Set(skeletonBaseOffsets[5].v, 1.5, .25, 0);
  721. p3real3Set(skeletonBaseOffsets[20].v, 0, 0, -1);
  722. p3real3Set(skeletonBaseOffsets[6].v, 1.5, -.25, 1);
  723. p3real3Set(skeletonBaseOffsets[7].v, 1, 0, 0);
  724.  
  725. // left arm
  726. p3real3Set(skeletonBaseOffsets[8].v, -1, 0, 0);
  727. p3real3Set(skeletonBaseOffsets[9].v, -1.5, .25, 0);
  728. p3real3Set(skeletonBaseOffsets[21].v, 0, 0, -1);
  729. p3real3Set(skeletonBaseOffsets[10].v, -1.5, -.25, 1);
  730. p3real3Set(skeletonBaseOffsets[11].v, -1, 0, 0);
  731.  
  732. // right le
  733. p3real3Set(skeletonBaseOffsets[12].v, 1, 1, -1);
  734. p3real3Set(skeletonBaseOffsets[13].v, 0, -1, -1);
  735. p3real3Set(skeletonBaseOffsets[14].v, 0, 0, -1);
  736. p3real3Set(skeletonBaseOffsets[15].v, 0, 1, 0);
  737.  
  738. // left leg
  739. p3real3Set(skeletonBaseOffsets[16].v, -1, 1, -1);
  740. p3real3Set(skeletonBaseOffsets[17].v, 0, -1, -1);
  741. p3real3Set(skeletonBaseOffsets[18].v, 0, 0, -1);
  742. p3real3Set(skeletonBaseOffsets[19].v, 0, 1, 0);
  743.  
  744. {
  745. // turn these into poses
  746. // convert base translations into poses
  747. //for (i = 0; i < demoState->skeleton->numNodes; ++i)
  748. //{
  749. // // put the translation into all poses
  750. // for (j = 0; j < demoState->skeletonPoses->keyPoseCount; ++j)
  751. // {
  752. // demoState->skeletonPoses->poseList[i][j].translation = skeletonBaseOffsets[i];
  753. // }
  754.  
  755. //}
  756.  
  757. for (i = 0; i < demoState->skeleton->numNodes; ++i)
  758. {
  759. // set temp node and add it to set
  760. a3hierarchyNodePoseSet(tmpPose, p3zeroVec4, skeletonBaseOffsets[i], p3oneVec3);
  761. a3hierarchyPoseSetInitNodePose(demoState->skeletonPoses, tmpPose, i, -1);
  762. }
  763. }
  764. }
  765.  
  766. // set rotations...manually
  767. i = a3hierarchyGetNodeIndex(demoState->skeleton, "r elbow");
  768. //demoState->skeletonPoses->poseList[i][1].orientation.z = 45;
  769. a3hierarchyNodePoseReset(tmpPose);
  770. tmpPose->orientation.z = 45;
  771. a3hierarchyPoseSetInitNodePose(demoState->skeletonPoses, tmpPose, i, 1);
  772.  
  773. // save hierarchies
  774. a3fileStreamWriteObject(fileStream, demoState->skeleton, (a3_FileStreamWriteFunc)a3hierarchySaveBinary);
  775.  
  776. // save base poses
  777. /*if (demoState->streaming)
  778. {
  779. fp = (FILE *)fileStream->stream;
  780. fileStream->bytes += (unsigned int)fwrite(demoState->skeletonBaseOffsets, sizeof(p3vec3), sizeof(demoState->skeletonBaseOffsets) / sizeof(p3vec3), fp);
  781. }*/
  782. }
  783.  
  784. // close stream
  785. a3fileStreamClose(fileStream);
  786.  
  787.  
  788. // initialize hierarchy states
  789. a3hierarchyStateCreate(demoState->skeletonState_procFK, demoState->skeleton);
  790. a3hierarchyStateCreate(demoState->skeletonState_ctrlFK, demoState->skeleton);
  791. a3hierarchyStateCreate(demoState->skeletonState_keyPoses, demoState->skeleton);
  792.  
  793. // set base states
  794. /*for (i = 0; i < demoState->skeleton->numNodes; ++i)
  795. {
  796. demoState->skeletonState_procFK->localSpaceTransforms[i].v3.xyz = demoState->skeletonBaseOffsets[i];
  797. demoState->skeletonState_ctrlFK->localSpaceTransforms[i].v3.xyz = demoState->skeletonBaseOffsets[i];
  798. }*/
  799.  
  800.  
  801. // set key pose
  802. // convert to matrices
  803. // solve fk
  804. a3hierarchyStateCopyKeyPose(demoState->skeletonState_procFK, demoState->skeletonPoses, 0);
  805. a3hierarchyStateCopyKeyPose(demoState->skeletonState_ctrlFK, demoState->skeletonPoses, 0);
  806. a3hierarchyStateCopyKeyPose(demoState->skeletonState_keyPoses, demoState->skeletonPoses, 0);
  807.  
  808.  
  809. a3hierarchyStateConvertPose(demoState->skeletonState_procFK, demoState->skeletonPoses, 0);
  810. a3hierarchyStateConvertPose(demoState->skeletonState_ctrlFK, demoState->skeletonPoses, 0);
  811. a3hierarchyStateConvertPose(demoState->skeletonState_keyPoses, demoState->skeletonPoses, 0);
  812.  
  813.  
  814.  
  815. a3kinematicsSolveForward(demoState->skeletonState_procFK);
  816. a3kinematicsSolveForward(demoState->skeletonState_ctrlFK);
  817. a3kinematicsSolveForward(demoState->skeletonState_keyPoses);
  818. }
  819.  
  820. // unload animation
  821. void a3demo_unloadAnimation(a3_DemoState *demoState)
  822. {
  823. // release resources
  824. a3hierarchyRelease(demoState->skeleton);
  825.  
  826. a3hierarchyStateRelease(demoState->skeletonState_procFK);
  827. a3hierarchyStateRelease(demoState->skeletonState_ctrlFK);
  828. }
  829.  
  830.  
  831. //-----------------------------------------------------------------------------
  832.  
  833. // initialize non-asset objects
  834. void a3demo_initScene(a3_DemoState *demoState)
  835. {
  836. unsigned int i;
  837. const float cameraAxisPos = 10.0f;
  838.  
  839. // all objects
  840. for (i = 0; i < demoStateMaxCount_sceneObject; ++i)
  841. a3demo_initSceneObject(demoState->sceneObject + i);
  842.  
  843. a3demo_setCameraSceneObject(demoState->sceneCamera, demoState->cameraObject);
  844. for (i = 0; i < demoStateMaxCount_camera; ++i)
  845. a3demo_initCamera(demoState->sceneCamera + i);
  846.  
  847. // cameras
  848. demoState->sceneCamera->znear = 1.00f;
  849. demoState->sceneCamera->zfar = 100.0f;
  850. demoState->sceneCamera->ctrlMoveSpeed = 10.0f;
  851. demoState->sceneCamera->ctrlRotateSpeed = 5.0f;
  852. demoState->sceneCamera->ctrlZoomSpeed = 5.0f;
  853.  
  854.  
  855. // camera's starting orientation depends on "vertical" axis
  856. // we want the exact same view in either case
  857. if (demoState->verticalAxis)
  858. {
  859. // vertical axis is Y
  860. demoState->sceneCamera->sceneObject->position.x = +cameraAxisPos;
  861. demoState->sceneCamera->sceneObject->position.y = +cameraAxisPos;
  862. demoState->sceneCamera->sceneObject->position.z = +cameraAxisPos;
  863. demoState->sceneCamera->sceneObject->euler.x = -15.0f;
  864. demoState->sceneCamera->sceneObject->euler.y = 45.0f;
  865. demoState->sceneCamera->sceneObject->euler.z = 0.0f;
  866. }
  867. else
  868. {
  869. // vertical axis is Z
  870. demoState->sceneCamera->sceneObject->position.x = +cameraAxisPos;
  871. demoState->sceneCamera->sceneObject->position.y = -cameraAxisPos;
  872. demoState->sceneCamera->sceneObject->position.z = +cameraAxisPos;
  873. demoState->sceneCamera->sceneObject->euler.x = 75.0f;
  874. demoState->sceneCamera->sceneObject->euler.y = 0.0f;
  875. demoState->sceneCamera->sceneObject->euler.z = 45.0f;
  876. }
  877.  
  878. // demoState->sceneCamera->sceneObject->position.x = 8.0f;
  879. // demoState->sceneCamera->sceneObject->position.y = 4.0f;
  880. // demoState->sceneCamera->sceneObject->position.z = cameraAxisPos;
  881.  
  882. // same fovy to start
  883. demoState->sceneCamera->fovy = realSixty;
  884.  
  885.  
  886. // light
  887. if (demoState->verticalAxis)
  888. {
  889. demoState->lightObject->position.x = +cameraAxisPos;
  890. demoState->lightObject->position.y = +cameraAxisPos;
  891. demoState->lightObject->position.z = -cameraAxisPos;
  892. }
  893. else
  894. {
  895. demoState->lightObject->position.x = +cameraAxisPos;
  896. demoState->lightObject->position.y = +cameraAxisPos;
  897. demoState->lightObject->position.z = +cameraAxisPos;
  898. }
  899.  
  900.  
  901. // skeletal
  902. demoState->displayBoneAxes = 1;
  903. demoState->cycleTime = 0.0f;
  904. demoState->cycleDuration = 2.0f;
  905.  
  906. }
  907.  
  908.  
  909. //-----------------------------------------------------------------------------
  910.  
  911. // confirm that all graphics objects were unloaded
  912. void a3demo_validateUnload(const a3_DemoState *demoState)
  913. {
  914. unsigned int handle;
  915. const a3_Texture *currentTex = demoState->texture,
  916. *const endTex = currentTex + demoStateMaxCount_texture;
  917. const a3_BufferObject *currentBuff = demoState->drawDataBuffer,
  918. *const endBuff = currentBuff + demoStateMaxCount_drawDataBuffer;
  919. const a3_VertexArrayDescriptor *currentVAO = demoState->vertexArray,
  920. *const endVAO = currentVAO + demoStateMaxCount_vertexArray;
  921. const a3_DemoStateShaderProgram *currentProg = demoState->shaderProgram,
  922. *const endProg = currentProg + demoStateMaxCount_shaderProgram;
  923.  
  924. handle = 0;
  925. currentTex = demoState->texture;
  926. while (currentTex < endTex)
  927. handle += (currentTex++)->handle->handle;
  928. if (handle)
  929. printf("\n A3 Warning: One or more texture not released.");
  930.  
  931. handle = 0;
  932. currentBuff = demoState->drawDataBuffer;
  933. while (currentBuff < endBuff)
  934. handle += (currentBuff++)->handle->handle;
  935. if (handle)
  936. printf("\n A3 Warning: One or more draw data buffers not released.");
  937.  
  938. handle = 0;
  939. currentVAO = demoState->vertexArray;
  940. while (currentVAO < endVAO)
  941. handle += (currentVAO++)->handle->handle;
  942. if (handle)
  943. printf("\n A3 Warning: One or more vertex arrays not released.");
  944.  
  945. handle = 0;
  946. currentProg = demoState->shaderProgram;
  947. while (currentProg < endProg)
  948. handle += (currentProg++)->program->handle->handle;
  949. if (handle)
  950. printf("\n A3 Warning: One or more shader programs not released.");
  951. }
  952.  
  953.  
  954. //-----------------------------------------------------------------------------
  955.  
  956. void a3demo_refresh(a3_DemoState *demoState)
  957. {
  958. // the handle release callbacks are no longer valid; since the library was
  959. // reloaded, old function pointers are out of scope!
  960. // could reload everything, but that would mean rebuilding GPU data...
  961. // ...or just set new function pointers!
  962.  
  963. a3_Texture *currentTex = demoState->texture,
  964. *const endTex = currentTex + demoStateMaxCount_texture;
  965. a3_BufferObject *currentBuff = demoState->drawDataBuffer,
  966. *const endBuff = currentBuff + demoStateMaxCount_drawDataBuffer;
  967. a3_VertexArrayDescriptor *currentVAO = demoState->vertexArray,
  968. *const endVAO = currentVAO + demoStateMaxCount_vertexArray;
  969. a3_DemoStateShaderProgram *currentProg = demoState->shaderProgram,
  970. *const endProg = currentProg + demoStateMaxCount_shaderProgram;
  971.  
  972. while (currentTex < endTex)
  973. a3textureHandleUpdateReleaseCallback(currentTex++);
  974. while (currentBuff < endBuff)
  975. a3bufferHandleUpdateReleaseCallback(currentBuff++);
  976. while (currentVAO < endVAO)
  977. a3vertexArrayHandleUpdateReleaseCallback(currentVAO++);
  978. while (currentProg < endProg)
  979. a3shaderProgramHandleUpdateReleaseCallback((currentProg++)->program);
  980. }
  981.  
  982. void a3demo_update(a3_DemoState *demoState, double dt)
  983. {
  984. unsigned int i;
  985.  
  986. a3_HierarchyState *currentHierarchyState;
  987.  
  988. float relativeTime;
  989. p3vec4 tmpPos;
  990. p3mat4 *tmpMatPtr;
  991.  
  992.  
  993. // controls
  994.  
  995. // move and rotate camera
  996. a3demo_moveSceneObject(demoState->camera->sceneObject, (float)dt * demoState->camera->ctrlMoveSpeed,
  997. (p3real)a3keyboardGetDifference(demoState->keyboard, a3key_D, a3key_A),
  998. (p3real)a3keyboardGetDifference(demoState->keyboard, a3key_E, a3key_Q),
  999. (p3real)a3keyboardGetDifference(demoState->keyboard, a3key_S, a3key_W)
  1000. );
  1001. if (a3mouseIsHeld(demoState->mouse, a3mouse_left))
  1002. {
  1003. const p3real azimuth = -(p3real)a3mouseGetDeltaX(demoState->mouse);
  1004. const p3real elevation = -(p3real)a3mouseGetDeltaY(demoState->mouse);
  1005.  
  1006. // this really defines which way is "up"
  1007. // mouse's Y motion controls pitch, but X can control yaw or roll
  1008. // controlling yaw makes Y axis seem "up", roll makes Z seem "up"
  1009. a3demo_rotateSceneObject(demoState->camera->sceneObject, (float)dt * demoState->camera->ctrlRotateSpeed,
  1010. // pitch: vertical tilt
  1011. elevation,
  1012. // yaw/roll depends on "vertical" axis: if y, yaw; if z, roll
  1013. demoState->verticalAxis ? azimuth : realZero,
  1014. demoState->verticalAxis ? realZero : azimuth);
  1015. }
  1016.  
  1017.  
  1018. // update scene objects
  1019. for (i = 0; i < demoStateMaxCount_sceneObject; ++i)
  1020. a3demo_updateSceneObject(demoState->sceneObject + i);
  1021.  
  1022. // update cameras
  1023. for (i = 0; i < demoStateMaxCount_camera; ++i)
  1024. a3demo_updateCameraViewProjection(demoState->camera + i);
  1025.  
  1026.  
  1027. // animation: solve kinematics here
  1028.  
  1029. // ****TO-DO: proper kinematics solution based on current mode
  1030. switch (demoState->kinematicsMode)
  1031. {
  1032. // procedural animation FK
  1033. case 0:
  1034. currentHierarchyState = demoState->skeletonState_procFK;
  1035.  
  1036. // ****TO-DO: update
  1037. demoState->cycleTime += (float)dt;
  1038. if (demoState->cycleTime >= demoState->cycleDuration)
  1039. {
  1040. demoState->cycleTime -= demoState->cycleDuration;
  1041. }
  1042. relativeTime = demoState->cycleTime / demoState->cycleDuration;
  1043.  
  1044. // curved time boi
  1045. relativeTime = p3cosd(360 * relativeTime) * 0.5 + 0.5;
  1046.  
  1047. // bend elbow
  1048. i = a3hierarchyGetNodeIndex(currentHierarchyState->hierarchy, "r elbow");
  1049. tmpMatPtr = currentHierarchyState->localSpaceTransforms[i].m;
  1050. tmpPos = tmpMatPtr->v3;
  1051. p3real4x4SetRotateZ(tmpMatPtr->m, relativeTime * 45);
  1052.  
  1053. tmpMatPtr->v3 = tmpPos;
  1054.  
  1055. i = a3hierarchyGetNodeIndex(currentHierarchyState->hierarchy, "l elbow");
  1056. tmpMatPtr = currentHierarchyState->localSpaceTransforms[i].m;
  1057. tmpPos = tmpMatPtr->v3;
  1058. p3real4x4SetRotateZ(tmpMatPtr->m, relativeTime * 45);
  1059.  
  1060. tmpMatPtr->v3 = tmpPos;
  1061.  
  1062. // neck
  1063. i = a3hierarchyGetNodeIndex(currentHierarchyState->hierarchy, "neck");
  1064. tmpMatPtr = currentHierarchyState->localSpaceTransforms[i].m;
  1065. tmpPos = tmpMatPtr->v3;
  1066. p3real4x4SetRotateX(tmpMatPtr->m, relativeTime * 60);
  1067.  
  1068. tmpMatPtr->v3 = tmpPos;
  1069.  
  1070. i = a3hierarchyGetNodeIndex(currentHierarchyState->hierarchy, "spine");
  1071. tmpMatPtr = currentHierarchyState->localSpaceTransforms[i].m;
  1072. tmpPos = tmpMatPtr->v3;
  1073. p3real4x4SetRotateX(tmpMatPtr->m, relativeTime * -135);
  1074.  
  1075. tmpMatPtr->v3 = tmpPos;
  1076.  
  1077.  
  1078. // r shoulder
  1079. i = a3hierarchyGetNodeIndex(currentHierarchyState->hierarchy, "r shoulder");
  1080. tmpMatPtr = currentHierarchyState->localSpaceTransforms[i].m;
  1081. tmpPos = tmpMatPtr->v3;
  1082. p3real4x4SetRotateY(tmpMatPtr->m, relativeTime * 30);
  1083.  
  1084. tmpMatPtr->v3 = tmpPos;
  1085.  
  1086. // l shoulder
  1087. i = a3hierarchyGetNodeIndex(currentHierarchyState->hierarchy, "l shoulder");
  1088. tmpMatPtr = currentHierarchyState->localSpaceTransforms[i].m;
  1089. tmpPos = tmpMatPtr->v3;
  1090. p3real4x4SetRotateY(tmpMatPtr->m, relativeTime * 30);
  1091.  
  1092. tmpMatPtr->v3 = tmpPos;
  1093.  
  1094. // root
  1095. i = a3hierarchyGetNodeIndex(currentHierarchyState->hierarchy, "root");
  1096. tmpMatPtr = currentHierarchyState->localSpaceTransforms[i].m;
  1097. tmpPos = tmpMatPtr->v3;
  1098. p3real4x4SetRotateX(tmpMatPtr->m, relativeTime * -90);
  1099. p3real4x4SetRotateZ(tmpMatPtr->m, relativeTime * 90);
  1100.  
  1101. tmpMatPtr->v3 = tmpPos;
  1102.  
  1103. // hips
  1104. i = a3hierarchyGetNodeIndex(currentHierarchyState->hierarchy, "r hip");
  1105. tmpMatPtr = currentHierarchyState->localSpaceTransforms[i].m;
  1106. tmpPos = tmpMatPtr->v3;
  1107. p3real4x4SetRotateX(tmpMatPtr->m, relativeTime * 30);
  1108.  
  1109. tmpMatPtr->v3 = tmpPos;
  1110.  
  1111. i = a3hierarchyGetNodeIndex(currentHierarchyState->hierarchy, "l hip");
  1112. tmpMatPtr = currentHierarchyState->localSpaceTransforms[i].m;
  1113. tmpPos = tmpMatPtr->v3;
  1114. p3real4x4SetRotateX(tmpMatPtr->m, relativeTime * -30);
  1115.  
  1116. tmpMatPtr->v3 = tmpPos;
  1117.  
  1118. // finally do IK
  1119. a3kinematicsSolveForward(currentHierarchyState);
  1120. break;
  1121.  
  1122. // user-controlled joints FK
  1123. case 1:
  1124. currentHierarchyState = demoState->skeletonState_ctrlFK;
  1125.  
  1126. // toggle active joint to be controlled
  1127. if (a3XboxControlIsChanged(demoState->xcontrol, a3xbox_DPAD_right) > 0
  1128. || a3keyboardIsChanged(demoState->keyboard, a3key_rightArrow) > 0)
  1129. {
  1130. demoState->skeletonControlIndex =
  1131. (demoState->skeletonControlIndex + 1) %
  1132. currentHierarchyState->hierarchy->numNodes;
  1133. }
  1134. else if (a3XboxControlIsChanged(demoState->xcontrol, a3xbox_DPAD_left) > 0
  1135. || a3keyboardIsChanged(demoState->keyboard, a3key_leftArrow) > 0)
  1136. {
  1137. demoState->skeletonControlIndex =
  1138. (demoState->skeletonControlIndex + currentHierarchyState->hierarchy->numNodes - 1) %
  1139. currentHierarchyState->hierarchy->numNodes;
  1140. }
  1141.  
  1142. // shorthand of index
  1143. i = demoState->skeletonControlIndex;
  1144.  
  1145. // update joint based on input
  1146. {
  1147. const float rotateRate = (float)(90.0 * dt);
  1148. p3vec3 eulerDelta;
  1149.  
  1150. if (a3XboxControlIsConnected(demoState->xcontrol))
  1151. {
  1152. double rJoystick[2], rTrigger[1], lTrigger[1];
  1153. a3XboxControlGetRightJoystick(demoState->xcontrol, rJoystick);
  1154. a3XboxControlGetTriggers(demoState->xcontrol, lTrigger, rTrigger);
  1155.  
  1156. eulerDelta.x = (float)(rJoystick[0]);
  1157. eulerDelta.y = (float)(rJoystick[1]);
  1158. eulerDelta.z = (float)(*rTrigger - *lTrigger);
  1159. }
  1160. else
  1161. {
  1162. eulerDelta.x = (float)(a3keyboardGetDifference(demoState->keyboard, a3key_L, a3key_J));
  1163. eulerDelta.y = (float)(a3keyboardGetDifference(demoState->keyboard, a3key_I, a3key_K));
  1164. eulerDelta.z = (float)(a3keyboardGetDifference(demoState->keyboard, a3key_O, a3key_U));
  1165. }
  1166.  
  1167. demoState->skeletonEulers[i].x = p3trigValid_sind(demoState->skeletonEulers[i].x + rotateRate * eulerDelta.x);
  1168. demoState->skeletonEulers[i].y = p3trigValid_sind(demoState->skeletonEulers[i].y + rotateRate * eulerDelta.y);
  1169. demoState->skeletonEulers[i].z = p3trigValid_sind(demoState->skeletonEulers[i].z + rotateRate * eulerDelta.z);
  1170. }
  1171.  
  1172. // ****TO-DO: update
  1173.  
  1174.  
  1175.  
  1176. break;
  1177.  
  1178. case 2:
  1179. currentHierarchyState = demoState->skeletonState_keyPoses;
  1180.  
  1181. if (a3XboxControlIsChanged(demoState->xcontrol, a3xbox_DPAD_right) > 0
  1182. || a3keyboardIsChanged(demoState->keyboard, a3key_rightArrow) > 0)
  1183. {
  1184. demoState->selectKeyPoseIndex =
  1185. (demoState->selectKeyPoseIndex + 1) %
  1186. demoState->skeletonPoses->keyPoseCount;
  1187. }
  1188. else if (a3XboxControlIsChanged(demoState->xcontrol, a3xbox_DPAD_left) > 0
  1189. || a3keyboardIsChanged(demoState->keyboard, a3key_leftArrow) > 0)
  1190. {
  1191. demoState->selectKeyPoseIndex =
  1192. (demoState->selectKeyPoseIndex + demoState->skeletonPoses->keyPoseCount - 1) %
  1193. demoState->skeletonPoses->keyPoseCount;
  1194. }
  1195.  
  1196. // copy key pose
  1197. // convert to matrices
  1198. // solve fk
  1199. a3hierarchyStateCopyKeyPose(currentHierarchyState, demoState->skeletonPoses, demoState->selectKeyPoseIndex);
  1200. a3hierarchyStateConvertPose(currentHierarchyState, demoState->skeletonPoses, 0);
  1201. a3kinematicsSolveForward(currentHierarchyState);
  1202.  
  1203. break;
  1204. }
  1205.  
  1206.  
  1207. // update input
  1208. a3mouseUpdate(demoState->mouse);
  1209. a3keyboardUpdate(demoState->keyboard);
  1210. a3XboxControlUpdate(demoState->xcontrol);
  1211. }
  1212.  
  1213. void a3demo_render(a3_DemoState *demoState)
  1214. {
  1215. const a3_VertexDrawable *currentDrawable;
  1216. const a3_DemoStateShaderProgram *currentDemoProgram;
  1217.  
  1218. const int useVerticalY = demoState->verticalAxis;
  1219.  
  1220. unsigned int i;
  1221.  
  1222.  
  1223. // grid lines highlight
  1224. // if Y axis is up, give it a greenish hue
  1225. // if Z axis is up, a bit of blue
  1226. const float gridColor[] = {
  1227. 0.15f,
  1228. useVerticalY ? 0.25f : 0.20f,
  1229. useVerticalY ? 0.20f : 0.25f,
  1230. 1.0f
  1231. };
  1232.  
  1233.  
  1234. // RGB
  1235. const float rgba4[] = {
  1236. 1.0f, 0.0f, 0.0f, 1.0f,
  1237. 0.0f, 1.0f, 0.0f, 1.0f,
  1238. 0.0f, 0.0f, 1.0f, 1.0f,
  1239. 0.5f, 0.5f, 0.5f, 0.5f,
  1240. };
  1241.  
  1242. // joint shape color: orange
  1243. const float jointColor[] = {
  1244. 1.0f, 0.5f, 0.0f, 1.0f
  1245. };
  1246.  
  1247. // bone shape color: blue
  1248. const float boneColor[] = {
  1249. 0.0f, 0.5f, 1.0f, 1.0f
  1250. };
  1251.  
  1252.  
  1253. // model transformations (if needed)
  1254. const p3mat4 convertY2Z = {
  1255. +1.0f, 0.0f, 0.0f, 0.0f,
  1256. 0.0f, 0.0f, +1.0f, 0.0f,
  1257. 0.0f, -1.0f, 0.0f, 0.0f,
  1258. 0.0f, 0.0f, 0.0f, +1.0f,
  1259. };
  1260. const p3mat4 convertZ2Y = {
  1261. +1.0f, 0.0f, 0.0f, 0.0f,
  1262. 0.0f, 0.0f, -1.0f, 0.0f,
  1263. 0.0f, +1.0f, 0.0f, 0.0f,
  1264. 0.0f, 0.0f, 0.0f, +1.0f,
  1265. };
  1266. const p3mat4 convertZ2X = {
  1267. 0.0f, 0.0f, -1.0f, 0.0f,
  1268. 0.0f, +1.0f, 0.0f, 0.0f,
  1269. +1.0f, 0.0f, 0.0f, 0.0f,
  1270. 0.0f, 0.0f, 0.0f, +1.0f,
  1271. };
  1272. const p3mat4 downscale5x = {
  1273. 0.2f, 0.0f, 0.0f, 0.0f,
  1274. 0.0f, 0.2f, 0.0f, 0.0f,
  1275. 0.0f, 0.0f, 0.2f, 0.0f,
  1276. 0.0f, 0.0f, 0.0f, 1.0f,
  1277. };
  1278.  
  1279. // transformed vectors
  1280. // p3vec4 lightPos_obj, eyePos_obj;
  1281.  
  1282. // final model matrix and full matrix stack
  1283. p3mat4 modelMat = p3identityMat4, modelMatInv = p3identityMat4, modelViewProjectionMat = p3identityMat4;
  1284. // p3mat4 modelMatOrig;
  1285.  
  1286. // current scene object being rendered, for convenience
  1287. a3_DemoSceneObject *currentSceneObject;
  1288.  
  1289.  
  1290. // reset viewport and clear buffers
  1291. a3framebufferDeactivateSetViewport(a3fbo_depth24, -demoState->frameBorder, -demoState->frameBorder, demoState->frameWidth, demoState->frameHeight);
  1292. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  1293.  
  1294.  
  1295. // draw objects:
  1296. // - correct "up" axis if needed
  1297. // - calculate full MVP matrix
  1298. // - move lighting objects' positions into object space
  1299. // - send uniforms
  1300. // - draw
  1301.  
  1302. currentSceneObject = demoState->skeletonObject;
  1303.  
  1304. /*
  1305. // draw model
  1306. currentDrawable = demoState->draw_teapot;
  1307. if (!useVerticalY) // teapot's axis is Y
  1308. {
  1309. modelMatOrig = currentSceneObject->modelMat;
  1310. p3real4x4ProductTransform(modelMat.m, convertY2Z.m, modelMatOrig.m);
  1311. p3real4TransformMul(convertZ2Y.m, modelMat.v3.v);
  1312. }
  1313. else
  1314. {
  1315. modelMatOrig = modelMat = currentSceneObject->modelMat;
  1316. modelMatInv = currentSceneObject->modelMatInv;
  1317. }
  1318. p3real4x4TransformInverseIgnoreScale(modelMatInv.m, modelMat.m);
  1319. p3real4x4Product(modelViewProjectionMat.m, demoState->camera->viewProjectionMat.m, modelMat.m);
  1320. p3real4TransformProduct(lightPos_obj.v, modelMatInv.m, demoState->lightObject->modelMat.v3.v);
  1321. p3real4TransformProduct(eyePos_obj.v, modelMatInv.m, demoState->cameraObject->modelMat.v3.v);
  1322.  
  1323. currentDemoProgram = demoState->prog_drawPhong_obj;
  1324. a3shaderProgramActivate(currentDemoProgram->program);
  1325. a3shaderUniformSendFloatMat(a3unif_mat4, 0, currentDemoProgram->uMVP, 1, modelViewProjectionMat.mm);
  1326. a3shaderUniformSendFloat(a3unif_vec4, currentDemoProgram->uLightPos_obj, 1, lightPos_obj.v);
  1327. a3shaderUniformSendFloat(a3unif_vec4, currentDemoProgram->uEyePos_obj, 1, eyePos_obj.v);
  1328. a3textureActivate(demoState->tex_checker, a3tex_unit00);
  1329. a3textureActivate(demoState->tex_checker, a3tex_unit01);
  1330. a3vertexActivateAndRenderDrawable(currentDrawable);
  1331. */
  1332.  
  1333. // draw grid aligned to world
  1334. currentDemoProgram = demoState->prog_drawColorUnif;
  1335. a3shaderProgramActivate(currentDemoProgram->program);
  1336. currentDrawable = demoState->draw_grid;
  1337. modelViewProjectionMat = demoState->camera->viewProjectionMat;
  1338. if (useVerticalY)
  1339. p3real4x4ConcatL(modelViewProjectionMat.m, convertZ2Y.m);
  1340. a3shaderUniformSendFloatMat(a3unif_mat4, 0, currentDemoProgram->uMVP, 1, modelViewProjectionMat.mm);
  1341. a3shaderUniformSendFloat(a3unif_vec4, currentDemoProgram->uColor, 1, gridColor);
  1342. a3vertexActivateAndRenderDrawable(currentDrawable);
  1343.  
  1344.  
  1345. // overlay items
  1346. glDisable(GL_DEPTH_TEST);
  1347.  
  1348. /*
  1349. // draw gimbal
  1350. currentDemoProgram = demoState->prog_drawColorUnif;
  1351. a3shaderProgramActivate(currentDemoProgram->program);
  1352.  
  1353. glCullFace(GL_FRONT);
  1354. currentDrawable = demoState->draw_gimbal;
  1355. a3vertexActivateDrawable(currentDrawable);
  1356. p3real4x4Product(modelViewProjectionMat.m, demoState->camera->viewProjectionMat.m, modelMatOrig.m);
  1357. a3shaderUniformSendFloatMat(a3unif_mat4, 0, currentDemoProgram->uMVP, 1, modelViewProjectionMat.mm);
  1358. a3shaderUniformSendFloat(a3unif_vec4, currentDemoProgram->uColor, 1, rgba4 + 12);
  1359. a3vertexRenderActiveDrawable();
  1360. glCullFace(GL_BACK);
  1361.  
  1362. currentDrawable = demoState->draw_ring;
  1363. a3vertexActivateDrawable(currentDrawable);
  1364. p3real4x4Product(modelViewProjectionMat.m, demoState->camera->viewProjectionMat.m, modelMatOrig.m);
  1365. a3shaderUniformSendFloatMat(a3unif_mat4, 0, currentDemoProgram->uMVP, 1, modelViewProjectionMat.mm);
  1366. a3shaderUniformSendFloat(a3unif_vec4, currentDemoProgram->uColor, 1, rgba4 + 8);
  1367. a3vertexRenderActiveDrawable();
  1368. p3real4x4Product(modelViewProjectionMat.m, demoState->camera->viewProjectionMat.m, modelMatOrig.m);
  1369. p3real4x4ConcatL(modelViewProjectionMat.m, convertZ2Y.m);
  1370. a3shaderUniformSendFloatMat(a3unif_mat4, 0, currentDemoProgram->uMVP, 1, modelViewProjectionMat.mm);
  1371. a3shaderUniformSendFloat(a3unif_vec4, currentDemoProgram->uColor, 1, rgba4 + 4);
  1372. a3vertexRenderActiveDrawable();
  1373. p3real4x4Product(modelViewProjectionMat.m, demoState->camera->viewProjectionMat.m, modelMatOrig.m);
  1374. p3real4x4ConcatL(modelViewProjectionMat.m, convertZ2X.m);
  1375. a3shaderUniformSendFloatMat(a3unif_mat4, 0, currentDemoProgram->uMVP, 1, modelViewProjectionMat.mm);
  1376. a3shaderUniformSendFloat(a3unif_vec4, currentDemoProgram->uColor, 1, rgba4 + 0);
  1377. a3vertexRenderActiveDrawable();
  1378. */
  1379.  
  1380.  
  1381. // ****TO-DO: draw skeleton
  1382. {
  1383. const a3_HierarchyState *currentHierarchyState;
  1384.  
  1385. // matrices for rendering bones relative to skeleton
  1386. p3mat4 boneMatrices[64], *boneMatrixPtr;
  1387.  
  1388. // temporary matrix pointers
  1389. const p3mat4 *nodeTransformPtr, *parentTransformPtr;
  1390. int parentIndex;
  1391.  
  1392. // tmp NDC vector for screen-space renders
  1393. p3vec4 posNDC;
  1394.  
  1395.  
  1396. currentDemoProgram = demoState->prog_drawColorUnifInstanced;
  1397. a3shaderProgramActivate(currentDemoProgram->program);
  1398.  
  1399. // select state
  1400. switch (demoState->kinematicsMode)
  1401. {
  1402. case 0:
  1403. currentHierarchyState = demoState->skeletonState_procFK;
  1404. break;
  1405. case 1:
  1406. currentHierarchyState = demoState->skeletonState_ctrlFK;
  1407. break;
  1408. case 2:
  1409. currentHierarchyState = demoState->skeletonState_keyPoses;
  1410. break;
  1411. }
  1412.  
  1413. // calculate and send viewing matrix for skeleton object
  1414. modelMat = currentSceneObject->modelMat;
  1415. modelMatInv = currentSceneObject->modelMatInv;
  1416. p3real4x4Product(modelViewProjectionMat.m, demoState->camera->viewProjectionMat.m, modelMat.m);
  1417. a3shaderUniformSendFloatMat(a3unif_mat4, 0, currentDemoProgram->uMVP, 1, modelViewProjectionMat.mm);
  1418.  
  1419. // draw joints
  1420. currentDrawable = demoState->draw_joint;
  1421. a3shaderUniformSendFloat(a3unif_vec4, currentDemoProgram->uColor, 1, jointColor);
  1422. a3shaderUniformSendFloatMat(a3unif_mat4, 0, currentDemoProgram->uLocal,
  1423. currentHierarchyState->hierarchy->numNodes, (float *)currentHierarchyState->objectSpaceTransforms);
  1424. a3vertexActivateAndRenderDrawableInstanced(currentDrawable, currentHierarchyState->hierarchy->numNodes);
  1425.  
  1426. // draw bones
  1427. // first calculate their object-space orientations to make them appear to
  1428. // link joints together (it's a Frenet frame)
  1429. for (i = 0; i < currentHierarchyState->hierarchy->numNodes; ++i)
  1430. {
  1431. boneMatrixPtr = boneMatrices + i;
  1432. parentIndex = currentHierarchyState->hierarchy->nodes[i].parentIndex;
  1433. if (parentIndex >= 0)
  1434. {
  1435. nodeTransformPtr = currentHierarchyState->objectSpaceTransforms + i;
  1436. parentTransformPtr = currentHierarchyState->objectSpaceTransforms + parentIndex;
  1437.  
  1438. // reset
  1439. *boneMatrixPtr = p3identityMat4;
  1440.  
  1441. // set position
  1442. boneMatrixPtr->v3 = parentTransformPtr->v3;
  1443.  
  1444. // set direction column (local Z)
  1445. p3real4Diff(boneMatrixPtr->v2.v, nodeTransformPtr->v3.v, boneMatrixPtr->v3.v);
  1446.  
  1447. // set other basis vectors
  1448. p3real3CrossUnit(boneMatrixPtr->v0.v, (boneMatrixPtr->y2 != 0.0f ? p3zVec3.v : p3yVec3.v), boneMatrixPtr->v2.v);
  1449. p3real3CrossUnit(boneMatrixPtr->v1.v, boneMatrixPtr->v2.v, boneMatrixPtr->v0.v);
  1450. }
  1451. else
  1452. memset(boneMatrixPtr, 0, sizeof(p3mat4));
  1453. }
  1454. currentDrawable = demoState->draw_bone;
  1455. a3shaderUniformSendFloat(a3unif_vec4, currentDemoProgram->uColor, 1, boneColor);
  1456. a3shaderUniformSendFloatMat(a3unif_mat4, 0, currentDemoProgram->uLocal,
  1457. currentHierarchyState->hierarchy->numNodes, (float *)boneMatrices);
  1458. a3vertexActivateAndRenderDrawableInstanced(currentDrawable, currentHierarchyState->hierarchy->numNodes);
  1459.  
  1460. // finally, draw small coordinate axes on bones to show
  1461. // their actual orientation
  1462. if (demoState->displayBoneAxes)
  1463. {
  1464. currentDemoProgram = demoState->prog_drawColorInstanced;
  1465. a3shaderProgramActivate(currentDemoProgram->program);
  1466.  
  1467. a3shaderUniformSendFloatMat(a3unif_mat4, 0, currentDemoProgram->uMVP, 1, modelViewProjectionMat.mm);
  1468.  
  1469. // apply downscale to all bone matrices
  1470. for (i = 0; i < currentHierarchyState->hierarchy->numNodes; ++i)
  1471. p3real4x4Product(boneMatrices[i].m, currentHierarchyState->objectSpaceTransforms[i].m, downscale5x.m);
  1472.  
  1473. currentDrawable = demoState->draw_axes;
  1474. a3shaderUniformSendFloatMat(a3unif_mat4, 0, currentDemoProgram->uLocal,
  1475. currentHierarchyState->hierarchy->numNodes, (float *)boneMatrices);
  1476. a3vertexActivateAndRenderDrawableInstanced(currentDrawable, currentHierarchyState->hierarchy->numNodes);
  1477.  
  1478. // also display joint names
  1479. if (demoState->textInit)
  1480. {
  1481. a3shaderProgramDeactivate();
  1482.  
  1483. // concatenate bone matrices with MVP to get full transformation
  1484. // sequence for each joint
  1485. // get position of each joint in NDC, draw text using NDC position
  1486. for (i = 0; i < currentHierarchyState->hierarchy->numNodes; ++i)
  1487. {
  1488. p3real4x4ConcatR(modelViewProjectionMat.m, boneMatrices[i].m);
  1489. p3real4Real4x4Product(posNDC.v, boneMatrices[i].m, p3wVec4.v);
  1490. p3real4DivS(posNDC.v, posNDC.w);
  1491.  
  1492. a3textDraw(demoState->text, posNDC.x, posNDC.y, posNDC.z, 1.0f, 1.0f, 1.0f, 1.0f,
  1493. currentHierarchyState->hierarchy->nodes[i].name);
  1494. }
  1495. }
  1496. }
  1497.  
  1498. // display edit joints
  1499. switch (demoState->kinematicsMode)
  1500. {
  1501. // controlled FK
  1502. case 1:
  1503. a3shaderProgramDeactivate();
  1504.  
  1505. i = demoState->skeletonControlIndex;
  1506. p3real4x4Product(boneMatrices[i].m, currentHierarchyState->objectSpaceTransforms[i].m, downscale5x.m);
  1507. p3real4x4ConcatR(modelViewProjectionMat.m, boneMatrices[i].m);
  1508. p3real4Real4x4Product(posNDC.v, boneMatrices[i].m, p3wVec4.v);
  1509. p3real4DivS(posNDC.v, posNDC.w);
  1510.  
  1511. // change color over time
  1512. if ((int)(demoState->renderTimer->totalTime * 2.0f) % 2)
  1513. a3textDraw(demoState->text, posNDC.x, posNDC.y, posNDC.z, 1.0f, 1.0f, 1.0f, 1.0f,
  1514. currentHierarchyState->hierarchy->nodes[i].name);
  1515. else
  1516. a3textDraw(demoState->text, posNDC.x, posNDC.y, posNDC.z, 1.0f, 0.5f, 0.5f, 1.0f,
  1517. currentHierarchyState->hierarchy->nodes[i].name);
  1518. break;
  1519. }
  1520. }
  1521.  
  1522. glEnable(GL_DEPTH_TEST);
  1523.  
  1524.  
  1525.  
  1526. // draw coordinate axes in front of everything
  1527. glDisable(GL_DEPTH_TEST);
  1528. currentDemoProgram = demoState->prog_drawColor;
  1529. a3shaderProgramActivate(currentDemoProgram->program);
  1530. currentDrawable = demoState->draw_axes;
  1531. a3vertexActivateDrawable(currentDrawable);
  1532.  
  1533. // center of world
  1534. modelViewProjectionMat = demoState->camera->viewProjectionMat;
  1535. a3shaderUniformSendFloatMat(a3unif_mat4, 0, currentDemoProgram->uMVP, 1, modelViewProjectionMat.mm);
  1536. a3vertexRenderActiveDrawable();
  1537.  
  1538. glEnable(GL_DEPTH_TEST);
  1539.  
  1540.  
  1541. // deactivate things
  1542. a3vertexDeactivateDrawable();
  1543. a3shaderProgramDeactivate();
  1544.  
  1545.  
  1546. // HUD
  1547. if (demoState->textInit && demoState->showText)
  1548. {
  1549. const char *modeText[] = {
  1550. "Forward kinematics (procedural animation)",
  1551. "Forward kinematics (user-controlled)",
  1552. "FK Key poses",
  1553. };
  1554.  
  1555. glDisable(GL_DEPTH_TEST);
  1556.  
  1557. a3textDraw(demoState->text, -0.98f, +0.90f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
  1558. "Orientation control mode (%u / 3): ", demoState->kinematicsMode + 1);
  1559. a3textDraw(demoState->text, -0.98f, +0.85f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
  1560. " %s", modeText[demoState->kinematicsMode]);
  1561.  
  1562. switch (demoState->kinematicsMode)
  1563. {
  1564. // proc fk
  1565. case 0:
  1566. break;
  1567. case 1:
  1568. a3textDraw(demoState->text, -0.98f, -0.85f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
  1569. "Editing joint \"%s\" (index = %u / count = %u)",
  1570. demoState->skeleton->nodes[demoState->skeletonControlIndex].name,
  1571. demoState->skeletonControlIndex, demoState->skeleton->numNodes);
  1572. a3textDraw(demoState->text, -0.98f, -0.90f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
  1573. " Local Euler angles: x ('L'/'J') = %f, y ('I'/'K') = %f, z ('O'/'U') = %f",
  1574. demoState->skeletonEulers[demoState->skeletonControlIndex].x,
  1575. demoState->skeletonEulers[demoState->skeletonControlIndex].y,
  1576. demoState->skeletonEulers[demoState->skeletonControlIndex].z);
  1577. break;
  1578. case 2:
  1579.  
  1580. break;
  1581. }
  1582.  
  1583. glEnable(GL_DEPTH_TEST);
  1584. }
  1585. }
  1586.  
  1587.  
  1588. //-----------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement