Finally, we started the most exciting moment in 3D. We were always using our program to define the vertex, and then coloring or pasting the texture. It was always so nice, maybe you may have such questions: how can we draw complicated models if we always draw them? For example, a house or chair. Indeed, it is very difficult to draw such a model in the program area. This time we will solve this problem and use the model, it is the model created in some 3D modeling tools such as 3dmax. We import it into our program to show that our world is rich and colorful. Let's take a look at the Code:
// ================================================ ========================================================
// Desc: Use of the file Grid Model
// ================================================ ========================================================
# Include <d3dx9. h>
//-----------------------------------------------------------------------------
// Desc: global variable
//-----------------------------------------------------------------------------
Lpdirect3d9 g_pd3d = NULL; // direct3d object
Lpdirect3ddevice9 g_pd3ddevice = NULL; // direct3d device object
Lpd3dxmesh g_pmesh = NULL; // mesh model object
D3dmaterial9 * g_pmeshmaterials = NULL; // mesh model material
Lpdirect3dtexture9 * g_pmeshtextures = NULL; // mesh model texture
DWORD g_dwnummaterials = 0l; // Number of Mesh Model Materials
//-----------------------------------------------------------------------------
// Desc: sets the world matrix.
//-----------------------------------------------------------------------------
Void setworldmatrix ()
{
// Create and set the world Matrix
D3dxmatrixa16 matworld;
D3dxmatrixrotationy (& matworld, timegettime ()/1000.0f );
G_pd3ddevice-> settransform (d3dts_world, & matworld );
}
//-----------------------------------------------------------------------------
// Desc: sets the observation matrix and projection matrix.
//-----------------------------------------------------------------------------
Void setviewandprojmatrix ()
{
// Create and set the observation matrix
D3dxvector3 veyept (0.0f, 10.0f,-20366f );
D3dxvector3 vlookatpt (0.0f, 0.0f, 0.0f );
D3dxvector3 vupvec (0.0f, 1.0f, 0.0f );
D3dxmatrixa16 matview;
D3dxmatrixlookatlh (& matview, & veyept, & vlookatpt, & vupvec );
G_pd3ddevice-> settransform (d3dts_view, & matview );
// Create and set the Projection Matrix
D3dxmatrixa16 matproj;
D3dxmatrixperspectivefovlh (& matproj, d3dx_pi/4, 1.0f, 1.0f, 100366f );
G_pd3ddevice-> settransform (d3dts_projection, & matproj );
}
//-----------------------------------------------------------------------------
// Desc: Initialize direct3d
//-----------------------------------------------------------------------------
Hresult initd3d (hwnd)
{
// Create a direct3d object used to create a direct3d device object
If (null = (g_pd3d = direct3dcreate9 (d3d_sdk_version )))
Return e_fail;
// Set the d3dpresent_parameters structure to create a direct3d device object
D3dpresent_parameters d3dpp;
Zeromemory (& d3dpp, sizeof (d3dpp ));
D3dpp. paiwed = true;
D3dpp. swapeffect = d3dswapeffect_discard;
D3dpp. backbufferformat = d3dfmt_unknown;
D3dpp. enableautodepthstencel = true;
D3dpp. autodepthstencilformat = d3dfmt_d16;
// Create a direct3d device object
If (failed (g_pd3d-> createdevice (d3dadapter_default, d3ddevtype_hal, hwnd,
D3dcreate_software_vertexprocessing,
& D3dpp, & g_pd3ddevice )))
{
Return e_fail;
}
// Set the ambient light
G_pd3ddevice-> setrenderstate (d3drs_ambient, 0 xffffffff );
// Set the observation matrix and Projection Matrix
Setviewandprojmatrix ();
Return s_ OK;
}
//-----------------------------------------------------------------------------
// Desc: extract the texture file name from the absolute path
//-----------------------------------------------------------------------------
Void removepathfromfilename (lpstr fullpath, lpwstr filename)
{
// First convert the fullpath type to lpwstr
Wchar wszbuf [max_path];
Multibytetowidechar (cp_acp, 0, fullpath,-1, wszbuf, max_path );
Wszbuf [MAX_PATH-1] = l'/0 ';
Wchar * wszfullpath = wszbuf;
// Extract the file name from the absolute path
Lpwstr PCH = wcsrchr (wszfullpath ,'//');
If (PCH)
Lstrcpy (filename, ++ PCH );
Else
Lstrcpy (filename, wszfullpath );
}
//-----------------------------------------------------------------------------
// Desc: Creates a scene image.
//-----------------------------------------------------------------------------
Hresult initgeometry ()
{
Lpd3dxbuffer pd3dxmtrlbuffer; // buffer object for storing the mesh model material
// Load the grid model from the disk file
If (failed (d3dxloadmeshfromx (L "airplane. X", d3dxmesh_managed,
G_pd3ddevice, null,
& Pd3dxmtrlbuffer, null, & g_dwnummaterials,
& G_pmesh )))
{
MessageBox (null, l "cocould not find airplane. X", l "mesh", mb_ OK );
Return e_fail;
}
// Extract material attributes and texture file names from the mesh model
D3dxmaterial * d3dxmaterials = (d3dxmaterial *) pd3dxmtrlbuffer-> getbufferpointer ();
G_pmeshmaterials = new d3dmaterial9 [g_dwnummaterials];
If (g_pmeshmaterials = NULL)
Return e_outofmemory;
G_pmeshtextures = new lpdirect3dtexture9 [g_dwnummaterials];
If (g_pmeshtextures = NULL)
Return e_outofmemory;
// Extract grid model material attributes and texture file names one by one
For (DWORD I = 0; I <g_dwnummaterials; I ++)
{
// Material attributes
G_pmeshmaterials [I] = d3dxmaterials [I]. matd3d;
// Set the ambient light reflection coefficient of the model material because the model material itself has not set the ambient light reflection coefficient
G_pmeshmaterials [I]. Ambient = g_pmeshmaterials [I]. Diffuse;
G_pmeshtextures [I] = NULL;
If (d3dxmaterials [I]. ptexturefilename! = NULL &&
Strlen (d3dxmaterials [I]. ptexturefilename)> 0)
{
// Obtain the texture file name
Wchar filename [256];
Removepathfromfilename (d3dxmaterials [I]. ptexturefilename, filename );
// Create a texture
If (failed (d3dxcreatetexturefromfile (g_pd3ddevice, filename,
& G_pmeshtextures [I])
{
MessageBox (null, l "cocould not find texture file", l "mesh", mb_ OK );
}
}
}
// Release the buffer object that saves the model material and texture data created when the model file is loaded.
Pd3dxmtrlbuffer-> release ();
Return s_ OK;
}
//-----------------------------------------------------------------------------
// Desc: Release the created object
//-----------------------------------------------------------------------------
Void cleanup ()
{
// Release the mesh model material
If (g_pmeshmaterials! = NULL)
Delete [] g_pmeshmaterials;
// Release the texture of the mesh model
If (g_pmeshtextures)
{
For (DWORD I = 0; I <g_dwnummaterials; I ++)
{
If (g_pmeshtextures [I])
G_pmeshtextures [I]-> release ();
}
Delete [] g_pmeshtextures;
}
// Release the mesh model object
If (g_pmesh! = NULL)
G_pmesh-> release ();
// Release the direct3d device object
If (g_pd3ddevice! = NULL)
G_pd3ddevice-> release ();
// Release the direct3d object
If (g_pd3d! = NULL)
G_pd3d-> release ();
}
//-----------------------------------------------------------------------------
// Desc: Rendering scenario
//-----------------------------------------------------------------------------
Void render ()
{
// Clear the buffer
G_pd3ddevice-> clear (0, null, d3dclear_target | d3dclear_zbuffer,
D3dcolor_xrgb (0, 0, 255), 1.0f, 0 );
// Start Rendering scenario
If (succeeded (g_pd3ddevice-> beginscene ()))
{
Setworldmatrix (); // sets the world matrix.
// Render the mesh model one by one
For (DWORD I = 0; I <g_dwnummaterials; I ++)
{
// Set materials and textures
G_pd3ddevice-> setmaterial (& g_pmeshmaterials [I]);
G_pd3ddevice-> settexture (0, g_pmeshtextures [I]);
// Rendering Model
G_pmesh-> drawsubset (I );
}
// Scene Rendering ends
G_pd3ddevice-> endscene ();
}
// Display the scenario on the screen
G_pd3ddevice-> present (null, null );
}
//-----------------------------------------------------------------------------
// Desc: A window process that processes messages.
//-----------------------------------------------------------------------------
Lresult winapi msgproc (hwnd, uint MSG, wparam, lparam)
{
Switch (MSG)
{
Case wm_destroy:
Cleanup ();
Postquitmessage (0 );
Return 0;
}
Return defwindowproc (hwnd, MSG, wparam, lparam );
}
//-----------------------------------------------------------------------------
// Desc: entry function
//-----------------------------------------------------------------------------
Int winapi winmain (hinstance hinst, hinstance, lpstr, INT)
{
// Register the window class
Wndclassex WC = {sizeof (wndclassex), cs_classdc, msgproc, 0l, 0l,
Getmodulehandle (null), null,
L "classname", null };
Registerclassex (& WC );
// Create a window
Hwnd = createwindow (L "classname", l "grid model ",
Ws_overlappedwindow, 200,100,500,500,
Getasktopwindow (), null, WC. hinstance, null );
// Initialize direct3d
If (succeeded (initd3d (hwnd )))
{
// Create a scene image
If (succeeded (initgeometry ()))
{
// Display window
Showwindow (hwnd, sw_showdefault );
Updatewindow (hwnd );
// Enter the message loop
MSG;
Zeromemory (& MSG, sizeof (MSG ));
While (msg. message! = Wm_quit)
{
If (peekmessage (& MSG, null, 0, 0, pm_remove ))
{
Translatemessage (& MSG );
Dispatchmessage (& MSG );
}
Else
{
Render (); // Rendering scenario
}
}
}
}
Unregisterclass (L "classname", WC. hinstance );
Return 0;
}
The above Code uses airplane. X file. The extension type of this file is. X is specially developed by Microsoft for d3d learning. In the first phase of learning, we have enough files of this type, this file should be placed in the project directory like the image used last time. However, model files generally contain texture images. Do not forget to put the texture images and files together, there are many online tutorials on model conversion. You can search elsewhere. I will not talk about it here. If you have a conversion method, you can use 3dmax to make a simple model and then export it to an X file.
Looking at this code, there are a lot of unfamiliar things. Well, it doesn't matter. In fact, all these are past accumulation. It's no big deal. Let's take a closer look:
Let's take a look at the global volume:
//-----------------------------------------------------------------------------
// Desc: global variable
//-----------------------------------------------------------------------------
Lpdirect3d9 g_pd3d = NULL; // direct3d object
Lpdirect3ddevice9 g_pd3ddevice = NULL; // direct3d device object
Lpd3dxmesh g_pmesh = NULL; // mesh model object
D3dmaterial9 * g_pmeshmaterials = NULL; // mesh model material
Lpdirect3dtexture9 * g_pmeshtextures = NULL; // mesh model texture
DWORD g_dwnummaterials = 0l; // Number of Mesh Model Materials
All the specific explanations are available in the Code. do you understand it now? It's okay. Let's talk about it later.
We can see that there is another function we have never seen before.
Hresult initgeometry ()
{
Lpd3dxbuffer pd3dxmtrlbuffer; // buffer object for storing the mesh model material
// Load the grid model from the disk file
If (failed (d3dxloadmeshfromx (L "airplane. X", d3dxmesh_managed,
G_pd3ddevice, null,
& Pd3dxmtrlbuffer, null, & g_dwnummaterials,
& G_pmesh )))
{
MessageBox (null, l "cocould not find airplane. X", l "mesh", mb_ OK );
Return e_fail;
}
// Extract material attributes and texture file names from the mesh model
D3dxmaterial * d3dxmaterials = (d3dxmaterial *) pd3dxmtrlbuffer-> getbufferpointer ();
G_pmeshmaterials = new d3dmaterial9 [g_dwnummaterials];
If (g_pmeshmaterials = NULL)
Return e_outofmemory;
G_pmeshtextures = new lpdirect3dtexture9 [g_dwnummaterials];
If (g_pmeshtextures = NULL)
Return e_outofmemory;
// Extract grid model material attributes and texture file names one by one
For (DWORD I = 0; I <g_dwnummaterials; I ++)
{
// Material attributes
G_pmeshmaterials [I] = d3dxmaterials [I]. matd3d;
// Set the ambient light reflection coefficient of the model material because the model material itself has not set the ambient light reflection coefficient
G_pmeshmaterials [I]. Ambient = g_pmeshmaterials [I]. Diffuse;
G_pmeshtextures [I] = NULL;
If (d3dxmaterials [I]. ptexturefilename! = NULL &&
Strlen (d3dxmaterials [I]. ptexturefilename)> 0)
{
// Obtain the texture file name
Wchar filename [256];
Removepathfromfilename (d3dxmaterials [I]. ptexturefilename, filename );
// Create a texture
If (failed (d3dxcreatetexturefromfile (g_pd3ddevice, filename,
& G_pmeshtextures [I])
{
MessageBox (null, l "cocould not find texture file", l "mesh", mb_ OK );
}
}
}
// Release the buffer object that saves the model material and texture data created when the model file is loaded.
Pd3dxmtrlbuffer-> release ();
Return s_ OK;
}
In fact, this function is used to load X files on the hard disk to the memory for our use. The lpd3dxmesh used is the polygon network model interface defined by the d3d extended utility library, to represent a complex 3D object model, including vertex data, material data, and texture data.
Lpd3dxbuffer pd3dxmtrlbuffer; // buffer object for storing the mesh model material
This data structure is generated for ease of operation. It stores various types of data such as vertex coordinates, materials, and textures. You can use the interface function getbufferpointer to get the data in the buffer and use getbuffersize to get the data size.
Example of extracting material and texture file names from the mesh model:
D3dxmaterial * d3dxmaterials = (d3dxmaterial *) pd3dxmtrlbuffer-> getbufferpointer (); a forced type conversion mode is provided here, which can be directly converted and very convenient.
There is also a function:
D3dxloadmeshfromx (L "airplane. X", d3dxmesh_managed,
G_pd3ddevice, null,
& Pd3dxmtrlbuffer, null, & g_dwnummaterials,
& G_pmesh)
This function is used to read X Files from files.
Let's take a closer look:
Hresult d3dxloadmeshfromx (
Lpctstr pfilename,
DWORD options,
Lpdirect3ddevice9 pd3ddevice,
Lpd3dxbuffer * ppadjacency,
Lpd3dxbuffer * ppmaterials,
Lpd3dxbuffer * ppeffectinstances,
DWORD * pnummaterials,
Lpd3dxmesh * ppmesh
);
Parameters
Pfilename
X file name, in string format.
Options
It is usually set to d3dxmesh_managed, indicating that the video memory is used.
Pd3ddevice
Environment pointer, which is commonly used
Ppadjacency
Point to the buffer memory address used to store information about the polygon surrounding each polygon. We cannot use this information, so we set it to null.
Ppmaterials
[Out] The buffer address used to store model textures and materials.
Ppeffectinstances
[Out] refers to the buffer address used to store the model effect instance.
Pnummaterials
[Out] Number of materials stored.
Ppmesh
[Out] pointer to the generated d3d mesh model.
The remaining function is to extract materials, textures, and other information from the obtained pd3dxmtrlbuffer, and set the environment light in the material. The code is simple and you can understand it.
This loading function is explained here. There is also a major change to the function below, which is in the rendering function:
Void render ()
{
// Clear the buffer
G_pd3ddevice-> clear (0, null, d3dclear_target | d3dclear_zbuffer,
D3dcolor_xrgb (0, 0, 255), 1.0f, 0 );
// Start Rendering scenario
If (succeeded (g_pd3ddevice-> beginscene ()))
{
Setworldmatrix (); // sets the world matrix.
// Render the mesh model one by one
For (DWORD I = 0; I <g_dwnummaterials; I ++)
{
// Set materials and textures
G_pd3ddevice-> setmaterial (& g_pmeshmaterials [I]);
G_pd3ddevice-> settexture (0, g_pmeshtextures [I]);
// Rendering Model
G_pmesh-> drawsubset (I );
}
// Scene Rendering ends
G_pd3ddevice-> endscene ();
}
// Display the scenario on the screen
G_pd3ddevice-> present (null, null );
}
In this function, we are still familiar with the previous part, that is, after setting the world matrix:
For (DWORD I = 0; I <g_dwnummaterials; I ++)
{
// Set materials and textures
G_pd3ddevice-> setmaterial (& g_pmeshmaterials [I]);
G_pd3ddevice-> settexture (0, g_pmeshtextures [I]);
// Rendering Model
G_pmesh-> drawsubset (I );
}
These codes are a bit unfamiliar. Take a closer look, g_pd3ddevice-> setmaterial (& g_pmeshmaterials [I]);
This Code sets the corresponding material. Previously we used g_pd3ddevice-> settexture (0, g_pmeshtextures [I]);
Used to set a texture image.
G_pmesh-> drawsubset (I );
A 3D mesh model is usually composed of several submodels. When a model is created, the material and texture are usually set for each submodel. Therefore, these submodels may use different materials and textures, therefore, you need to set materials and textures for different submodels during rendering. The g_dwnummaterials in the above program indicates the number of materials and textures, which is actually the number of submodels of the 3D model.
Here, the program is about to be introduced. If you have any questions, we can discuss them together.
This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/luoya263547560/archive/2009/04/05/4049563.aspx