![]() |
If any of you have played Homeworld, I'm sure one of the first things you take note of are the trails coming from the ships. It's a great effect and pretty simple to do. Conceptually, it's simple but implementing it in code is somewhat tricky.
![]() Now think about it, if you have 20 segments, how many vertices do you have? There is one pair of vertices for each segment, but if you do that, you'll leave a segment at the end without any ending vertices. So the number of vertex pairs you have is one more than the number of segments you have. Each pair of vertices has two vertices therefore if you have 20 segments, you have 42 vertices. So let's start seeing some code. Here is the creation of the mesh, the surface, and the array containing the vertices. You also need to create an array holding the vertices' positions. Remember that an array starts at zero, so if you want to make an array hold 2, the value you put in for the dimension is 1, one less than the actual number. Now for the triangles, like I said, there are 4 triangles per segment. Two quads a segment, two triangles per quad, one quad for top and on for bottom. Let's initialize the array holding the triangles. With the memory allocated, you have to create the vertices and meshes now. It's easier to pre-create the vertices and update their positions than clearing the mesh and recreating everything. Now takes a little graphical thinking, we have to organize the verticies and triangles in the right positions. The diagram shows how I organize my stuff. ![]() Okay, simple enough, right? Nope! You gotta specify the UV coordinates! Unless you want a trail that's a solid color with no fading. Okay, I've provided the trail texture: ![]() Now how do you create the UV coordinates for that? Well, first off you gotta know what UV coordinates are. UV coordinates help specify the location of a vertice on a texture. How UV coordinates work is that at UV coordinates (0,0), the position is at the top-left corner of the image. At (1,1), the position is at the bottom-right corner. basically a percentage value across the width and height of the texture. Looking at the image, we know that the top vertice will already have a V (vertical, height) coordinate of 0 and the bottom vertice with a V coordinate of 1. Now, if a U coordinate of 1 is considered at the very and of the image and that's where our trail ends, how would we go about specifying the coordinates for the U component? Well, if there are a maximum of 20 segments, 21 verticies, the U coordinate is simply the segment vertice number divided by the maximum number of segments verticies. This works because UV coordinates work as a percentage. Check out the diagram if you're having trouble recognizing this. ![]() So with that in mind, here's the code. Remember that we don't need to care about the position of the vertex during its creation because we'll be changing it later anyway. Okay, now our vertices are in place. Next is yet another tricky part, the triangles. Going back to the diagram with the vertices' labels, follow that in order to figure out which vertices each triangle uses. So basically, here's how the creation of the triangles goes. ...and tada! We have our mesh trail finished. Now we have to update it. Update RoutineRemember how the trail works, each time it's updated, the first segment is positioned to where the engine is. Then for every other segment, it recieves the positions of the segment ahead of it, therefore the segment ahead of it passes its position over to the next segment. First let's whip up the code for the positioning of the first segment to the engine, the first segment is also position 0 in the array. For now, I'm going to be using x# and z# for the position of the engine assuming that this is only in a 2d plane overhead, the y value stays at a contant zero. If you want to make it into 3d, you just need to add another dimension to the vertice positions. Also, I'm going to specify a width# variable that determines how wide the trail is. Accompanying that is an ang# variable that represents the angle of direction of the ship on the y axis. Check out the diagram.![]() Here's the code for position the first segment towards the engine. Okay, now we need to assign the rest of the vertices their new positions which are the old positions of the vertices ahead of them. We need to take note here though that we're not incrementing in the for loop but decrementing. This is because we're going from the end of the trail to the beginning. Now think about it, if we ran it forward, every vertex position will eventually be the same. Another thing I'm going to take into consideration is the update time. The update time is basically the delay between each trail update. If you have an update time of 0 or 1, it'll update every frame. An update time of 2 would update the mesh every other frame, and etc. The longer the update time, the longer the trail but it tends to look rough with a long update time. However, I don't make the first segment dependent to the update time because if I do, it'll look like the trail detaches itself from the engine. For now, I'll use an every other update method. So here it goes. We put that for loop before the engine attachment part so that we can retrieve the old engine position before it gets updated. Okay, now that the vertex positions are updated, we need to update the actual vertices. We simply run through a loop for each vertex and position it where it belongs. Then of course, we need to update the mesh and then update it's normals. And there you have it! Here's a sample program if you want to see it in action, make sure you run it with the texture in the same directory. In the sample program, I added a little wavy feature where it adds a small random number to the vertex positions to give it a wavy appearance. I'm hoping you understood the code before you implemented it, but either way it's fine as long as you got it working. If you have any comments or questions, just run 'em over to world_creator@hotmail.com. Sample ProgramFor a printable copy of this article, please click HERE.
This site is Copyright© 2000-2004, BlitzCoder. All rights reserved.
|