25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 
 

384 satır
11 KiB

  1. // ----------------------------------------------------------------------------
  2. // Simple sample to prove that Assimp is easy to use with OpenGL.
  3. // It takes a file name as command line parameter, loads it using standard
  4. // settings and displays it.
  5. //
  6. // If you intend to _use_ this code sample in your app, do yourself a favour
  7. // and replace immediate mode calls with VBOs ...
  8. //
  9. // The vc8 solution links against assimp-release-dll_win32 - be sure to
  10. // have this configuration built.
  11. // ----------------------------------------------------------------------------
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <GL/glut.h>
  15. // assimp include files. These three are usually needed.
  16. #include <assimp/cimport.h>
  17. #include <assimp/scene.h>
  18. #include <assimp/postprocess.h>
  19. // the global Assimp scene object
  20. const struct aiScene* scene = NULL;
  21. GLuint scene_list = 0;
  22. struct aiVector3D scene_min, scene_max, scene_center;
  23. // current rotation angle
  24. static float angle = 0.f;
  25. #define aisgl_min(x,y) (x<y?x:y)
  26. #define aisgl_max(x,y) (y>x?y:x)
  27. // ----------------------------------------------------------------------------
  28. void reshape(int width, int height)
  29. {
  30. const double aspectRatio = (float) width / height, fieldOfView = 45.0;
  31. glMatrixMode(GL_PROJECTION);
  32. glLoadIdentity();
  33. gluPerspective(fieldOfView, aspectRatio,
  34. 1.0, 1000.0); /* Znear and Zfar */
  35. glViewport(0, 0, width, height);
  36. }
  37. // ----------------------------------------------------------------------------
  38. void get_bounding_box_for_node (const struct aiNode* nd,
  39. struct aiVector3D* min,
  40. struct aiVector3D* max,
  41. struct aiMatrix4x4* trafo
  42. ){
  43. struct aiMatrix4x4 prev;
  44. unsigned int n = 0, t;
  45. prev = *trafo;
  46. aiMultiplyMatrix4(trafo,&nd->mTransformation);
  47. for (; n < nd->mNumMeshes; ++n) {
  48. const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
  49. for (t = 0; t < mesh->mNumVertices; ++t) {
  50. struct aiVector3D tmp = mesh->mVertices[t];
  51. aiTransformVecByMatrix4(&tmp,trafo);
  52. min->x = aisgl_min(min->x,tmp.x);
  53. min->y = aisgl_min(min->y,tmp.y);
  54. min->z = aisgl_min(min->z,tmp.z);
  55. max->x = aisgl_max(max->x,tmp.x);
  56. max->y = aisgl_max(max->y,tmp.y);
  57. max->z = aisgl_max(max->z,tmp.z);
  58. }
  59. }
  60. for (n = 0; n < nd->mNumChildren; ++n) {
  61. get_bounding_box_for_node(nd->mChildren[n],min,max,trafo);
  62. }
  63. *trafo = prev;
  64. }
  65. // ----------------------------------------------------------------------------
  66. void get_bounding_box (struct aiVector3D* min, struct aiVector3D* max)
  67. {
  68. struct aiMatrix4x4 trafo;
  69. aiIdentityMatrix4(&trafo);
  70. min->x = min->y = min->z = 1e10f;
  71. max->x = max->y = max->z = -1e10f;
  72. get_bounding_box_for_node(scene->mRootNode,min,max,&trafo);
  73. }
  74. // ----------------------------------------------------------------------------
  75. void color4_to_float4(const struct aiColor4D *c, float f[4])
  76. {
  77. f[0] = c->r;
  78. f[1] = c->g;
  79. f[2] = c->b;
  80. f[3] = c->a;
  81. }
  82. // ----------------------------------------------------------------------------
  83. void set_float4(float f[4], float a, float b, float c, float d)
  84. {
  85. f[0] = a;
  86. f[1] = b;
  87. f[2] = c;
  88. f[3] = d;
  89. }
  90. // ----------------------------------------------------------------------------
  91. void apply_material(const struct aiMaterial *mtl)
  92. {
  93. float c[4];
  94. GLenum fill_mode;
  95. int ret1, ret2;
  96. struct aiColor4D diffuse;
  97. struct aiColor4D specular;
  98. struct aiColor4D ambient;
  99. struct aiColor4D emission;
  100. float shininess, strength;
  101. int two_sided;
  102. int wireframe;
  103. unsigned int max;
  104. set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f);
  105. if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse))
  106. color4_to_float4(&diffuse, c);
  107. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c);
  108. set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f);
  109. if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular))
  110. color4_to_float4(&specular, c);
  111. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c);
  112. set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f);
  113. if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient))
  114. color4_to_float4(&ambient, c);
  115. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c);
  116. set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f);
  117. if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission))
  118. color4_to_float4(&emission, c);
  119. glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c);
  120. max = 1;
  121. ret1 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max);
  122. if(ret1 == AI_SUCCESS) {
  123. max = 1;
  124. ret2 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS_STRENGTH, &strength, &max);
  125. if(ret2 == AI_SUCCESS)
  126. glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength);
  127. else
  128. glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
  129. }
  130. else {
  131. glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f);
  132. set_float4(c, 0.0f, 0.0f, 0.0f, 0.0f);
  133. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c);
  134. }
  135. max = 1;
  136. if(AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, &max))
  137. fill_mode = wireframe ? GL_LINE : GL_FILL;
  138. else
  139. fill_mode = GL_FILL;
  140. glPolygonMode(GL_FRONT_AND_BACK, fill_mode);
  141. max = 1;
  142. if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided)
  143. glDisable(GL_CULL_FACE);
  144. else
  145. glEnable(GL_CULL_FACE);
  146. }
  147. // ----------------------------------------------------------------------------
  148. void recursive_render (const struct aiScene *sc, const struct aiNode* nd)
  149. {
  150. unsigned int i;
  151. unsigned int n = 0, t;
  152. struct aiMatrix4x4 m = nd->mTransformation;
  153. // update transform
  154. aiTransposeMatrix4(&m);
  155. glPushMatrix();
  156. glMultMatrixf((float*)&m);
  157. // draw all meshes assigned to this node
  158. for (; n < nd->mNumMeshes; ++n) {
  159. const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
  160. apply_material(sc->mMaterials[mesh->mMaterialIndex]);
  161. if(mesh->mNormals == NULL) {
  162. glDisable(GL_LIGHTING);
  163. } else {
  164. glEnable(GL_LIGHTING);
  165. }
  166. for (t = 0; t < mesh->mNumFaces; ++t) {
  167. const struct aiFace* face = &mesh->mFaces[t];
  168. GLenum face_mode;
  169. switch(face->mNumIndices) {
  170. case 1: face_mode = GL_POINTS; break;
  171. case 2: face_mode = GL_LINES; break;
  172. case 3: face_mode = GL_TRIANGLES; break;
  173. default: face_mode = GL_POLYGON; break;
  174. }
  175. glBegin(face_mode);
  176. for(i = 0; i < face->mNumIndices; i++) {
  177. int index = face->mIndices[i];
  178. if(mesh->mColors[0] != NULL)
  179. glColor4fv((GLfloat*)&mesh->mColors[0][index]);
  180. if(mesh->mNormals != NULL)
  181. glNormal3fv(&mesh->mNormals[index].x);
  182. glVertex3fv(&mesh->mVertices[index].x);
  183. }
  184. glEnd();
  185. }
  186. }
  187. // draw all children
  188. for (n = 0; n < nd->mNumChildren; ++n) {
  189. recursive_render(sc, nd->mChildren[n]);
  190. }
  191. glPopMatrix();
  192. }
  193. // ----------------------------------------------------------------------------
  194. void do_motion (void)
  195. {
  196. static GLint prev_time = 0;
  197. static GLint prev_fps_time = 0;
  198. static int frames = 0;
  199. int time = glutGet(GLUT_ELAPSED_TIME);
  200. angle += (time-prev_time)*0.01;
  201. prev_time = time;
  202. frames += 1;
  203. if ((time - prev_fps_time) > 1000) // update every seconds
  204. {
  205. int current_fps = frames * 1000 / (time - prev_fps_time);
  206. printf("%d fps\n", current_fps);
  207. frames = 0;
  208. prev_fps_time = time;
  209. }
  210. glutPostRedisplay ();
  211. }
  212. // ----------------------------------------------------------------------------
  213. void display(void)
  214. {
  215. float tmp;
  216. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  217. glMatrixMode(GL_MODELVIEW);
  218. glLoadIdentity();
  219. gluLookAt(0.f,0.f,3.f,0.f,0.f,-5.f,0.f,1.f,0.f);
  220. // rotate it around the y axis
  221. glRotatef(angle,0.f,1.f,0.f);
  222. // scale the whole asset to fit into our view frustum
  223. tmp = scene_max.x-scene_min.x;
  224. tmp = aisgl_max(scene_max.y - scene_min.y,tmp);
  225. tmp = aisgl_max(scene_max.z - scene_min.z,tmp);
  226. tmp = 1.f / tmp;
  227. glScalef(tmp, tmp, tmp);
  228. // center the model
  229. glTranslatef( -scene_center.x, -scene_center.y, -scene_center.z );
  230. // if the display list has not been made yet, create a new one and
  231. // fill it with scene contents
  232. if(scene_list == 0) {
  233. scene_list = glGenLists(1);
  234. glNewList(scene_list, GL_COMPILE);
  235. // now begin at the root node of the imported data and traverse
  236. // the scenegraph by multiplying subsequent local transforms
  237. // together on GL's matrix stack.
  238. recursive_render(scene, scene->mRootNode);
  239. glEndList();
  240. }
  241. glCallList(scene_list);
  242. glutSwapBuffers();
  243. do_motion();
  244. }
  245. // ----------------------------------------------------------------------------
  246. int loadasset (const char* path)
  247. {
  248. // we are taking one of the postprocessing presets to avoid
  249. // spelling out 20+ single postprocessing flags here.
  250. scene = aiImportFile(path,aiProcessPreset_TargetRealtime_MaxQuality);
  251. if (scene) {
  252. get_bounding_box(&scene_min,&scene_max);
  253. scene_center.x = (scene_min.x + scene_max.x) / 2.0f;
  254. scene_center.y = (scene_min.y + scene_max.y) / 2.0f;
  255. scene_center.z = (scene_min.z + scene_max.z) / 2.0f;
  256. return 0;
  257. }
  258. return 1;
  259. }
  260. // ----------------------------------------------------------------------------
  261. int main(int argc, char **argv)
  262. {
  263. struct aiLogStream stream;
  264. glutInitWindowSize(900,600);
  265. glutInitWindowPosition(100,100);
  266. glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  267. glutInit(&argc, argv);
  268. glutCreateWindow("Assimp - Very simple OpenGL sample");
  269. glutDisplayFunc(display);
  270. glutReshapeFunc(reshape);
  271. // get a handle to the predefined STDOUT log stream and attach
  272. // it to the logging system. It remains active for all further
  273. // calls to aiImportFile(Ex) and aiApplyPostProcessing.
  274. stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL);
  275. aiAttachLogStream(&stream);
  276. // ... same procedure, but this stream now writes the
  277. // log messages to assimp_log.txt
  278. stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt");
  279. aiAttachLogStream(&stream);
  280. // the model name can be specified on the command line. If none
  281. // is specified, we try to locate one of the more expressive test
  282. // models from the repository (/models-nonbsd may be missing in
  283. // some distributions so we need a fallback from /models!).
  284. if( 0 != loadasset( argc >= 2 ? argv[1] : "../../test/models-nonbsd/X/dwarf.x")) {
  285. if( argc != 1 || (0 != loadasset( "../../../../test/models-nonbsd/X/dwarf.x") && 0 != loadasset( "../../test/models/X/Testwuson.X"))) {
  286. return -1;
  287. }
  288. }
  289. glClearColor(0.1f,0.1f,0.1f,1.f);
  290. glEnable(GL_LIGHTING);
  291. glEnable(GL_LIGHT0); // Uses default lighting parameters
  292. glEnable(GL_DEPTH_TEST);
  293. glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
  294. glEnable(GL_NORMALIZE);
  295. // XXX docs say all polygons are emitted CCW, but tests show that some aren't.
  296. if(getenv("MODEL_IS_BROKEN"))
  297. glFrontFace(GL_CW);
  298. glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
  299. glutGet(GLUT_ELAPSED_TIME);
  300. glutMainLoop();
  301. // cleanup - calling 'aiReleaseImport' is important, as the library
  302. // keeps internal resources until the scene is freed again. Not
  303. // doing so can cause severe resource leaking.
  304. aiReleaseImport(scene);
  305. // We added a log stream to the library, it's our job to disable it
  306. // again. This will definitely release the last resources allocated
  307. // by Assimp.
  308. aiDetachAllLogStreams();
  309. return 0;
  310. }