Advertisement
Guest User

Untitled

a guest
Oct 17th, 2019
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.26 KB | None | 0 0
  1. // ========================================================================
  2. // COSC422: Advanced Computer Graphics; University of Canterbury (2019)
  3. //
  4. // FILE NAME: ArmyPilot.cpp
  5. //
  6. // Press key '1' to toggle 90 degs model rotation about x-axis on/off.
  7. // ========================================================================
  8.  
  9. #include <iostream>
  10. #include <map>
  11. #include <GL/freeglut.h>
  12. #include <IL/il.h>
  13. using namespace std;
  14.  
  15. #include <assimp/cimport.h>
  16. #include <assimp/types.h>
  17. #include <assimp/scene.h>
  18. #include <assimp/postprocess.h>
  19. #include "assimp_extras.h"
  20.  
  21. //----------Globals----------------------------
  22. const aiScene* scene = NULL;
  23. const aiScene* animation = NULL;
  24. float angle = 0;
  25. aiVector3D scene_min, scene_max, scene_center;
  26. bool modelRotn = true;
  27. std::map<int, int> texIdMap;
  28.  
  29. //------------Modify the following as needed----------------------
  30. float materialCol[4] = { 0.9, 0.9, 0.9, 1 }; //Default material colour (not used if model's colour is available)
  31. bool replaceCol = false; //Change to 'true' to set the model's colour to the above colour
  32. float lightPosn[4] = { 0, 50, 50, 1 }; //Default light's position
  33. bool twoSidedLight = false; //Change to 'true' to enable two-sided lighting
  34.  
  35. int tDuration; //Animation duration in ticks
  36. int currTick = 0; //current tick
  37. float timeStep=50; //Animation time step = 50 m.sec
  38. float ambient[4] = { 0.2, 0.2, 0.2, 1.0 }; //Ambient light
  39. float white[4] = { 1, 1, 1, 1 }; //Light's colour
  40.  
  41. struct meshInit
  42. {
  43. int mNumVertices;
  44. aiVector3D* mVertices;
  45. aiVector3D* mNormals;
  46. };
  47.  
  48. meshInit* initData;
  49.  
  50. /*
  51. aiMatrix4x4 get_interpolated_rotation(double tick, aiNodeAnim *node) {
  52. aiQuatKey prevKey;
  53. aiQuatKey nextKey;
  54. for(int i = 0; i < node->mNumRotationKeys; i++) {
  55. if(tick >= node->mRotationKeys[i].mTime) {
  56. prevKey = node->mRotationKeys[i];
  57. continue;
  58. }
  59.  
  60. nextKey = node->mRotationKeys[i];
  61.  
  62. double timeDiff = nextKey.mTime - prevKey.mTime;
  63. double currTime = tick - prevKey.mTime;
  64. double timeLerp = currTime / timeDiff;
  65.  
  66. aiQuaternion rotnOut;
  67. aiQuaternion::Interpolate(rotnOut, prevKey.mValue, nextKey.mValue, timeLerp);
  68. return aiMatrix4x4(rotnOut.GetMatrix());
  69. }
  70. }
  71.  
  72. aiMatrix4x4 get_interpolated_position(double tick, aiNodeAnim *node) {
  73. aiVectorKey prevKey;
  74. aiVectorKey nextKey;
  75. for(int i = 0; i < node->mNumPositionKeys; i++) {
  76. if(tick >= node->mPositionKeys[i].mTime) {
  77. prevKey = node->mPositionKeys[i];
  78. continue;
  79. }
  80. nextKey = node->mPositionKeys[i];
  81.  
  82. double timeDiff = nextKey.mTime - prevKey.mTime;
  83. double currTime = tick - prevKey.mTime;
  84. double timeLerp = currTime / timeDiff;
  85.  
  86. aiVector3D posnOut;
  87. posnOut = prevKey.mValue + (nextKey.mValue - prevKey.mValue) * float(timeLerp);
  88.  
  89. aiMatrix4x4 posnMat;
  90. aiMatrix4x4::Translation(prevKey.mValue, posnMat);
  91. return posnMat;
  92. }
  93. }*/
  94. bool loadAnimation(const char* fileName) {
  95.  
  96. animation = aiImportFile(fileName, aiProcessPreset_TargetRealtime_MaxQuality);
  97. if(scene == NULL) exit(1);
  98.  
  99. //printSceneInfo(scene);
  100. //printMeshInfo(scene);
  101. //printTreeInfo(scene->mRootNode);
  102. //printBoneInfo(scene);
  103. //printAnimInfo(scene); //WARNING: This may generate a lengthy output if the model has animation data
  104. tDuration = animation->mAnimations[0]->mDuration;
  105.  
  106. }
  107.  
  108. //-------Loads model data from file and creates a scene object----------
  109. bool loadModel(const char* fileName)
  110. {
  111.  
  112. scene = aiImportFile(fileName, aiProcessPreset_TargetRealtime_MaxQuality);
  113. if(scene == NULL) exit(1);
  114. //printSceneInfo(scene);
  115. //printMeshInfo(scene);
  116. //printTreeInfo(scene->mRootNode);
  117. //printBoneInfo(scene);
  118. //printAnimInfo(scene); //WARNING: This may generate a lengthy output if the model has animation data
  119. get_bounding_box(scene, &scene_min, &scene_max);
  120.  
  121. initData = new meshInit[scene->mNumMeshes];
  122. // New Code
  123. for (int i = 0; i < scene->mNumMeshes; i++) {
  124. aiMesh *mesh = scene->mMeshes[i];
  125. int numVert = mesh->mNumVertices;
  126. (initData + i)->mNumVertices = numVert;
  127. (initData + i)->mVertices = new aiVector3D[numVert];
  128. (initData + i)->mNormals = new aiVector3D[numVert];
  129.  
  130. for (int i_vert = 0; i_vert < mesh->mNumVertices; i_vert++) {
  131. (initData + i)->mVertices[i_vert] = mesh->mVertices[i_vert];
  132. (initData + i)->mNormals[i_vert] = mesh->mNormals[i_vert];
  133. }
  134. }
  135.  
  136.  
  137.  
  138.  
  139. //node = scene->mRootNode->FindNode()
  140.  
  141. return true;
  142. }
  143.  
  144.  
  145. void transformVertices()
  146. {
  147. for (int i = 0; i < scene->mNumMeshes; i++) {
  148. aiMesh *mesh = scene->mMeshes[i];
  149.  
  150. for (int i_bone = 0; i_bone < mesh->mNumBones; i_bone++) {
  151. aiBone *bone = mesh->mBones[i_bone];
  152. aiNode *node = scene->mRootNode->FindNode(bone->mName);
  153. aiMatrix4x4 boneTransform = bone->mOffsetMatrix;
  154.  
  155. while(node != nullptr) {
  156. std::string check(node->mName.C_Str());
  157. if(check != "free3dmodel_skeleton") {
  158. boneTransform = node->mTransformation * boneTransform;
  159. }
  160. node = node->mParent;
  161.  
  162. }
  163.  
  164. aiMatrix4x4 boneTransformTranspose = boneTransform;
  165. boneTransformTranspose.Transpose();
  166.  
  167. for (int k = 0; k < bone->mNumWeights; k++) {
  168. int vid = (bone->mWeights[k]).mVertexId;
  169.  
  170. aiVector3D vert = (initData + i)->mVertices[vid];
  171. aiVector3D norm = (initData + i)->mNormals[vid];
  172.  
  173. mesh->mVertices[vid] = boneTransform * vert;
  174. mesh->mNormals[vid] = boneTransformTranspose * norm;
  175.  
  176. //aiVertexWeight weight = bone->mWeights[i_weight];
  177. //mesh->mVertices[weight.mVertexId] = (boneTransform * initData[i].mVertices[weight.mVertexId]);
  178. //mesh->mNormals[weight.mVertexId] = (boneTransformTranspose * initData[i].mNormals[weight.mVertexId]);
  179. }
  180. }
  181. }
  182. }
  183.  
  184. //-------------Loads texture files using DevIL library-------------------------------
  185. void loadGLTextures(const aiScene* scene)
  186. {
  187. /* initialization of DevIL */
  188. ilInit();
  189. if (scene->HasTextures())
  190. {
  191. std::cout << "Support for meshes with embedded textures is not implemented" << endl;
  192. return;
  193. }
  194.  
  195. /* scan scene's materials for textures */
  196. /* Simplified version: Retrieves only the first texture with index 0 if present*/
  197. for (unsigned int m = 0; m < scene->mNumMaterials; ++m)
  198. {
  199. aiString path; // filename
  200.  
  201. if (scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, 0, &path) == AI_SUCCESS)
  202. {
  203. glEnable(GL_TEXTURE_2D);
  204. ILuint imageId;
  205. GLuint texId;
  206. ilGenImages(1, &imageId);
  207. glGenTextures(1, &texId);
  208. texIdMap[m] = texId; //store tex ID against material id in a hash map
  209. ilBindImage(imageId); /* Binding of DevIL image name */
  210. ilEnable(IL_ORIGIN_SET);
  211. ilOriginFunc(IL_ORIGIN_LOWER_LEFT);
  212.  
  213. std::string string(path.C_Str());
  214. std::string proper_path = string.substr(string.rfind("/") + 1, string.length());
  215.  
  216. if (ilLoadImage((ILstring)proper_path.c_str())) //if success
  217. {
  218. /* Convert image to RGBA */
  219. ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
  220.  
  221. /* Create and load textures to OpenGL */
  222. glBindTexture(GL_TEXTURE_2D, texId);
  223. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  224. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  225. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ilGetInteger(IL_IMAGE_WIDTH),
  226. ilGetInteger(IL_IMAGE_HEIGHT), 0, GL_RGBA, GL_UNSIGNED_BYTE,
  227. ilGetData());
  228. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  229. cout << "Texture:" << path.data << " successfully loaded." << endl;
  230. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  231. glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  232. glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  233. glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  234. }
  235. else
  236. {
  237. cout << "Couldn't load Image: " << path.data << endl;
  238. }
  239. }
  240. } //loop for material
  241.  
  242. }
  243.  
  244. // ------A recursive function to traverse scene graph and render each mesh----------
  245. void render (const aiScene* sc, const aiNode* nd)
  246. {
  247. aiMatrix4x4 m = nd->mTransformation;
  248. aiMesh* mesh;
  249. aiFace* face;
  250. aiMaterial* mtl;
  251. GLuint texId;
  252. aiColor4D diffuse;
  253. int meshIndex, materialIndex, textureIndex;
  254.  
  255. aiTransposeMatrix4(&m); //Convert to column-major order
  256. glPushMatrix();
  257. glMultMatrixf((float*)&m); //Multiply by the transformation matrix for this node
  258.  
  259. // Draw all meshes assigned to this node
  260. for (int n = 0; n < nd->mNumMeshes; n++)
  261. {
  262. meshIndex = nd->mMeshes[n]; //Get the mesh indices from the current node
  263. mesh = scene->mMeshes[meshIndex]; //Using mesh index, get the mesh object
  264.  
  265. materialIndex = mesh->mMaterialIndex; //Get material index attached to the mesh
  266. mtl = sc->mMaterials[materialIndex];
  267. if (replaceCol)
  268. glColor4fv(materialCol); //User-defined colour
  269. else if (AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse)) //Get material colour from model
  270. glColor4f(diffuse.r, diffuse.g, diffuse.b, 1.0);
  271. else
  272. glColor4fv(materialCol); //Default material colour
  273.  
  274. //Get the polygons from each mesh and draw them
  275. for (int k = 0; k < mesh->mNumFaces; k++)
  276. {
  277. face = &mesh->mFaces[k];
  278. GLenum face_mode;
  279.  
  280. switch(face->mNumIndices)
  281. {
  282. case 1: face_mode = GL_POINTS; break;
  283. case 2: face_mode = GL_LINES; break;
  284. case 3: face_mode = GL_TRIANGLES; break;
  285. default: face_mode = GL_POLYGON; break;
  286. }
  287.  
  288. if (mesh->HasTextureCoords(0)) {
  289. textureIndex = texIdMap[materialIndex];
  290. glBindTexture(GL_TEXTURE_2D, textureIndex);
  291. }
  292.  
  293. glBegin(face_mode);
  294.  
  295. for(int i = 0; i < face->mNumIndices; i++) {
  296. int vertexIndex = face->mIndices[i];
  297.  
  298. if(mesh->HasVertexColors(0))
  299. glColor4fv((GLfloat*)&mesh->mColors[0][vertexIndex]);
  300.  
  301. //Assign texture coordinates here
  302. if (mesh->HasTextureCoords(0)) {
  303. glTexCoord2f(mesh->mTextureCoords[0][vertexIndex].x, mesh->mTextureCoords[0][vertexIndex].y);
  304. }
  305.  
  306. if (mesh->HasNormals())
  307. glNormal3fv(&mesh->mNormals[vertexIndex].x);
  308.  
  309. glVertex3fv(&mesh->mVertices[vertexIndex].x);
  310. }
  311.  
  312. glEnd();
  313. }
  314. }
  315.  
  316. // Draw all children
  317. for (int i = 0; i < nd->mNumChildren; i++)
  318. render(sc, nd->mChildren[i]);
  319.  
  320. glPopMatrix();
  321. }
  322.  
  323. //--------------------OpenGL initialization------------------------
  324. void initialise()
  325. {
  326.  
  327. glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
  328. glEnable(GL_LIGHTING);
  329. glEnable(GL_LIGHT0);
  330. glEnable(GL_DEPTH_TEST);
  331. glEnable(GL_NORMALIZE);
  332. glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
  333. glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
  334. glLightfv(GL_LIGHT0, GL_SPECULAR, white);
  335. if (twoSidedLight) glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
  336.  
  337. glEnable(GL_COLOR_MATERIAL);
  338. glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
  339. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
  340. glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50);
  341. glColor4fv(materialCol);
  342. loadModel("mannequin.fbx"); //<<<-------------Specify input file name here
  343. loadAnimation("run.fbx");
  344.  
  345. loadGLTextures(scene);
  346. glMatrixMode(GL_PROJECTION);
  347. glLoadIdentity();
  348. gluPerspective(35, 1, 1.0, 1000.0);
  349. }
  350.  
  351. void updateNodeMatrices(int tick)
  352. {
  353. aiAnimation* anim = animation->mAnimations[0];
  354. aiMatrix4x4 matPos, matRot, matProd;
  355. aiMatrix3x3 matRot3;
  356. aiNode* nd;
  357.  
  358. for (int i = 0; i < anim->mNumChannels; i++) {
  359.  
  360. matPos = aiMatrix4x4(); //Identity
  361. matRot = aiMatrix4x4();
  362. aiNodeAnim* ndAnim = anim->mChannels[i]; //Channel
  363.  
  364. // Position
  365. aiVector3D posn = (ndAnim->mPositionKeys[0]).mValue;
  366. for(int j = 0; j < ndAnim->mNumPositionKeys; j++) {
  367. if(ndAnim->mPositionKeys[j].mTime == tick) {
  368. posn = ndAnim->mPositionKeys[j].mValue;
  369. break;
  370. } else if(ndAnim->mPositionKeys[j-1].mTime < tick && tick <= ndAnim->mPositionKeys[j].mTime){
  371. aiVector3D posn1 = (ndAnim->mPositionKeys[j-1]).mValue;
  372. aiVector3D posn2 = (ndAnim->mPositionKeys[j]).mValue;
  373. float time1 = (ndAnim->mPositionKeys[j-1]).mTime;
  374. float time2 = (ndAnim->mPositionKeys[j]).mTime;
  375. float factor = (tick - time1) / (time2 - time1);
  376. posn = posn1 + factor * (posn2 - posn1);
  377. break;
  378. }
  379. }
  380.  
  381. // Rotation
  382. aiQuaternion rotn = (ndAnim->mRotationKeys[0]).mValue;
  383. for(int j_rot = 0; j_rot < ndAnim->mNumRotationKeys; j_rot++) {
  384. if(ndAnim->mRotationKeys[j_rot].mTime == tick) {
  385. rotn = ndAnim->mRotationKeys[j_rot].mValue;
  386. break;
  387. } else if(ndAnim->mRotationKeys[j_rot-1].mTime < tick && tick <= ndAnim->mRotationKeys[j_rot].mTime){
  388. aiQuaternion rotn1 = (ndAnim->mRotationKeys[j_rot-1]).mValue;
  389. aiQuaternion rotn2 = (ndAnim->mRotationKeys[j_rot]).mValue;
  390. float time1 = (ndAnim->mRotationKeys[j_rot-1]).mTime;
  391. float time2 = (ndAnim->mRotationKeys[j_rot]).mTime;
  392. float factor = (tick - time1) / (time2 - time1);
  393. rotn.Interpolate(rotn, rotn1, rotn2, factor);
  394. break;
  395. }
  396. }
  397.  
  398. matPos.Translation(posn, matPos);
  399. matRot3 = rotn.GetMatrix();
  400. matRot = aiMatrix4x4(matRot3);
  401.  
  402. // applies everything
  403.  
  404. matProd = matPos * matRot;
  405. nd = scene->mRootNode->FindNode(ndAnim->mNodeName);
  406. nd->mTransformation = matProd;
  407. }
  408. transformVertices();
  409.  
  410. }
  411.  
  412.  
  413.  
  414. //----Timer callback for continuous rotation of the model about y-axis----
  415. void update(int value)
  416. {
  417. if (currTick < tDuration)
  418. {
  419. updateNodeMatrices(currTick);
  420. glutTimerFunc(timeStep, update, 0);
  421. currTick++;
  422. } else {
  423. currTick = 0;
  424. glutTimerFunc(timeStep, update, 0);
  425. }
  426. glutPostRedisplay();
  427. }
  428.  
  429. //----Keyboard callback to toggle initial model orientation---
  430. void keyboard(unsigned char key, int x, int y)
  431. {
  432. //if(key == '1') modelRotn = !modelRotn; //Enable/disable initial model rotation
  433. glutPostRedisplay();
  434. }
  435.  
  436. void floor()
  437. {
  438. /*
  439. glPushMatrix();
  440. glTranslatef(0, -1.2, -10);
  441. glScalef(0.3,1,0.3);
  442. glEnable(GL_LIGHTING);
  443. float white[4] = {1., 1., 1., 1.};
  444. float black[4] = {0};
  445.  
  446. glColor3f(0.2, 0.2, 0.2); //The floor is gray in colour
  447. glNormal3f(0.0, 1.0, 0.0);*/
  448. //The floor is made up of several tiny squares on a 200x200 grid. Each square has a unit size.
  449. glDisable(GL_TEXTURE_2D);
  450. glNormal3f(0.0, 1.0, 0.0);
  451. glScalef(200,200,200);
  452. glBegin(GL_QUADS);
  453. for(int i = -150; i < 150; i++)
  454. {
  455. for(int j = -150; j < 150; j++)
  456. {
  457. if((i+j) % 2 == 0) {
  458. glColor3f(1,1,1);
  459. } else {
  460. glColor3f(0,0,0.1);
  461. }
  462. glVertex3f(i, 0, j);
  463. glVertex3f(i, 0, j+1);
  464. glVertex3f(i+1, 0, j+1);
  465. glVertex3f(i+1, 0, j);
  466. }
  467. }
  468. glEnd();
  469. glEnable(GL_TEXTURE_2D);
  470. //glPopMatrix();
  471.  
  472.  
  473. }
  474.  
  475. //------The main display function---------
  476. //----The model is first drawn using a display list so that all GL commands are
  477. // stored for subsequent display updates.
  478. void display()
  479. {
  480. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  481.  
  482. glMatrixMode(GL_MODELVIEW);
  483. glLoadIdentity();
  484. gluLookAt(0, 0, 3, 0, 0, -5, 0, 1, 0);
  485. glLightfv(GL_LIGHT0, GL_POSITION, lightPosn);
  486.  
  487. glRotatef(angle, 0.f, 1.f ,0.f); //Continuous rotation about the y-axis
  488.  
  489. // scale the whole asset to fit into our view frustum
  490. float tmp = scene_max.x - scene_min.x;
  491. tmp = aisgl_max(scene_max.y - scene_min.y,tmp);
  492. tmp = aisgl_max(scene_max.z - scene_min.z,tmp);
  493. tmp = 1.f / tmp;
  494.  
  495.  
  496. float xc = (scene_min.x + scene_max.x)*0.5;
  497. float yc = (scene_min.y + scene_max.y)*0.5;
  498. float zc = (scene_min.z + scene_max.z)*0.5;
  499. // center the model
  500.  
  501. glPushMatrix();
  502. glRotatef(-90,1,0,0);
  503. glTranslatef(0,0,-0.6);
  504. glScalef(tmp, tmp, tmp);
  505. glTranslatef(-xc, -yc, -zc);
  506.  
  507. //Define shadow mat, multiply by thing below, translate up a bit
  508. render(scene, scene->mRootNode);
  509. glPopMatrix();
  510. glPushMatrix();
  511. glScalef(tmp, tmp, tmp);
  512. glTranslatef(-xc, -yc, -zc);
  513.  
  514. floor();
  515. glPopMatrix();
  516. glutSwapBuffers();
  517. }
  518.  
  519.  
  520.  
  521. int main(int argc, char** argv)
  522. {
  523. glutInit(&argc, argv);
  524. glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  525. glutInitWindowSize(600, 600);
  526. glutCreateWindow("Mannequin");
  527. glutInitContextVersion (4, 2);
  528. glutInitContextProfile ( GLUT_CORE_PROFILE );
  529.  
  530. initialise();
  531. glutDisplayFunc(display);
  532. glutTimerFunc(50, update, 0);
  533. glutKeyboardFunc(keyboard);
  534. glutMainLoop();
  535.  
  536. aiReleaseImport(scene);
  537. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement