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库。)

本例仍然没有使用贴图。希望我的下个例子能把贴图做出来。

好了,代码全部贴在下面了。需要的库仍然可以在网上找到,就不废话了。

/// // player2.c // // 2009-2-14 // // 作者:cheungmine // // 参考: // // http://www.lib3ds.org/lib3ds-1.2.0/examples/player.c // // 目录结构: // // lib/lib3ds_2.0/src/ // debug/lib3ds20d.lib lib3ds20d.dll // release/lib3ds20.lib lib3ds20.dll // // lib/lib3ds_2.0/ // glut_test/player.c // // lib/win_opengl32/ // inc/gl.h glu.h glut.h // lib/opengl32.lib glu32.lib glut32.lib // bin/opengl32.dll glu32.dll glut32.dll // /// // 内存泄漏检测 // 在需要检测的地方放置语句: // _CrtDumpMemoryLeaks(); // 以下3句的次序不能改变 #define _CRTDBG_MAP_ALLOC #include<stdlib.h> #include<crtdbg.h> #include<stdio.h> #include<string.h> #include<math.h> #include<assert.h> #include <windows.h> // 使用 USE_SGI_OPENGL 可能在某些机器上运行 wglMakeCurrent 系列函数返回失败的结果 #define GLUT_NO_LIB_PRAGMA // #define USE_SGI_OPENGL #ifdef USE_SGI_OPENGL #include "../../sgi-opengl2-sdk/include/gl/gl.h" #include "../../sgi-opengl2-sdk/include/gl/glu.h" #include "../../sgi-opengl2-sdk/include/gl/glut.h" #pragma comment(lib, "../../sgi-opengl2-sdk/lib/opengl.lib") #pragma comment(lib, "../../sgi-opengl2-sdk/lib/glu.lib") #pragma comment(lib, "../../sgi-opengl2-sdk/lib/glut.lib") #else #include "../../win-opengl32/inc/GL.h" #include "../../win-opengl32/inc/GLU.h" #pragma comment(lib, "../../win-opengl32/lib/OPENGL32.lib") #pragma comment(lib, "../../win-opengl32/lib/GLU32.lib") #include "../../win-opengl32/inc/GLUT.h" #pragma comment(lib, "../../win-opengl32/lib/glut32.lib") #endif // // lib3ds // #include "../src/lib3ds.h" #ifdef _DEBUG # pragma comment(lib, "../src/debug/lib3ds20d.lib") #else # pragma comment(lib, "../src/release/lib3ds20.lib") #endif static const char* filename="E://GU2005//LIB//lib3ds_2.0//data//Bf109G6//Bf109G6.3ds"; //E://3DS//Spacecraft//Spacecraft.3ds"; //"E://GU2005//LIB//lib3ds_2.0//data//abom.3ds"; //"E:/3DS/House/house.3ds"; static Lib3dsFile *model=0; static const char* camera=0; static float current_frame=0.0; static int gl_width; static int gl_height; static int camera_menu_id=0; static int halt=0; #ifndef MAX # define MAX(x,y) ((x)>(y)?(x):(y)) #endif static void camera_menu(int value) { Lib3dsCamera *c=0; int i; for( i=0; i<value; i++ ){ if (i==model->ncameras) return; c = model->cameras[i]; } if (c) camera=c->name; } static void render_node(Lib3dsNode *node) { Lib3dsNode *p; Lib3dsMesh *mesh; Lib3dsFace *face; Lib3dsMaterial *mat; Lib3dsMeshInstanceNode *meshData; Lib3dsVector *norm_verts; Lib3dsVector *norm_faces; int i; unsigned fi; float M[4][4]; assert(model); // 递归 for (p=node->childs; p!=0; p=p->next){ render_node(p); } if (node->type==LIB3DS_NODE_MESH_INSTANCE) { if (strcmp(node->name,"$$$DUMMY")==0) { return; } if (!node->user_id) { mesh = lib3ds_file_mesh_for_node(model, node); assert(mesh); if (!mesh) { return; } node->user_id = glGenLists(1); glNewList(node->user_id, GL_COMPILE); norm_verts = (Lib3dsVector*) malloc(3*sizeof(Lib3dsVector)*mesh->nfaces); norm_faces = (Lib3dsVector*) malloc(sizeof(Lib3dsVector)*mesh->nfaces); lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_inv(M); glMultMatrixf(&M[0][0]); lib3ds_mesh_calculate_face_normals(mesh, (float (*)[3])norm_faces); lib3ds_mesh_calculate_vertex_normals(mesh, (float (*)[3])norm_verts); for (fi=0; fi<mesh->nfaces; ++fi) { face = &(mesh->faces[fi]); mat = 0; if (face->material>=0 && face->material<model->nmaterials) mat=model->materials[face->material]; if (mat) { // 使用材质 float s = pow(2, 10.0*mat->shininess); if (s>128.0) s = 128.0f; glMaterialfv(GL_FRONT, GL_AMBIENT, mat->ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular); glMaterialf(GL_FRONT, GL_SHININESS, s); } else { // 使用贴图 float a[]={0.2, 0.2, 0.2, 1.0}; float d[]={0.8, 0.8, 0.8, 1.0}; float s[]={0.0, 0.0, 0.0, 1.0}; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, d); glMaterialfv(GL_FRONT, GL_SPECULAR, s); } // Draw tri-face glBegin(GL_TRIANGLES); glNormal3fv(norm_faces[fi].v); // face normal for (i=0; i<3; ++i) { glNormal3fv(norm_verts[3*fi+i].v); // vertex normal glVertex3fv(mesh->vertices[face->index[i]]); } glEnd(); } free(norm_faces); free(norm_verts); glEndList(); } if (node->user_id) { glPushMatrix(); meshData = (Lib3dsMeshInstanceNode*) node; glMultMatrixf(&node->matrix[0][0]); glTranslatef(-meshData->pivot[0], -meshData->pivot[1], -meshData->pivot[2]); glCallList(node->user_id); // glutSolidSphere(50.0, 20,20); glPopMatrix(); } } } static void display(void) { int i, li; Lib3dsNode *nodC, *nodT, *nod; Lib3dsCameraNode *camNode; Lib3dsTargetNode *tgtNode; float M[4][4]; GLfloat a[] = {0.0f, 0.0f, 0.0f, 1.0f}; GLfloat c[] = {1.0f, 1.0f, 1.0f, 1.0f}; GLfloat p[] = {0.0f, 0.0f, 0.0f, 1.0f}; Lib3dsLight *l; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (!model) { exit(1); } nodC=lib3ds_file_node_by_name(model, camera, LIB3DS_NODE_CAMERA); nodT=lib3ds_file_node_by_name(model, camera, LIB3DS_NODE_CAMERA_TARGET); if (!nodC || !nodT) { assert(0 && "Camera or Target not found!"); exit(1); } camNode = (Lib3dsCameraNode*) nodC; tgtNode = (Lib3dsTargetNode*) nodT; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective( camNode->fov, gl_width/gl_height, 0.1f, 6000.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef(-90, 1.0, 0,0); li=GL_LIGHT0; for (i=0; i<model->nlights; i++) { l = model->lights[i]; glEnable(li); glLightfv(li, GL_AMBIENT, a); glLightfv(li, GL_DIFFUSE, c); glLightfv(li, GL_SPECULAR, c); // p? p[0] = l->position[0]; p[1] = l->position[1]; p[2] = l->position[2]; glLightfv(li, GL_POSITION, p); if (!l->spot_light) { continue; } p[0] = l->target[0] - l->position[0]; p[1] = l->target[1] - l->position[1]; p[2] = l->target[2] - l->position[2]; glLightfv(li, GL_SPOT_DIRECTION, p); ++li; } lib3ds_matrix_camera(M, camNode->pos, tgtNode->pos, camNode->roll); glMultMatrixf(&M[0][0]); for (nod=model->nodes; nod!=0; nod=nod->next) { render_node(nod); } if (!halt) { current_frame+=1.0; if (current_frame>model->frames) { current_frame=0; } lib3ds_file_eval(model, current_frame); glutSwapBuffers(); glutPostRedisplay(); } } // 增加默认的相机和目标 static add_default_cameras (Lib3dsFile *model, Lib3dsBBox *bbox, float sizes[], float center[]) { int index=0; Lib3dsCamera *cam; Lib3dsCameraNode *nodCam; Lib3dsTargetNode *nodTgt; // Camera_X cam = lib3ds_camera_new ("Camera_X"); assert(cam); memcpy(cam->target, center, sizeof(Lib3dsVector)); memcpy(cam->position, center, sizeof(Lib3dsVector)); cam->position[0] = bbox->bmax[0] + 1.5*MAX(sizes[1],sizes[2]); cam->near_range = (cam->position[0] - bbox->bmax[0])/2; cam->far_range = (cam->position[0] - bbox->bmin[0])*2; lib3ds_file_insert_camera(model, cam, index++); nodCam = lib3ds_node_new_camera(cam); assert(nodCam); lib3ds_file_append_node(model, (Lib3dsNode*)nodCam, 0); nodTgt = lib3ds_node_new_camera_target(cam); assert(nodTgt); lib3ds_file_append_node(model, (Lib3dsNode*)nodTgt, 0); // Camera_Y cam = lib3ds_camera_new ("Camera_Y"); assert(cam); memcpy(cam->target, center, sizeof(Lib3dsVector)); memcpy(cam->position, center, sizeof(Lib3dsVector)); cam->position[1] = bbox->bmin[1] - 1.5*MAX(sizes[0],sizes[2]); cam->near_range = (bbox->bmin[1]-cam->position[1])/2; cam->far_range = (bbox->bmax[1]-cam->position[1])*2; lib3ds_file_insert_camera(model, cam, index++); nodCam = lib3ds_node_new_camera(cam); assert(nodCam); lib3ds_file_append_node(model, (Lib3dsNode*)nodCam, 0); nodTgt = lib3ds_node_new_camera_target(cam); assert(nodTgt); lib3ds_file_append_node(model, (Lib3dsNode*)nodTgt, 0); // Camera_Z cam = lib3ds_camera_new ("Camera_Z"); assert(cam); memcpy(cam->target, center, sizeof(Lib3dsVector)); memcpy(cam->position, center, sizeof(Lib3dsVector)); cam->position[2] = bbox->bmax[2] + 1.5*MAX(sizes[0],sizes[1]); cam->near_range = (cam->position[2]-bbox->bmax[2])/2; cam->far_range = (cam->position[2]-bbox->bmin[2])*2; lib3ds_file_insert_camera(model, cam, index++); nodCam = lib3ds_node_new_camera(cam); assert(nodCam); lib3ds_file_append_node(model, (Lib3dsNode*)nodCam, 0); nodTgt = lib3ds_node_new_camera_target(cam); assert(nodTgt); lib3ds_file_append_node(model, (Lib3dsNode*)nodTgt, 0); // Camera_ISO cam = lib3ds_camera_new ("Camera_ISO"); assert(cam); memcpy(cam->target, center, sizeof(Lib3dsVector)); cam->position[0] = bbox->bmax[0] + 0.75f*sizes[3]; cam->position[1] = bbox->bmin[1] - 0.75f*sizes[3]; cam->position[2] = bbox->bmax[2] + 0.75f*sizes[3]; cam->near_range = (cam->position[0]-bbox->bmax[0])/2; cam->far_range = (cam->position[0]-bbox->bmin[0])*3; lib3ds_file_insert_camera(model, cam, index++); nodCam = lib3ds_node_new_camera(cam); assert(nodCam); lib3ds_file_append_node(model, (Lib3dsNode*)nodCam, 0); nodTgt = lib3ds_node_new_camera_target(cam); assert(nodTgt); lib3ds_file_append_node(model, (Lib3dsNode*)nodTgt, 0); } // 增加默认的灯光 static void add_default_lights (Lib3dsFile *model, Lib3dsBBox *bbox, float sizes[], float center[]) { int index=0; Lib3dsOmnilightNode *omniNode; Lib3dsLight *light; // light0 light = lib3ds_light_new("light0"); assert(light); light->spot_light = 0; light->see_cone = 0; light->color[0]=light->color[1]=light->color[2]=0.6f; light->position[0]=center[0]+sizes[3]*0.75; light->position[1]=center[1]-sizes[3]*1; light->position[2]=center[2]+sizes[3]*1.5; light->outer_range = 100; light->inner_range = 10; light->multiplier=1; lib3ds_file_insert_light(model, light, index++); omniNode = lib3ds_node_new_omnilight(light); assert(omniNode); lib3ds_file_append_node(model, (Lib3dsNode*)omniNode, 0); // light1 light = lib3ds_light_new("light1"); assert(light); light->spot_light = 0; light->see_cone = 0; light->color[0]=light->color[1]=light->color[2]=0.3f; light->position[0]=center[0]-sizes[3]; light->position[1]=center[1]-sizes[3]; light->position[2]=center[2]+sizes[3]*0.75; light->outer_range = 100; light->inner_range = 10; light->multiplier=1; lib3ds_file_insert_light(model, light, index++); omniNode = lib3ds_node_new_omnilight(light); assert(omniNode); lib3ds_file_append_node(model, (Lib3dsNode*)omniNode, 0); // light2 light = lib3ds_light_new("light2"); assert(light); light->spot_light = 0; light->see_cone = 0; light->color[0]=light->color[1]=light->color[2]=0.3f; light->position[0]=center[0]; light->position[1]=center[1]+sizes[3]; light->position[2]=center[2]+sizes[3]; light->outer_range = 100; light->inner_range = 10; light->multiplier=1; lib3ds_file_insert_light(model, light, index++); omniNode = lib3ds_node_new_omnilight(light); assert(omniNode); lib3ds_file_append_node(model, (Lib3dsNode*)omniNode, 0); } static void init(void) { int i; float sizes[4]; // 模型尺寸坐标 float center[3]; // 模型目标中心坐标 Lib3dsBBox bbox; // 模型范围 glClearColor(0, 0, 0, 1.0); // 背景色 glShadeModel(GL_SMOOTH); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glDisable(GL_LIGHT1); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); //glDisable(GL_NORMALIZE); //glPolygonOffset(1.0, 2); // 打开模型文件,读入模型数据并关闭文件句柄 model=lib3ds_file_open(filename); if (!model) { printf("***ERROR*** Loading 3DS file failed."); exit(1); } // 读取模型的包围盒 lib3ds_file_bounding_box_of_nodes (model, 1, 0, 0, bbox.bmin, bbox.bmax, 0); for (i=0; i<3; i++) { sizes[i] = bbox.bmax[i]-bbox.bmin[i]; center[i]= (bbox.bmax[i]+bbox.bmin[i])/2; } sizes[3] = MAX(sizes[0],sizes[1]); sizes[3] = MAX(sizes[3],sizes[2]); if (!model->cameras) { // 如果3ds Max制作的场景中没有灯光、相机,就人为地在模型空间的四个角各加入一个 add_default_cameras (model, &bbox, sizes, center); add_default_lights (model, &bbox, sizes, center); } if (!camera) { camera = model->cameras[0]->name; } camera_menu_id = glutCreateMenu(camera_menu); for (i=0; i<model->ncameras; i++){ glutAddMenuEntry(model->cameras[i]->name, i); } glutAttachMenu(0); lib3ds_file_eval(model, 0); } static void reshape (int nWidth, int nHeight) { gl_width = nWidth; gl_height = (nHeight==0?1:nHeight); glViewport(0, 0, gl_width, gl_height); } static void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; case 'h': halt=!halt; glutPostRedisplay(); break; } } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(640, 480); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); /* Memory leaks detecting */ _CrtDumpMemoryLeaks(); return(0); }

我选了几个3ds文件测试,结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值