Heightmap Problems?

Started by
13 comments, last by Phil_93 11 years ago

Hey everyone,

I posted a while back about having issues with heightmaps. I was on Easter break from university so I had to try and get help on-line but I couldn't really understand what I needed to do. I started back at university yesterday and asked my tutor to take a look and he couldn't make help me, he didn't seem to understand the code which is annoying being as I went off the tutorials supplied by my university which were made by said tutor. I'm still seriously stuck on this and I'm starting to run out of places to get help.

Could anyone please help me? My code is a bit long to actually put on the post, besides it's better off if someone who knows what they are doing can see the entire thing so they know exactly where I'm going wrong. I don't want people giving me code or anything like that. I just want someone to look through my program, see where I'm going wrong and talk me through how to fix it, I really want to be able to understand this better.

Any help is greatly appreciated.

Edit: Just to mention the problem I'm having is that my car in my game is just hovering at a fixed height and phasing through the high sections of the heightmap. As far as I know all the code to alter it's height etc. is there, it just isn't doing anything.

Here are just the source files instead of having to download a full program: http://www.mediafire.com/download.php?dwbh8ws11t4oys8

Advertisement
Just as a note: gamedev.net operates on a volunteer basis, and a lot of us will just do the occasionally run through the forums as we go about our day. Downloading and debugging a 250MB project is typically going to take more time than a lot of people really want to spend. I'm coming off a bout of insomnia, though, so I went ahead and downloaded your project to see what I can find.

The first thing I did was opened up your Heightmap.cs source file, to see how you determine the height of the map at a given point. In Heightmap, you have the method GetHeight() which seems to perform this task. Then I did a Find in Files with the search phrase GetHeight to see where it might be called. In the directory Turbo Rally the search found only 2 places where the search token GetHeight appears: at line 94 in Heightmap.cs (where it is defined) and at line 78 in Game1.cs where appears the line:

//player.world = Matrix.CreateTranslation(player.yaw, terrain.GetHeight(player.position), player.pitch);
Note that it's commented out.

Nowhere else in the source was GetHeight found. So then I went source diving to see if you were calculating the heightmap height elsewhere in some other fashion. In Car.UpdateDrive you calculate a new world vector for the car, but you never account for heightmap height. So I am forced to assume that the only place you are actually trying to account for heightmap height is in the above commented-out line of code.

Now, in reference to my opening point, you probably should have posted the source files Heightmap.cs, Car.cs, Game1.cs (none of them are very large) rather than posting a 250MB zip archive, and you'd get a lot more eyes on your project and potential answers.

Sorry about posting a link to a large file, I wasn't sure what do do because I didn't want people having to trawl though bits of code on a post.

I forgot to explain that line, I added it in because I thought it would help me sort my problem out but it just locks my car up so it will only travel in a straight line and my game crashes when the car reaches the side of the heightmap, this is why it was commented out.

I'm really stuck, sorry If I'm being a pain.

You say you added that because you thought it would sort your problem, but where/how were you calling GetHeight before you added that?

Correcting for terrain height is a simple matter of querying the heightmap for the height, and correcting the Y value of the position. So perhaps after applying translationThisFrame to position in Car.cs, you could then calculate the heightmap value, correct position.Y, then construct your world matrix. This would also serve to put this height correction inside of Car where it would make more sense than putting it inside Game.
Yeah, I'm not too good with this and I tried a lot of different things before asking for help, I also tried changing some of the effect. lines at the bottom of the heightmap class. Oh right, so I'd be better off putting GetHeight in the actual car class rather than trying to pass it through the Update or Draw in the main game? Most of the time when I try to implement GetHeight I get errors. Thank you so much for helping out by the way.
Well, typically the Physics system would handle this sort of thing, rather than the Game class or the Car class where it currently resides. In physics-enabled applications, the Physics subsystem will integrate the simulation, apply any collision correction to fix penetrations, then notify the participant objects of their new transforms. In your current model, though, there just aren't very many elegant answers to your question. Integrating movement/physics into the object methods like this presents you with some issues that may come back to bite you later:

1) Visibility of the Heightmap to Car. Since Car is responsible for its own movement and physics, it needs to be aware of the world. That means, it'll have to have a reference of some sort to the Heightmap so that during UpdateDrive it can call GetHeight to correct its Y coordinate. This adds a dependency upon Heightmap to Car, so that any change to Heightmap requires changes or, at least, recompilation for Car. It will also have to have access to whatever organizational structure you use to hold all cars, in order to correct for collisions with other cars and objects. This can create circular dependency chains and knotty logical issues.

2) Different versions of Car for Player or AI controlled cars. If you decide to implement AI cars, you'll need a different version of Car from what you have now since an AI car wouldn't respond to controller input. So that means either duplicating update code, or refactoring Car into a hierarchy (a thorny, twisted road to go down in a game of any sort of complexity).

3) Modifying the simulation could mean modifying code spread out across many modules. Say you want to add gravity to the simulation, rather than just clamping Y values directly to the heightmap surface. This would facilitate, for example, jumping and falling. However, if the physics are spread out among all the various participating object classes (PlayerCar, AICar, etc...) then you have to go and correct each participating class's Update methods with the new code. Make sure you get them all, because if you forget to enable gravity for one then it will not behave uniformly with the remainder of the objects. And if later you decide to tweak something else, then again you need to traverse the entire codebase modifying each class Update method to account for it.

In a simulation that is built upon an actual physics library (rather than homegrown gestalt update methods) then actual movement, collision correction, etc... are encapsulated in a physics subsystem whose sole responsibility is to integrate the physics and move stuff around. Individual cars don't move themselves; they simply apply, or inject, forces into the system. Pressing the accelerator, for example, would inject a linear impulse in one direction, tapping the brake would inject a linear impulse or some other form of decelerating impulse in another. Holding the thumbsticks for steering would inject angular impulses. And so on. But the actual movement of objects would be encapsulated within the physics system, acting upon the properties set for a given object, and pushing transform matrices back out to the participating objects after the simulation step is performed. In this way, changes to the Physics subsystem are confined to a single module rather than spread out across several classes, and behavior is shared among all types of objects without introducing any kind of dependencies between those types.

It is for architecture questions like this that people have begun to strongly recommend composition-based systems rather than concrete classes such as Car. If your game were to progress along your current curve toward a fairly complex simulation, you would find an exponential increase in the difficulty of maintaining and modifying it. Eventually, for example, you might want to implement other vehicle types: motorcycles, trucks, jet-powered cars, etc... And you find yourself either building horrible, complex hierarchies and trying to shoehorn every vehicle type into it, or duplicating a horrendous amount of code across multiple discrete classes. Either way, it becomes more and more of a nightmare trying to maintain it, and significant changes to the simulation will require significant changes to large portions of the codebase.

I haven't looked your code, but when I used a heigthmap on Panda3d I had a similiar problem, maybe they use the same approach.

When you use a heightmap the heights will be between 0 and 255 (or normalized in the interval [0, 1.0]). In this case you need to use an upper axis scale that is applied to every pixel . If you are only getting the position height, you might have apply the same scale to find the actual upper axis coordinate.

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).

I feel really stupid for saying this but a lot of that just went straight over my head (It's my own fault I should have said to keep it simple, I'm fairly new to programming. Even more so to xna). My university is giving us code/tutorials that doesn't work properly and not even the tutors seem to understand their own stuff.

I've been trying to do this for about 4 weeks straight now and I'm getting to the point where I just want to give up and go home. It's starting to look like university isn't for me.

I feel really stupid for saying this but a lot of that just went straight over my head (It's my own fault I should have said to keep it simple, I'm fairly new to programming. Even more so to xna). My university is giving us code/tutorials that doesn't work properly and not even the tutors seem to understand their own stuff.

I've been trying to do this for about 4 weeks straight now and I'm getting to the point where I just want to give up and go home. It's starting to look like university isn't for me.

Don't give up. Sorry for getting a bit advanced there.

To get back to the code as presented, try to break it down into the exact steps that are occurring here.

1) Input is polled to get the positions of the thumbsticks and triggers. These values are used to determine forward/backward movement and turning.

2) Objects are moved (updated) based on this input.

In Car::UpdateDrive, this sequence of actions occurs:
1) Translation for the frame is calculated, based on the input
2) New position for the car is calculated by translating the old position by the input translation.
3) New direction is calculated based on the input
4) New world matrix is calculated for the car to be drawn

When you added the line

//player.world = Matrix.CreateTranslation(player.yaw, terrain.GetHeight(player.position), player.pitch);
to Game1.cs, you basically negated everything that was done in Car::UpdateDrive, setting the world matrix for player directly. As you discovered for yourself, that wasn't the correct thing to do. But if you analyze exactly what UpdateDrive is doing, you might be able to deduce when the best time to correct the Y location is: right after the new position is calculated, but before a new world matrix is constructed for the object. So if you were to add some sort of code to UpdateDrive, right after the new position is calculated, that will call the Heightmap, get the height for the new position, and set the new position's Y value to this height, then it should work.

Thank you so much for the help. I'll go and have a try now.

I just hope I'm not being annoying or anything.

This topic is closed to new replies.

Advertisement