52880.fb2 DirectX 8 Programming Tutorial - читать онлайн бесплатно полную версию книги . Страница 10

DirectX 8 Programming Tutorial - читать онлайн бесплатно полную версию книги . Страница 10

DirectX Tutorial 10: Loading Complex Models

Introduction

In this tutorial we will look at how to create a complex model and load it into your DirectX application. So far, we have created some simple shapes: cubes, spheres, cones, etc. But when it comes to creating a game we will need to create objects like guns, people, buildings and spaceships. You could workout where all the vertices for an object are on a piece of paper and then create the object in code, or you could use a piece of software called a "3D modeller". I would recommend using the modelling software! It is far easier! You can download the full source code by clicking the "Download Source" link above.

3D Modelling Software

You will need to use a 3D modelling package to create your game objects. Below is a list of 3D modellers that you may like to try (in order of price). There are many more 3D modelling packages available, but from my research for this topic, these seem to be the most popular.

To use a 3D modelling package with DirectX, it must be able to export your model to a .x file. This can be done as a built-in feature, as an optional plug-in or you could use a conversion program to convert one file format into the .x file format.

PackageWebsitePrice*
3D Studio Maxhttp://www.discreet.com/$3495
Mayahttp://www.aliaswavefront.com/$1999
Cinema 4Dhttp://www.cinema4d.com/$1695
TrueSpacehttp://www.caligari.com/$595
3D Canvas LPhttp://www.amabilis.com/$34.95
MilkShape 3Dhttp://www.milkshape3d.com/$20
OpenFXhttp://www.openfx.org/Free

* Prices are correct at time of publication. Please go to the products website to confirm current pricing. You can convert these prices into your local currency at http://www.oanda.com/.

So which one should you use? Well, that is entirely up to you. However, I have tried 3D Canvas (trial version), MilkShape 3D (trial version) and OpenFX (full version). I tried these three packages because their price was so low, which is good if you are creating games as a hobby.

3D Canvas is a good piece of software but it has one major downside. If you are using Windows XP or Windows 2000 (like me) it can reboot your machine without warning! The help advised me that updating my display driver to the latest version would fix the problem… but I have the latest version already! So, I'm afraid 3D Canvas is no good for me.

MilkShape 3D is an excellent package for creating low polygon models. It has most of the features that you need to create a 3D model, and is pretty easy to use. There are loads of tutorials on the web and a forum on the MilkShape site that is really useful.

OpenFX is a great all round 3D modeller. I found it easy to use and very powerful. The main problem I had was exporting my model into a .x file. The only way I found was to export to a .3ds file and then use the conv3ds.exe tool that comes with the DirectX SDK to convert it to a .x file. The only problem was that it lost the textures when exporting to a .3ds file. There is also very limited help. So, OpenFX isn't the right tool for me.

So, I have decided to use MilkShape 3D because it is cheap, it can export to a .x file (via a free plug-in) and it is easy to use.

Creating a .x file with MilkShape 3D

Once you have your 3D modelling package, the next thing to do is create a model. For this tutorial have created a simple spaceship. I used the tutorials http://xu1productions.com/3dstudio/tutorials.html to get me started with MilkShape. Fig 10.1 below, shows a screenshot of MilkShape 3D with my completed spaceship model.

Fig 10.1

Once your model is complete, you need to export it to a .x file. To do this with MilkShape, download and install the "DirectX 8.1 Exporter" plug-in by John Thompson from the MilkShape website. Then open your model in MilkShape and go to "File"→"Export"→"DirectX (JT)…". Select a location for your .x file, then select the options you require (normally the defaults) and press "OK". You are now ready to load your model into your DirectX program.

Loading a .x file into your program

For this tutorial I have created a wrapper class called CMesh for loading and rendering meshes loaded from a .x file. Below is the main code for the CMesh class. The constuctor shows how to load a mesh from a .x file and store it in memory. The destructor shows how to free the memory that was used to store the mesh. The Render method shows how to render a mesh.

The CMesh constructor takes two parameters, the first is a pointer to the device and the second is string containing the path of the .x file to load. We use the D3DXLoadMeshFromX function to load the mesh into memory. Once this is done we create two arrays, one to hold the materials and one to hold the textures of our model. We then loop around and populate the two arrays from the loaded mesh. The last thing to do is make sure that the normals are set for each vertex of the mesh. We clone the mesh and use the D3DXComputeNormals function to set the normals.

In the destructor we release each texture and the mesh itself. We also have to delete the two array pointers that we created in the constructor.

The Render function is pretty straight forward, we simply loop through each subset of the mesh and render it with the appropriate texture and material.

CMesh::CMesh(LPDIRECT3DDEVICE8 pD3DDevice, LPSTR pFilename) {

 LPD3DXBUFFER pMaterialsBuffer = NULL;

 LPD3DXMESH pMesh = NULL;

 m_pD3DDevice = pD3DDevice;

 if (FAILED(D3DXLoadMeshFromX(pFilename, D3DXMESH_SYSTEMMEM, m_pD3DDevice, NULL, &pMaterialsBuffer, &m_dwNumMaterials, &pMesh))) {

  m_pMesh = NULL;

  m_pMeshMaterials = NULL;

  m_pMeshTextures = NULL;

  LogError("<li>Mesh '%s' failed to load", pFilename);

  return;

 }

 D3DXMATERIAL* matMaterials = (D3DXMATERIAL*)pMaterialsBuffer->GetBufferPointer();

 //Create two arrays. One to hold the materials and only to hold the textures

 m_pMeshMaterials = new D3DMATERIAL8[m_dwNumMaterials];

 m_pMeshTextures = new LPDIRECT3DTEXTURE8[m_dwNumMaterials];

 for (DWORD i = 0; i < m_dwNumMaterials; i++) {

  //Copy the material

  m_pMeshMaterials[i] = matMaterials[i].MatD3D;

  //Set the ambient color for the material (D3DX does not do this)

  m_pMeshMaterials[i].Ambient = m_pMeshMaterials[i].Diffuse;

  //Create the texture

  if (FAILED(D3DXCreateTextureFromFile(m_pD3DDevice, matMaterials[i].pTextureFilename, &m_pMeshTextures[i]))) {

   m_pMeshTextures[i] = NULL;

  }

 }

 //We've finished with the material buffer, so release it

 SafeRelease(pMaterialsBuffer);

//Make sure that the normals are setup for our mesh

 pMesh->CloneMeshFVF(D3DXMESH_MANAGED, MESH_D3DFVF_CUSTOMVERTEX, m_pD3DDevice, &m_pMesh);

 SafeRelease(pMesh);

 D3DXComputeNormals(m_pMesh);

 LogInfo("<li>Mesh '%s' loaded OK", pFilename);

}

CMesh::~CMesh() {

 SafeDelete(m_pMeshMaterials);

 if (m_pMeshTextures != NULL) {

  for (DWORD i = 0; i < m_dwNumMaterials; i++) {

   if (m_pMeshTextures[i]) {

    SafeRelease(m_pMeshTextures[i]);

   }

  }

 }

 SafeDelete(m_pMeshTextures);

 SafeRelease(m_pMesh);

 LogInfo("<li>Mesh destroyed OK");

}

DWORD CMesh::Render() {

 if (m_pMesh != NULL) {

  for (DWORD i = 0; i < m_dwNumMaterials; i++) {

   m_pD3DDevice->SetMaterial(&m_pMeshMaterials[i]);

   m_pD3DDevice->SetTexture(0, m_pMeshTextures[i]);

   m_pMesh->DrawSubset(i);

  }

  return m_pMesh->GetNumFaces();

 } else {

  return 0;

 }

}

Scaling makes your object darker?

One extra thing to note is that if you scale the mesh you will also scale the normals. This will have the effect of making the object darker the more it is scaled. To fix this problem we need to enable the D3DRS_NORMALIZENORMALS render state. This is done with one call to the SetRenderState function as shown below.

m_pD3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);

For this tutorial we will create three spaceships and rotate them each about a different axis. The final scene when rendered will look something like the screenshot below:

Summary

So now we can create any object we like, we are no longer limited to cubes and spheres. Remember, when you create your models, make sure they have a low number of polygons. The more polygons you have the more your frame rate will drop. In the next tutorial we will look at adding 2D elements to a 3D scene. That is useful when it comes to creating scores and energy bars.