天天看點

lib3ds 2.0 example 2

lib3ds 2.0 example 2

cheungmine

2009-2-14

  在上一個例子中,展示了基本的lib3ds2.0的使用方法。在本例中,對上面的代碼稍作修改。這樣,無論3ds檔案是否有相機或燈光,都可以顯示了。

     思路就是,如果3ds檔案沒有相機,我們就增加4個相機。如果沒有燈光,就增加3個OmniLight。

上面的代碼參考了文章:

  《利用lib3ds和OpenGL實作3ds檔案的讀取和顯示---白改朝》---電腦程式設計技巧與維護2008.7

    例子player.c代碼使用了glut32。(下篇文章,我會轉到Windows上實作這個代碼。不使用glut庫。)

    本例仍然沒有使用貼圖。希望我的下個例子能把貼圖做出來。

    好了,代碼全部貼在下面了。需要的庫仍然可以在網上找到,就不廢話了。

[cpp:nogutter]  view plain copy print ?

  1. ///  
  2. // player2.c  
  3. //  
  4. // 2009-2-14  
  5. //  
  6. // 作者:cheungmine  
  7. //  
  8. // 參考:  
  9. //  
  10. //        http://www.lib3ds.org/lib3ds-1.2.0/examples/player.c  
  11. //  
  12. // 目錄結構:  
  13. //  
  14. // lib/lib3ds_2.0/src/  
  15. //          debug/lib3ds20d.lib  lib3ds20d.dll  
  16. //          release/lib3ds20.lib  lib3ds20.dll  
  17. //  
  18. // lib/lib3ds_2.0/  
  19. //          glut_test/player.c  
  20. //  
  21. // lib/win_opengl32/  
  22. //          inc/gl.h  glu.h   glut.h  
  23. //          lib/opengl32.lib  glu32.lib   glut32.lib  
  24. //          bin/opengl32.dll  glu32.dll   glut32.dll  
  25. //  
  26. ///  
  27. // 記憶體洩漏檢測  
  28. // 在需要檢測的地方放置語句:  
  29. //        _CrtDumpMemoryLeaks();  
  30. // 以下3句的次序不能改變  
  31. #define _CRTDBG_MAP_ALLOC     
  32. #include<stdlib.h>  
  33. #include<crtdbg.h>  
  34. #include<stdio.h>  
  35. #include<string.h>  
  36. #include<math.h>  
  37. #include<assert.h>  
  38. #include <windows.h>  
  39. // 使用 USE_SGI_OPENGL 可能在某些機器上運作 wglMakeCurrent 系列函數傳回失敗的結果  
  40. #define GLUT_NO_LIB_PRAGMA  
  41. // #define USE_SGI_OPENGL  
  42. #ifdef USE_SGI_OPENGL  
  43.     #include "../../sgi-opengl2-sdk/include/gl/gl.h"  
  44.     #include "../../sgi-opengl2-sdk/include/gl/glu.h"  
  45.     #include "../../sgi-opengl2-sdk/include/gl/glut.h"  
  46.     #pragma comment(lib, "../../sgi-opengl2-sdk/lib/opengl.lib")  
  47.     #pragma comment(lib, "../../sgi-opengl2-sdk/lib/glu.lib")  
  48.     #pragma comment(lib, "../../sgi-opengl2-sdk/lib/glut.lib")  
  49. #else  
  50.     #include "../../win-opengl32/inc/GL.h"  
  51.     #include "../../win-opengl32/inc/GLU.h"  
  52.     #pragma comment(lib, "../../win-opengl32/lib/OPENGL32.lib")  
  53.     #pragma comment(lib, "../../win-opengl32/lib/GLU32.lib")  
  54.     #include "../../win-opengl32/inc/GLUT.h"  
  55.     #pragma comment(lib, "../../win-opengl32/lib/glut32.lib")  
  56. #endif  
  57. //  
  58. // lib3ds  
  59. //  
  60. #include "../src/lib3ds.h"  
  61. #ifdef _DEBUG  
  62. #  pragma comment(lib, "../src/debug/lib3ds20d.lib")  
  63. #else  
  64. #  pragma comment(lib, "../src/release/lib3ds20.lib")  
  65. #endif  
  66. static const char* filename="E://GU2005//LIB//lib3ds_2.0//data//Bf109G6//Bf109G6.3ds";  
  67. //E://3DS//Spacecraft//Spacecraft.3ds";  
  68. //"E://GU2005//LIB//lib3ds_2.0//data//abom.3ds";  
  69. //"E:/3DS/House/house.3ds";  
  70. static Lib3dsFile *model=0;  
  71. static const char* camera=0;  
  72. static float current_frame=0.0;  
  73. static int gl_width;  
  74. static int gl_height;  
  75. static int camera_menu_id=0;  
  76. static int halt=0;  
  77. #ifndef MAX  
  78. #  define MAX(x,y)  ((x)>(y)?(x):(y))  
  79. #endif  
  80. static void camera_menu(int value)   
  81. {  
  82.     Lib3dsCamera *c=0;  
  83.     int i;  
  84.     for( i=0; i<value; i++ ){  
  85.         if (i==model->ncameras)  
  86.             return;  
  87.         c = model->cameras[i];  
  88.     }  
  89.     if (c)  
  90.         camera=c->name;  
  91. }  
  92. static void render_node(Lib3dsNode *node)  
  93. {  
  94.     Lib3dsNode      *p;  
  95.     Lib3dsMesh      *mesh;  
  96.     Lib3dsFace      *face;  
  97.     Lib3dsMaterial  *mat;  
  98.     Lib3dsMeshInstanceNode *meshData;  
  99.     Lib3dsVector    *norm_verts;  
  100.     Lib3dsVector    *norm_faces;  
  101.     int         i;  
  102.     unsigned    fi;  
  103.     float       M[4][4];  
  104.     assert(model);  
  105.     // 遞歸  
  106.     for (p=node->childs; p!=0; p=p->next){  
  107.         render_node(p);  
  108.     }  
  109.     if (node->type==LIB3DS_NODE_MESH_INSTANCE)  
  110.     {  
  111.         if (strcmp(node->name,"$$$DUMMY")==0) {  
  112.             return;  
  113.         }  
  114.         if (!node->user_id)   
  115.         {  
  116.             mesh = lib3ds_file_mesh_for_node(model, node);  
  117.             assert(mesh);  
  118.             if (!mesh) {  
  119.                 return;  
  120.             }  
  121.             node->user_id = glGenLists(1);  
  122.             glNewList(node->user_id, GL_COMPILE);  
  123.             norm_verts = (Lib3dsVector*) malloc(3*sizeof(Lib3dsVector)*mesh->nfaces);  
  124.             norm_faces = (Lib3dsVector*) malloc(sizeof(Lib3dsVector)*mesh->nfaces);                
  125.             lib3ds_matrix_copy(M, mesh->matrix);  
  126.             lib3ds_matrix_inv(M);  
  127.             glMultMatrixf(&M[0][0]);  
  128.             lib3ds_mesh_calculate_face_normals(mesh, (float (*)[3])norm_faces);  
  129.             lib3ds_mesh_calculate_vertex_normals(mesh, (float (*)[3])norm_verts);  
  130.             for (fi=0; fi<mesh->nfaces; ++fi) {  
  131.                 face = &(mesh->faces[fi]);  
  132.                 mat = 0;  
  133.                 if (face->material>=0 && face->material<model->nmaterials)  
  134.                     mat=model->materials[face->material];  
  135.                 if (mat)   
  136.                 {  
  137.                     // 使用材質  
  138.                     float s = pow(2, 10.0*mat->shininess);  
  139.                     if (s>128.0) s = 128.0f;  
  140.                     glMaterialfv(GL_FRONT, GL_AMBIENT, mat->ambient);  
  141.                     glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse);  
  142.                     glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular);  
  143.                     glMaterialf(GL_FRONT, GL_SHININESS, s);  
  144.                 }  
  145.                 else {  
  146.                     // 使用貼圖  
  147.                     float a[]={0.2, 0.2, 0.2, 1.0};  
  148.                     float d[]={0.8, 0.8, 0.8, 1.0};  
  149.                     float s[]={0.0, 0.0, 0.0, 1.0};  
  150.                     glMaterialfv(GL_FRONT, GL_AMBIENT, a);  
  151.                     glMaterialfv(GL_FRONT, GL_DIFFUSE, d);  
  152.                     glMaterialfv(GL_FRONT, GL_SPECULAR, s);  
  153.                 }  
  154.                 // Draw tri-face  
  155.                 glBegin(GL_TRIANGLES);  
  156.                 glNormal3fv(norm_faces[fi].v);  // face normal  
  157.                 for (i=0; i<3; ++i) {  
  158.                     glNormal3fv(norm_verts[3*fi+i].v);  // vertex normal  
  159.                     glVertex3fv(mesh->vertices[face->index[i]]);  
  160.                 }  
  161.                 glEnd();  
  162.             }  
  163.             free(norm_faces);  
  164.             free(norm_verts);  
  165.             glEndList();  
  166.         }  
  167.         if (node->user_id) {  
  168.             glPushMatrix();  
  169.             meshData = (Lib3dsMeshInstanceNode*) node;  
  170.             glMultMatrixf(&node->matrix[0][0]);  
  171.             glTranslatef(-meshData->pivot[0], -meshData->pivot[1], -meshData->pivot[2]);  
  172.             glCallList(node->user_id);  
  173.             // glutSolidSphere(50.0, 20,20);  
  174.             glPopMatrix();  
  175.         }  
  176.     }  
  177. }  
  178. static void display(void)  
  179. {  
  180.     int  i, li;  
  181.     Lib3dsNode *nodC, *nodT, *nod;  
  182.     Lib3dsCameraNode *camNode;  
  183.     Lib3dsTargetNode *tgtNode;  
  184.     float             M[4][4];  
  185.     GLfloat a[] = {0.0f, 0.0f, 0.0f, 1.0f};  
  186.     GLfloat c[] = {1.0f, 1.0f, 1.0f, 1.0f};  
  187.     GLfloat p[] = {0.0f, 0.0f, 0.0f, 1.0f};  
  188.     Lib3dsLight *l;  
  189.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  190.     if (!model) {  
  191.         exit(1);  
  192.     }  
  193.     nodC=lib3ds_file_node_by_name(model, camera, LIB3DS_NODE_CAMERA);  
  194.     nodT=lib3ds_file_node_by_name(model, camera, LIB3DS_NODE_CAMERA_TARGET);  
  195.     if (!nodC || !nodT) {  
  196.         assert(0 && "Camera or Target not found!");  
  197.         exit(1);  
  198.     }  
  199.     camNode = (Lib3dsCameraNode*) nodC;  
  200.     tgtNode = (Lib3dsTargetNode*) nodT;  
  201.     glMatrixMode(GL_PROJECTION);  
  202.     glLoadIdentity();  
  203.     gluPerspective( camNode->fov, gl_width/gl_height, 0.1f, 6000.0);  
  204.     glMatrixMode(GL_MODELVIEW);  
  205.     glLoadIdentity();  
  206.     glRotatef(-90, 1.0, 0,0);  
  207.     li=GL_LIGHT0;  
  208.     for (i=0; i<model->nlights; i++)  
  209.     {  
  210.         l = model->lights[i];  
  211.         glEnable(li);  
  212.         glLightfv(li, GL_AMBIENT, a);  
  213.         glLightfv(li, GL_DIFFUSE, c);  
  214.         glLightfv(li, GL_SPECULAR, c);  // p?  
  215.         p[0] = l->position[0];  
  216.         p[1] = l->position[1];  
  217.         p[2] = l->position[2];  
  218.         glLightfv(li, GL_POSITION, p);  
  219.         if (!l->spot_light) {  
  220.             continue;  
  221.         }  
  222.         p[0] = l->target[0] - l->position[0];  
  223.         p[1] = l->target[1] - l->position[1];  
  224.         p[2] = l->target[2] - l->position[2];        
  225.         glLightfv(li, GL_SPOT_DIRECTION, p);  
  226.         ++li;  
  227.     }  
  228.     lib3ds_matrix_camera(M, camNode->pos, tgtNode->pos, camNode->roll);  
  229.     glMultMatrixf(&M[0][0]);  
  230.     for (nod=model->nodes; nod!=0; nod=nod->next) {  
  231.         render_node(nod);  
  232.     }  
  233.     if (!halt) {  
  234.         current_frame+=1.0;  
  235.         if (current_frame>model->frames) {  
  236.             current_frame=0;  
  237.         }  
  238.         lib3ds_file_eval(model, current_frame);  
  239.         glutSwapBuffers();  
  240.         glutPostRedisplay();  
  241.     }  
  242. }  
  243. // 增加預設的相機和目标  
  244. static add_default_cameras (Lib3dsFile *model, Lib3dsBBox *bbox, float sizes[], float center[])  
  245. {  
  246.     int  index=0;  
  247.     Lib3dsCamera     *cam;  
  248.     Lib3dsCameraNode *nodCam;  
  249.     Lib3dsTargetNode *nodTgt;  
  250.     // Camera_X  
  251.     cam = lib3ds_camera_new ("Camera_X");  
  252.     assert(cam);  
  253.     memcpy(cam->target, center, sizeof(Lib3dsVector));  
  254.     memcpy(cam->position, center, sizeof(Lib3dsVector));  
  255.     cam->position[0] = bbox->bmax[0] + 1.5*MAX(sizes[1],sizes[2]);  
  256.     cam->near_range = (cam->position[0] - bbox->bmax[0])/2;  
  257.     cam->far_range = (cam->position[0] - bbox->bmin[0])*2;  
  258.     lib3ds_file_insert_camera(model, cam, index++);  
  259.     nodCam = lib3ds_node_new_camera(cam);  
  260.     assert(nodCam);  
  261.     lib3ds_file_append_node(model, (Lib3dsNode*)nodCam, 0);  
  262.     nodTgt = lib3ds_node_new_camera_target(cam);  
  263.     assert(nodTgt);  
  264.     lib3ds_file_append_node(model, (Lib3dsNode*)nodTgt, 0);  
  265.     // Camera_Y  
  266.     cam = lib3ds_camera_new ("Camera_Y");  
  267.     assert(cam);  
  268.     memcpy(cam->target, center, sizeof(Lib3dsVector));  
  269.     memcpy(cam->position, center, sizeof(Lib3dsVector));  
  270.     cam->position[1] = bbox->bmin[1] - 1.5*MAX(sizes[0],sizes[2]);  
  271.     cam->near_range = (bbox->bmin[1]-cam->position[1])/2;  
  272.     cam->far_range = (bbox->bmax[1]-cam->position[1])*2;  
  273.     lib3ds_file_insert_camera(model, cam, index++);  
  274.     nodCam = lib3ds_node_new_camera(cam);  
  275.     assert(nodCam);  
  276.     lib3ds_file_append_node(model, (Lib3dsNode*)nodCam, 0);  
  277.     nodTgt = lib3ds_node_new_camera_target(cam);  
  278.     assert(nodTgt);  
  279.     lib3ds_file_append_node(model, (Lib3dsNode*)nodTgt, 0);  
  280.     // Camera_Z  
  281.     cam = lib3ds_camera_new ("Camera_Z");  
  282.     assert(cam);  
  283.     memcpy(cam->target, center, sizeof(Lib3dsVector));  
  284.     memcpy(cam->position, center, sizeof(Lib3dsVector));  
  285.     cam->position[2] = bbox->bmax[2] + 1.5*MAX(sizes[0],sizes[1]);  
  286.     cam->near_range = (cam->position[2]-bbox->bmax[2])/2;  
  287.     cam->far_range = (cam->position[2]-bbox->bmin[2])*2;  
  288.     lib3ds_file_insert_camera(model, cam, index++);  
  289.     nodCam = lib3ds_node_new_camera(cam);  
  290.     assert(nodCam);  
  291.     lib3ds_file_append_node(model, (Lib3dsNode*)nodCam, 0);  
  292.     nodTgt = lib3ds_node_new_camera_target(cam);  
  293.     assert(nodTgt);  
  294.     lib3ds_file_append_node(model, (Lib3dsNode*)nodTgt, 0);  
  295.     // Camera_ISO  
  296.     cam = lib3ds_camera_new ("Camera_ISO");  
  297.     assert(cam);  
  298.     memcpy(cam->target, center, sizeof(Lib3dsVector));  
  299.     cam->position[0] = bbox->bmax[0] + 0.75f*sizes[3];  
  300.     cam->position[1] = bbox->bmin[1] - 0.75f*sizes[3];  
  301.     cam->position[2] = bbox->bmax[2] + 0.75f*sizes[3];  
  302.     cam->near_range = (cam->position[0]-bbox->bmax[0])/2;  
  303.     cam->far_range = (cam->position[0]-bbox->bmin[0])*3;  
  304.     lib3ds_file_insert_camera(model, cam, index++);  
  305.     nodCam = lib3ds_node_new_camera(cam);  
  306.     assert(nodCam);  
  307.     lib3ds_file_append_node(model, (Lib3dsNode*)nodCam, 0);  
  308.     nodTgt = lib3ds_node_new_camera_target(cam);  
  309.     assert(nodTgt);  
  310.     lib3ds_file_append_node(model, (Lib3dsNode*)nodTgt, 0);  
  311. }  
  312. // 增加預設的燈光  
  313. static void add_default_lights (Lib3dsFile *model, Lib3dsBBox *bbox, float sizes[], float center[])  
  314. {  
  315.     int  index=0;  
  316.     Lib3dsOmnilightNode     *omniNode;  
  317.     Lib3dsLight             *light;  
  318.     // light0  
  319.     light = lib3ds_light_new("light0");  
  320.     assert(light);  
  321.     light->spot_light = 0;  
  322.     light->see_cone = 0;  
  323.     light->color[0]=light->color[1]=light->color[2]=0.6f;  
  324.     light->position[0]=center[0]+sizes[3]*0.75;  
  325.     light->position[1]=center[1]-sizes[3]*1;  
  326.     light->position[2]=center[2]+sizes[3]*1.5;  
  327.     light->outer_range = 100;  
  328.     light->inner_range = 10;  
  329.     light->multiplier=1;  
  330.     lib3ds_file_insert_light(model, light, index++);  
  331.     omniNode = lib3ds_node_new_omnilight(light);  
  332.     assert(omniNode);  
  333.     lib3ds_file_append_node(model, (Lib3dsNode*)omniNode, 0);  
  334.     // light1  
  335.     light = lib3ds_light_new("light1");  
  336.     assert(light);  
  337.     light->spot_light = 0;  
  338.     light->see_cone = 0;  
  339.     light->color[0]=light->color[1]=light->color[2]=0.3f;  
  340.     light->position[0]=center[0]-sizes[3];  
  341.     light->position[1]=center[1]-sizes[3];  
  342.     light->position[2]=center[2]+sizes[3]*0.75;  
  343.     light->outer_range = 100;  
  344.     light->inner_range = 10;  
  345.     light->multiplier=1;  
  346.     lib3ds_file_insert_light(model, light, index++);  
  347.     omniNode = lib3ds_node_new_omnilight(light);  
  348.     assert(omniNode);  
  349.     lib3ds_file_append_node(model, (Lib3dsNode*)omniNode, 0);  
  350.     // light2  
  351.     light = lib3ds_light_new("light2");  
  352.     assert(light);  
  353.     light->spot_light = 0;  
  354.     light->see_cone = 0;  
  355.     light->color[0]=light->color[1]=light->color[2]=0.3f;  
  356.     light->position[0]=center[0];  
  357.     light->position[1]=center[1]+sizes[3];  
  358.     light->position[2]=center[2]+sizes[3];  
  359.     light->outer_range = 100;  
  360.     light->inner_range = 10;  
  361.     light->multiplier=1;  
  362.     lib3ds_file_insert_light(model, light, index++);  
  363.     omniNode = lib3ds_node_new_omnilight(light);  
  364.     assert(omniNode);  
  365.     lib3ds_file_append_node(model, (Lib3dsNode*)omniNode, 0);  
  366. }  
  367. static void init(void)   
  368. {  
  369.     int     i;  
  370.     float      sizes[4];        // 模型尺寸坐标  
  371.     float      center[3];       // 模型目标中心坐标  
  372.     Lib3dsBBox bbox;            // 模型範圍  
  373.     glClearColor(0, 0, 0, 1.0); // 背景色  
  374.     glShadeModel(GL_SMOOTH);  
  375.     glEnable(GL_LIGHTING);  
  376.     glEnable(GL_LIGHT0);  
  377.     glDisable(GL_LIGHT1);  
  378.     glDepthFunc(GL_LEQUAL);  
  379.     glEnable(GL_DEPTH_TEST);  
  380.     glEnable(GL_CULL_FACE);  
  381.     glCullFace(GL_BACK);  
  382.     //glDisable(GL_NORMALIZE);  
  383.     //glPolygonOffset(1.0, 2);  
  384.     // 打開模型檔案,讀入模型資料并關閉檔案句柄  
  385.     model=lib3ds_file_open(filename);  
  386.     if (!model) {  
  387.         printf("***ERROR*** Loading 3DS file failed.");  
  388.         exit(1);  
  389.     }  
  390.     // 讀取模型的包圍盒  
  391.     lib3ds_file_bounding_box_of_nodes (model, 1, 0, 0, bbox.bmin, bbox.bmax, 0);  
  392.     for (i=0; i<3; i++) {  
  393.         sizes[i] = bbox.bmax[i]-bbox.bmin[i];  
  394.         center[i]= (bbox.bmax[i]+bbox.bmin[i])/2;  
  395.     }  
  396.     sizes[3] = MAX(sizes[0],sizes[1]); sizes[3] = MAX(sizes[3],sizes[2]);  
  397.     if (!model->cameras) {  
  398.         // 如果3ds Max制作的場景中沒有燈光、相機,就人為地在模型空間的四個角各加入一個  
  399.         add_default_cameras (model, &bbox, sizes, center);  
  400.         add_default_lights (model, &bbox, sizes, center);  
  401.     }  
  402.     if (!camera) {  
  403.         camera = model->cameras[0]->name;  
  404.     }  
  405.     camera_menu_id = glutCreateMenu(camera_menu);  
  406.     for (i=0; i<model->ncameras; i++){  
  407.         glutAddMenuEntry(model->cameras[i]->name, i);  
  408.     }  
  409.     glutAttachMenu(0);  
  410.     lib3ds_file_eval(model, 0);  
  411. }  
  412. static void reshape (int nWidth, int nHeight)  
  413. {  
  414.     gl_width = nWidth;  
  415.     gl_height = (nHeight==0?1:nHeight);  
  416.     glViewport(0, 0, gl_width, gl_height);  
  417. }  
  418. static void keyboard(unsigned char key, int x, int y)  
  419. {  
  420.     switch (key) {  
  421.     case 27:  
  422.         exit(0);  
  423.         break;  
  424.     case 'h':  
  425.         halt=!halt;  
  426.         glutPostRedisplay();  
  427.         break;  
  428.     }  
  429. }  
  430. int main(int argc, char** argv)  
  431. {  
  432.     glutInit(&argc, argv);  
  433.     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);  
  434.     glutInitWindowSize(640, 480);   
  435.     glutInitWindowPosition(100, 100);  
  436.     glutCreateWindow(argv[0]);  
  437.     init();  
  438.     glutDisplayFunc(display);   
  439.     glutReshapeFunc(reshape);  
  440.     glutKeyboardFunc(keyboard);  
  441.     glutMainLoop();  
  442.     _CrtDumpMemoryLeaks();  
  443.     return(0);  
  444. }  

我選了幾個3ds檔案測試,結果如下:

lib3ds 2.0 example 2