Advertisement
Guest User

Untitled

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