//Establish constants used in sphere generation
FLOAT rDeltaRingAngle = (D3DX_PI / m_nRings);
FLOAT rDeltaSegAngle = (2.0f * D3DX_PI / m_nSegments);
//Generate the group of rings for the sphere
for (nCurrentRing = 0; nCurrentRing < m_nRings + 1; nCurrentRing++) {
FLOAT r0 = sinf(nCurrentRing * rDeltaRingAngle);
FLOAT y0 = cosf(nCurrentRing * rDeltaRingAngle);
//Generate the group of segments for the current ring
for (nCurrentSegment = 0; nCurrentSegment < m_nSegments + 1; nCurrentSegment++) {
FLOAT x0 = r0 * sinf(nCurrentSegment * rDeltaSegAngle);
FLOAT z0 = r0 * cosf(nCurrentSegment * rDeltaSegAngle);
vNormal.x = x0;
vNormal.y = y0;
vNormal.z = z0;
D3DXVec3Normalize(&vNormal, &vNormal);
//Add one vertex to the strip which makes up the sphere
pVertex->x = x0;
pVertex->y = y0;
pVertex->z = z0;
pVertex->nx = vNormal.x;
pVertex->ny = vNormal.y;
pVertex->nz = vNormal.z;
pVertex->tu = 1.0f – ((FLOAT)nCurrentSegment / (FLOAT)m_nSegments);
pVertex->tv = (FLOAT)nCurrentRing / (FLOAT)m_nRings;
pVertex++;
//Add two indices except for the last ring
if (nCurrentRing != m_nRings) {
*pIndices = wVertexIndex;
pIndices++;
*pIndices = wVertexIndex + (WORD)(m_nSegments + 1);
pIndices++;
wVertexIndex++;
}
}
}
if (FAILED(m_pIndexBuffer->Unlock())) {
LogError("<li>CSphere: Unable to unlock index buffer.");
return false;
}
if (FAILED(m_pVertexBuffer->Unlock())) {
LogError("<li>CSphere: Unable to unlock vertex buffer.");
return false;
}
return true;
}
So what is going on here? Once we have locked the index and vertex buffers we are ready to write to them. We use the same calculation as before to obtain the segment angle and a slight variation to obtain the ring angle. For the ring angle we only need to divide half a circle (PI radians) by the number of rings.
Once we have the ring and segment angles, we simply loop around once for each ring creating the vertices for each segment within that ring. We add an entry into the index buffer each time to create our triangle list. We set the normal values for each vertex to be the normalised position values. The radius of the sphere is always 1. You can use a scaling transformation matrix to increase or decrease the size of the sphere. Once complete, we unlock the vertex and index buffers ready for rendering.
The final scene when rendered will look something like the screenshot below:
You may have notices in the code above, some new logging functions called LogInfo and LogError. Well, by using these new logging functions we can create a more readable log file. Errors will be highlighted in red and normal information will be in black. To see the log file, take a look in the project folder at this file called Log.htm once you have run the sample code. There is also a LogWarning function, which you can use to log warnings that will appear in orange. There is also a LogMemoryUsage() function which will log the amount of memory your application is currently using. Do not use this function inside your game loop at it is far to slow.
Now we can create quite a few shapes: a cube, a sphere, a cone, a cylinder and even a simple terrain. These shapes are pretty basic, but can be very useful when you start creating your own scenes. In the next tutorial, we'll look at creating more complex objects like aliens, guns and vehicles.
DirectX Tutorial 10: Loading Complex Models
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.
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.
Package | Website | Price* |
---|---|---|
3D Studio Max | http://www.discreet.com/ | $3495 |
Maya | http://www.aliaswavefront.com/ | $1999 |
Cinema 4D | http://www.cinema4d.com/ | $1695 |
TrueSpace | http://www.caligari.com/ | $595 |
3D Canvas LP | http://www.amabilis.com/ | $34.95 |
MilkShape 3D | http://www.milkshape3d.com/ | $20 |
OpenFX | http://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.