北理工虛擬現實作業-OpenGL下實現3D Max模型的匯入
阿新 • • 發佈:2018-12-31
兩個禮拜之前,李鳳霞老師又佈置了一次虛擬現實作業,這次的作業題目是自己從網上找一個汽車的3D模型(一般都是3D Max建的),然後把這個模型匯入到OpenGL中,在工程中顯示出來,同時能通過滑鼠的移動切換視角。由於時間太緊(矩陣分析要考試),這個作業就拜託了宿舍的一個同學,可是沒想到最後還是自己做了,就這樣也學了點東西(不過不知道有什麼用)。
先貼下實現效果,車輛是網上找的一個奧迪Q7 3D模型,為了簡單不再貼紋理了
下面說下實現步驟:
1、轉換3D Max模型
3D MAX建模後生成的一般都是3ds字尾的檔案,直接匯入貌似還要在opengl中建立對應的資料結構,上網查了一些資料後,我發現可以
2、新增標頭檔案和初始化
把.h檔案新增到工程中去後,在.h檔案中加入一個新的類用以匯入
class CModernho { public: CModernho(void); public: ~CModernho(void); public: long ScanBytes(int pixWidth, int bitsPixel); void MyMaterial(GLenum mode, GLfloat * f, GLfloat alpha); void SelectMaterial(int i); GLint Gen3DObjectList(); }; CModernho::CModernho(void) { } CModernho::~CModernho(void) { }
然後在主檔案中新增對應的內容
開頭定義一個變數,應該對應匯入的數目
int listnum;//匯入變數
在main函式中初始化時載入該模型
CModernho cmodernho;
listnum = GL3DS_initialize_audi(); //載入audi
最後在渲染函式中呼叫該模型
glCallList(listnum);// 呼叫載入函式
這樣就得到了以上的效果,工程結構如下:
audi.h就是view3d轉換後的檔案,很長,其中包含很多點線的資訊,顯然是把模型的各個點和線都儲存下來了
testcar.cpp程式碼如下:
#include <gl/glaux.h> #include <gl/glu.h> #include <GL/glut.h> #include "math.h" #include <stdio.h> #include"audi.h" int flag=1; double front_Point_x,front_Point_y,front_Point_z; double pos_Up[3],pos_Down[3],pos_Motion[3]; double viewmatrix[16],modelviewmatrix[16]; #define GLUT_MIDDLE_UP_BUTTON 0x0003 #define GLUT_MIDDLE_DOWN_BUTTON 0x0004 float PI = 3.141592654; int listnum;//匯入變數 GLfloat xangle = 0.0; GLfloat yangle = 0.0; GLfloat oDistance = 5.0; int cacheX = 0; int cacheY = 0; int xSpeed = 1; int ySpeed = 1; BOOL light=true; // 光源的開/關 BOOL lp=true; // L鍵按下了麼? GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; //環境光引數 GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; // 漫射光引數 GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f }; // 光源位置 void motion(int x, int y) //滑鼠響應事件 { if (x > cacheX) { yangle = yangle - xSpeed; } if (x < cacheX) { yangle = yangle + xSpeed; } if (y > cacheY) { xangle = xangle + ySpeed; } if (y < cacheY) { xangle = xangle - ySpeed; } glutPostRedisplay(); cacheX = x; cacheY = y; } void setView() //設定觀察角度 { glRotatef(10,1.0,0.0,0.0); glRotatef(22,0.0,1.0,0.0); glTranslatef(-20.5,-10.0,-55.0); glGetDoublev(GL_MODELVIEW_MATRIX,viewmatrix); } void SetRC() //設定渲染 { glEnable (GL_LINE_SMOOTH); glEnable (GL_BLEND); glShadeModel(GL_FLAT); glFrontFace(GL_CW); glEnable (GL_LINE_SMOOTH); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glHint(GL_LINE_SMOOTH,GL_NICEST); glEnable(GL_DEPTH_TEST); glPolygonMode(GL_BACK,GL_LINE); glEnable( GL_COLOR_MATERIAL); } void renderWorld() //模擬場景 { glFrontFace(GL_CCW); glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); float oXhudu = PI / (180 / xangle); //沿著X軸旋轉的角度 float oYhudu = PI / (180 / yangle); //沿著Y軸旋轉的角度 //設定場景座標 GLfloat btm = oDistance * cos(oXhudu); GLfloat vpY = oDistance * sin(oXhudu); GLfloat vpX = btm * sin(oYhudu); GLfloat vpZ = btm * cos(oYhudu); if (fabs(xangle) < 90.0) { gluLookAt(vpX, vpY, vpZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); } else { if (fabs(xangle) >= 270.0) { if (fabs(xangle) >= 360.0) { xangle = 0.0; } gluLookAt(vpX, vpY, vpZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); } else { gluLookAt(vpX, vpY, vpZ, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0); } } if (fabs(yangle) >= 360.0) { yangle = 0; } //繪製場景座標軸 glLineWidth(1); glBegin(GL_LINES); glColor3f(1.0,0.0,0.0); glVertex3f(0.0,0.0,0.0); glVertex3f(200,0,0); glColor3f(0.0,1.0,0.0); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,200,0.0); glColor3f(0.0,0.0,1.0); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,0.0,200.0); glEnd(); glColor3f(0.3,0.5,0.1); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glGetDoublev(GL_MODELVIEW_MATRIX,modelviewmatrix); glCallList(listnum);// 呼叫載入函式 } void myDisplay(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glClearColor(0.1,0.1,0.1,0.1); glPushMatrix(); setView(); renderWorld(); glPopMatrix(); glutSwapBuffers(); } void myReshape(int w,int h) //重新繪製場景 { GLfloat nRange = 100.0f; glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(w<=h) //建立裁剪區域(左右下上近遠) { glOrtho(-nRange,nRange,-nRange*h/w,nRange*h/w,-100,100); } else { glOrtho(-nRange*w/h,nRange*w/h,-nRange,nRange,-100,100); } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void mouse(int btn, int state, int x, int y) { if(btn==GLUT_RIGHT_BUTTON ) { if(state == GLUT_DOWN) { if(light) { glDisable(GL_LIGHT1); // 啟用光源 light=!light; } else { glEnable(GL_LIGHT1); light=!light; } } } glutPostRedisplay();//重新載入 } int main(int argc, char *argv[]) //主函式 { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(10, 10); glutInitWindowSize(800, 800); glutCreateWindow("VR-2"); glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // 設定環境光 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // 設定漫射光 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // 光源位置 glEnable(GL_LIGHT1); // 啟用光源 CModernho cmodernho; listnum = GL3DS_initialize_audi(); //載入audi glutDisplayFunc(&myDisplay); glutReshapeFunc(&myReshape); SetRC(); glutMouseFunc(mouse); glutMotionFunc(&motion); glutMainLoop(); return 0; }
至於滑鼠控制完全不會,抄了一個同學的程式碼,不過我知道滑鼠響應是在glutMotionFunc(&motion);這個函式中實現的,具體也不深究了,做完這一次後還有最後一次作業,希望不要太難。