new3dsloader.cpp
来自「3ds 文件读取程序」· C++ 代码 · 共 429 行
CPP
429 行
// New3DSLoader.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include <math.h>
#include "resource.h"
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glaux.lib")
#include "3dsModel.h"
#define SCREEN_WIDTH 800 // We want our screen width 800 pixels
#define SCREEN_HEIGHT 600 // We want our screen height 600 pixels
#define SCREEN_DEPTH 16 // We want 16 bits per pixel
//程序路径
char g_sAppPath[512];
//模型路径
char g_sMediaPath[512];
//纹理号表(100个)
UINT g_Texture[100] = {0}; // This holds the texture info, referenced by an ID
//全局参数
bool g_bFullScreen = true;
UINT g_ViewMode; // Set full screen as default
BOOL g_bLighting=FALSE;
HWND g_hWnd; // This is the handle for the window
RECT g_rRect; // This holds the window dimensions
HDC g_hDC; // General HDC - (handle to device context)
HGLRC g_hRC; // General OpenGL_DC - Our Rendering Context for OpenGL
HINSTANCE g_hInstance; // This holds the global hInstance for UnregisterClass() in DeInit()
float g_fEyeX=0;
float g_fEyeZ=0;
float g_fEyeY=5;
float g_fRotateAngle=3.14f;
//3个模型
C3DSModel g_3dsModel[3];
//
ATOM MyRegisterClass(HINSTANCE hInstance);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
HWND CreateMyWindow(LPSTR strWindowName, int width, int height, DWORD dwStyle, bool bFullScreen, HINSTANCE hInstance);
void ChangeToFullScreen();
WPARAM MainLoop();
void InitializeOpenGL(int width, int height);
void SizeOpenGLScreen(int width, int height);
bool bSetupPixelFormat(HDC hdc);
void Init(HWND hWnd);
void DeInit();
void RenderScene();
void UpdateScene();
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
//应用程序路径
GetModuleFileName(hInstance,g_sAppPath,512);
GetFilePath (g_sAppPath);
//素材路径
strcpy(g_sMediaPath,g_sAppPath);
strcat(g_sMediaPath,"models\\");
//是否使用全屏幕模式
if(MessageBox(NULL, "是否使用全屏幕模式?", "窗口选择", MB_YESNO | MB_ICONQUESTION) == IDNO)
g_bFullScreen = false;
//生成窗口
hWnd = CreateMyWindow("www.bvrain.com", SCREEN_WIDTH, SCREEN_HEIGHT, 0, g_bFullScreen, hInstance);
// 如果没有成功,退出
if(hWnd == NULL) return true;
// 初始化OPENGL
Init(hWnd);
// 主循环
return MainLoop();
}
//生成窗口
HWND CreateMyWindow(LPSTR strWindowName, int width, int height, DWORD dwStyle, bool bFullScreen, HINSTANCE hInstance)
{
HWND hWnd;
// 注册窗口类
MyRegisterClass(hInstance);
//全屏幕判断
if(bFullScreen && !dwStyle) // Check if we wanted full screen mode
{ // Set the window properties for full screen mode
dwStyle = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
ChangeToFullScreen(); // Go to full screen
//ShowCursor(FALSE); // Hide the cursor
}
else if(!dwStyle) // Assign styles to the window depending on the choice
dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
g_hInstance = hInstance; // Assign our global hInstance to the window's hInstance
RECT rWindow;
if(bFullScreen)
{
rWindow.left = 0;
rWindow.right = width; // Set Right Value To Requested Width
rWindow.top = 0;
rWindow.bottom = height;
}
else
{
rWindow.left = (GetSystemMetrics(SM_CXSCREEN)-width)/2; // Set Left Value To 0
rWindow.right = rWindow.left+width; // Set Right Value To Requested Width
rWindow.top = (GetSystemMetrics(SM_CYSCREEN)-height)/2; // Set Top Value To 0
rWindow.bottom = rWindow.top+height; // Set Bottom Value To Requested Height
}
AdjustWindowRect( &rWindow, dwStyle, false); // Adjust Window To True Requested Size
// Create the window
hWnd = CreateWindow("bvrain", strWindowName, dwStyle, rWindow.left, rWindow.top,
width, height,
NULL, NULL, hInstance, NULL);
if(!hWnd) return NULL; // If we could get a handle, return NULL
ShowWindow(hWnd, SW_SHOWNORMAL); // Show the window
UpdateWindow(hWnd); // Draw the window
SetFocus(hWnd); // Sets Keyboard Focus To The Window
return hWnd;
}
//注册窗口类
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_NEW3DSLOADER);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCSTR)IDC_NEW3DSLOADER;
wcex.lpszClassName = "bvrain";
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//窗口消息处理函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
LONG lRet = 0;
PAINTSTRUCT ps;
switch (uMsg)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(g_hInstance, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
break;
case WM_SIZE: // If the window is resized
if(!g_bFullScreen) // Do this only if we are NOT in full screen
{
SizeOpenGLScreen(LOWORD(lParam),HIWORD(lParam));// LoWord=Width, HiWord=Height
GetClientRect(hWnd, &g_rRect); // Get the window rectangle
}
break;
case WM_PAINT: // If we need to repaint the scene
BeginPaint(hWnd, &ps); // Init the paint struct
EndPaint(hWnd, &ps); // EndPaint, Clean up
break;
case WM_LBUTTONDOWN: // If the left mouse button was clicked
if(g_ViewMode == GL_TRIANGLES) { // We our drawing mode is at triangles
g_ViewMode = GL_LINE_STRIP; // Go to line stips
} else {
g_ViewMode = GL_TRIANGLES; // Go to triangles
}
break;
case WM_RBUTTONDOWN: // If the right mouse button was clicked.
g_bLighting = !g_bLighting; // Turn lighting ON/OFF
if(g_bLighting) { // If lighting is ON
glEnable(GL_LIGHTING); // Enable OpenGL lighting
} else {
glDisable(GL_LIGHTING); // Disable OpenGL lighting
}
break;
case WM_KEYDOWN: // If we pressed a key
switch(wParam) { // Check if we hit a key
case VK_ESCAPE: // If we hit the escape key
PostQuitMessage(0); // Send a QUIT message to the window
break;
}
break;
case WM_CLOSE: // If the window is being closed
PostQuitMessage(0); // Send a QUIT Message to the window
break;
default: // Return by default
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
break;
}
return lRet; // Return by default
}
// 关于对话框消息处理函数
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
//主循环
WPARAM MainLoop()
{
MSG msg;
while(1) // Do our infinate loop
{ // Check if there was a message
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT) // If the message wasnt to quit
break;
TranslateMessage(&msg); // Find out what the message does
DispatchMessage(&msg); // Execute the message
}
else // if there wasn't a message
{
UpdateScene();
RenderScene(); // Update the screen
}
}
DeInit(); // Clean up and free all allocated memory
return(msg.wParam); // Return from the program
}
///////////////////////////////// INIT GAME WINDOW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// 初始化函数
/////
///////////////////////////////// INIT GAME WINDOW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void Init(HWND hWnd)
{
GLfloat glDarkColor[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat glfLightAmbient[] = { 0.7f, 0.7f, 0.7f, 1.0f };
GLfloat glfLightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat glfLightSpecular[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat glfLingtPosition1[] = { 100.0f, 200.0f, 100.0f, 1.0f };
GLfloat glfLingtPosition2[] = { -200.0f, 20.0f, 10.0f, 1.0f };
GLfloat glfLingtPosition3[] = { 10.0f, -100.0f, -100.0f, 1.0f };
g_hWnd = hWnd; // Assign the window handle to a global window handle
GetClientRect(g_hWnd, &g_rRect); // Assign the windows rectangle to a global RECT
InitializeOpenGL(g_rRect.right, g_rRect.bottom); // Init OpenGL with the global rect
//读取3个模型
g_3dsModel[0].LoadModelFromFile("ground.3ds");
g_3dsModel[1].LoadModelFromFile("cheku.3ds");
g_3dsModel[2].LoadModelFromFile("chanche.3ds");
glLightfv (GL_LIGHT0, GL_AMBIENT, glfLightAmbient);
glLightfv (GL_LIGHT0, GL_DIFFUSE, glfLightDiffuse);
glLightfv (GL_LIGHT0, GL_SPECULAR, glfLightSpecular);
glLightfv (GL_LIGHT0, GL_POSITION, glfLingtPosition1);
glLightfv (GL_LIGHT1, GL_AMBIENT, glDarkColor);
glLightfv (GL_LIGHT1, GL_DIFFUSE, glfLightDiffuse);
glLightfv (GL_LIGHT1, GL_SPECULAR, glfLightSpecular);
glLightfv (GL_LIGHT1, GL_POSITION, glfLingtPosition2);
glLightfv (GL_LIGHT2, GL_AMBIENT, glDarkColor);
glLightfv (GL_LIGHT2, GL_DIFFUSE, glfLightDiffuse);
glLightfv (GL_LIGHT2, GL_SPECULAR, glfLightSpecular);
glLightfv (GL_LIGHT2, GL_POSITION, glfLingtPosition3);
glEnable(GL_LIGHT0); // Turn on a light with defaults set
glEnable(GL_LIGHT1);
glEnable(GL_LIGHT2);
glEnable(GL_LIGHTING); // Turn on lighting
}
//初始化OpenGL
void InitializeOpenGL(int width, int height)
{
g_hDC = GetDC(g_hWnd); // This sets our global HDC
// We don't free this hdc until the end of our program
if (!bSetupPixelFormat(g_hDC)) // This sets our pixel format/information
PostQuitMessage (0); // If there's an error, quit
g_hRC = wglCreateContext(g_hDC); // This creates a rendering context from our hdc
wglMakeCurrent(g_hDC, g_hRC); // This makes the rendering context we just created the one we want to use
glEnable(GL_TEXTURE_2D); // Enables Texture Mapping
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
SizeOpenGLScreen(width, height); // Setup the screen translations and viewport
}
//改变窗口大小
void SizeOpenGLScreen(int width, int height) // Initialize The GL Window
{
if (height==0) // Prevent A Divide By Zero error
{
height=1; // Make the Height Equal One
}
glViewport(0,0,width,height); // Make our viewport the whole window
// We could make the view smaller inside
// Our window if we wanted too.
// The glViewport takes (x, y, width, height)
// This basically means, what our our drawing boundries
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
// The parameters are:
// (view angle, aspect ration of the width to the height,
// The closest distance to the camera before it clips,
// FOV // Ratio // The farthest distance before it stops drawing)
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height, 1.0f ,800.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}
//结束处理
void DeInit()
{
if (g_hRC)
{
wglMakeCurrent(NULL, NULL); // This frees our rendering memory and sets everything back to normal
wglDeleteContext(g_hRC); // Delete our OpenGL Rendering Context
}
if (g_hDC)
ReleaseDC(g_hWnd, g_hDC); // Release our HDC from memory
if(g_bFullScreen) // If we were in full screen
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
}
UnregisterClass("bvrain", g_hInstance); // Free the window class
PostQuitMessage (0); // Post a QUIT message to the window
}
//更新场景
void UpdateScene()
{
static DWORD elapsedTime = 0;
static DWORD lastTime = 0;
DWORD time = GetTickCount();
elapsedTime = time - lastTime;
if (elapsedTime >=40) //40 毫秒
{
g_fRotateAngle+=float(PI/360);
if(g_fRotateAngle>=2*PI)g_fRotateAngle=0.0f;
g_fEyeX=30*sinf(g_fRotateAngle);
g_fEyeZ=30*cosf(g_fRotateAngle);
lastTime = time;
}
}
//绘制场景
void RenderScene()
{
glClearColor(0.8f,0.8f,1.0f,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The matrix
gluLookAt(g_fEyeX,g_fEyeY,g_fEyeZ,0,0,0,0,1,0);
//地面
g_3dsModel[0].Draw();
//车库
g_3dsModel[1].Draw();
//铲车
glTranslatef(-10,1.3f,0);
glScalef(0.025f,0.025f,0.025f);
g_3dsModel[2].Draw();
SwapBuffers(g_hDC); // Swap the backbuffers to the foreground
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?