Need pointers.

Started by
9 comments, last by jpetrie 16 years, 8 months ago
Ahoy. A few months ago, I completed my "3D engine" which basically sets up lighting, can load and animate models from my own format (converted from MS3D) and handle basic rotation. Since then, I've been stuck in a well of thinking. Where... next? I've identified the next step as some kind of world-model interaction system - or at least a system that makes it possible. Seeing as my mathematical prowess is lacking, I've tried to avoid anything that risks breaking my internal calculator. My current idea is to have a coordinates-esque system, where the player model is known to be loaded at *,*,* - and all movements will be calculated and the coordinates altered accordingly. Before which, the would-be coordinates (where the player is going) would be checked against some kind of boolean table to see whether they're allowed to go there. This covers the issue of them walking through walls/objects, but it seems very -- for want of a better word -- icky. It also leaves out the business of raising/lowering the model when they walk up and down steps. I've no idea what to be looking into for this. Gravity engines? Collision detection? I'm scared. I'm an amazing programmer (if I do say so myself) - I just can't handle math. It literally takes me a minute to work out 5*6. To roughly summarize: - What would I need to research for stopping players walking through other models? - What would I need to research for raising/lowering the model when the ground level changes? - Are there any other potentially useful tutorials or guides that may relate to keeping track of a "world" and the players/NPC's/etc in it? Any and all help will be appreciated.
Advertisement
Disclaimer: Very simplified, and probably incomplete text following ;)

A way to describe your world and what objects are in it is called a scenegraph.
A scenegraph also has the advantage that it can describe relations between objects.
For example a car has 4 wheels. To move the care you can:
A:
- Move the car body
- move left front wheel
- move right front wheel
-etc.
OR
B:
Wheels are 'child' objects of car, and when you move the car body, they move along with it.

When you look into scenegraphs you will come into contact with terms as 'world coordinates' and 'local coordinates'.
In the example above a world coordinate could be the car's position in the world, and the local coordinates for the wheel could be the distance from the car body( 1m left, 1.50m in front for the left front wheel.)

Scenegraphs are a very big and much discussed subject. So You might want to read up on them first.
Some links that helped me:
Scenegraph info
More scenegraph info

Hope this helps.


edit: Fixed links
Look at all the pretty colours!
Quote:Original post by Smee
To roughly summarize:

- What would I need to research for stopping players walking through other models?


You need to research collision detection, using bit-fields (your boolean table) to reperesent where an object can/cannot go is a very bad idea, space is continuous not discrete (...ish [wink], in reality a computer can only model things discretely and real space may have some sort of infintisimal discrete unit).
Collision detection involves vector mathematics, you can likely find tons of examples on the internet that you can literally copy and paste so you dont need to understand them.

Quote:- What would I need to research for raising/lowering the model when the ground level changes?

This is collision response, related to collision detection, think of it like this "so now i know i am colliding, what do i do?". Again this usually involves vector mathematics, but you should realise that the way you respond to colliding with one thing (like stairs) will be different to how you respond to another (like lava).

Quote:- Are there any other potentially useful tutorials or guides that may relate to keeping track of a "world" and the players/NPC's/etc in it?

Look into scene-graphs, theres a discussion about them going on currently on about them now but thers loads of information on them on these forums and [google].

A comment about the wikipedia article, I wrote most of that a while back and its not really my best work. Also because scene-graphs are a wide and oftentimes misunderstood concept theres also plenty of miss-information in there especially when considering a 3D game since its an article on scene-graphs in general (which feature in everything from games to 2D graphics editing packages), so use it as a place to get started (actually snk_kid recommended it as a good starting point once) but dont dwell on it to much for your implementation [smile]

Edit: Everything you could ever want to know about scene-graphs
Quote:
Where... next?

Write a game. Until you do, you'll have no idea if your "engine" is actually useful or not, and as you do, you'll have a much better idea of the features you need to add to your engine codebase to make it useful.

If you try to simply assemble a bunch of "engine-esque" technologies in isolation, without a firm need (the game), there is an absurdly high chance you will end up with a hodgepodge of tech that looks nice on paper, but in practice does not integrate well and requires massive refactoring to actually be helpful in creating a game.
Thanks for the feedback so far. ;)

Gave the scenegraph links a read over & they've given me some food for thought. The technique seems to be more relevant to large maps which I don't think I'll be experimenting with any time soon, but I'm sure a time will come in the future.

@ jpetrie: I'm yet to write a game, but I believe that what I have done so far is useful. What I have is a seperate header file with 3 classes (one for each file format - static model, animated model & multiple animation model) and the relevant functions to load, draw/animate and rotate their specific model. Can't really say that it could be rendered useless because it's not yet complex enough to become distant to the possible cause. I do however understand that the more stuff becomes piled on top of it, the more useless it could become for whatever I may decide to use it for e.g. making it suitable for FPS and then wanting to make an RPG.

@ dmatter: I'd already established that a boolean table would be a hog, but I figured it'd be acceptable given what I intend to do. My current sights are set on an RPG & I know that the maps won't be that large... with the possible exception of one or two. I also have a fear that the code behind collision detection and response may be more intense (at least on the CPU) than is necessary. It stands to reason that a constant calculation of "model pushing down on floor" would be more demanding than one-off calculations after movement - unless the detection/response could also be done strictly after movement?

I have read one or two collision detection articles, but I've never picked up anything that seems relevant to detecting when a model has intruded the space of another model, funnily enough. It all seems to rant on about building complex physics engines which come across as overkill - at least for what I'll be needing it for, anyway.

Do fill me in. ;)
Quote:Original post by Smee
Gave the scenegraph links a read over & they've given me some food for thought. The technique seems to be more relevant to large maps which I don't think I'll be experimenting with any time soon, but I'm sure a time will come in the future.

Ah yes, granted if you dont have an overly complex scene then you can use simple lists (like a list of NPC, weapons, 'n'-wat-not), scene-graphs are great at managing scenes but if you only really have simple ones (notice 'simple' doesnt have to relate to how big or small a level is) then lists are probably more optimal..always use the structure that best suites the job.

Quote:
@ dmatter: I'd already established that a boolean table would be a hog, but I figured it'd be acceptable given what I intend to do. My current sights are set on an RPG & I know that the maps won't be that large... with the possible exception of one or two.

It could be acceptable if a single boolean represents a relatively large area of space? So you're really performing collision detection with a level-map grid. But if you're mapping bools to teeny tiny little voxels of space then its no good.

Quote:
I also have a fear that the code behind collision detection and response may be more intense (at least on the CPU) than is necessary. It stands to reason that a constant calculation of "model pushing down on floor" would be more demanding than one-off calculations after movement - unless the detection/response could also be done strictly after movement?

Yes collision detection 'can be' intensive and the cost grows rapidly with the more objects you add in to test. But you do only need to test collisions for objects that are moving. I think NeHe has an openGL tutorial about colliding with the world geometry (not that I'm especially a fan of his tutorials, no offense to NeHe).

Quote:
I have read one or two collision detection articles, but I've never picked up anything that seems relevant to detecting when a model has intruded the space of another model, funnily enough. It all seems to rant on about building complex physics engines which come across as overkill - at least for what I'll be needing it for, anyway.

Generally we appoximate the space of each model using a bounding volume. In order of complexity typical bounding volumes are as follows: simplest bounding volume is a sphere, next is an axis-aligned-bounding-box (AABB), third are oriented-bounding-boxes (OBB), and last is a polygonal model itself so requres polygon-to-polygon collision tests.

Search for things like AABB collision tests... and sphere to sphere collision tests. IMO most people opt for using AABBs because theyre usually a better approximation than a sphere even though a sphere test is easier to perform.
Quote:
@ jpetrie: I'm yet to write a game, but I believe that what I have done so far is useful. What I have is a seperate header file with 3 classes (one for each file format - static model, animated model & multiple animation model) and the relevant functions to load, draw/animate and rotate their specific model. Can't really say that it could be rendered useless because it's not yet complex enough to become distant to the possible cause. I do however understand that the more stuff becomes piled on top of it, the more useless it could become for whatever I may decide to use it for e.g. making it suitable for FPS and then wanting to make an RPG.

Already useless! ;)

Well, not really, and not for the reasons I was initially describing. I do still recommend you start building some kind of actual game with the tech as soon as possible, though, even if its small and simple. You'll be surprised how much it reveals about the usability of your tech.

Now, that said, your model classes are broken. You don't need three, you need one. What's a static mesh? A mesh with no associated animations. What's an animated mesh? A mesh with one associated animation. What's a multiple-animation mesh? A mesh with more than one associated animation.

You can get away with exactly one mesh class; the animations bound to that mesh are values of mesh properties, not properties themselves. Multiple mesh classes in the form you've got will become brittle and unmaintainable moving forward. There are three points of extensibility that cannot be swapped easily for each other (because of the rigid nature of the type system in C++), and they all are very similar. Inheritance would even be overkill here.
I'd be interesting in you clarifying how it's already useless, jpetrie. Not quite seeing how a model loader/animat0r/etc is useless in a 3D game... which requires models that can be loaded and animated.

The reason for 3 classes is because I didn't want the code to have to detect which format is being used. For example, if I know that the map is just going to be a concrete floor and a brick wall with a hole in it, I just select the class for the static models and then that'll handle it. If I had one class, it'd have to detect whether it's static and it'd have functions and allocated data that's useless to the cause. I guess it's hard to grasp my method without seeing what's being done.

@ dmatter: Thanks for filling a few more blanks. ;) I'll continue hunting for articles and such like when I'm not ready to pass out.
Quote:
I'd be interesting in you clarifying how it's already useless, jpetrie. Not quite seeing how a model loader/animat0r/etc is useless in a 3D game... which requires models that can be loaded and animated.

Er... did the smiley face and "well, not really..." sentence not clarify that I wasn't entirely serious with that comment? There are, as I said, problems with having three different model classes, however.

Quote:
The reason for 3 classes is because I didn't want the code to have to detect which format is being used. For example, if I know that the map is just going to be a concrete floor and a brick wall with a hole in it, I just select the class for the static models and then that'll handle it. If I had one class, it'd have to detect whether it's static and it'd have functions and allocated data that's useless to the cause. I guess it's hard to grasp my method without seeing what's being done.

No, I see what you're doing. You're doing it inefficiently -- and you've mentioned something else that is a potential serious flaw in your design. But I will address that later.

First, the whole issue with "detecting the format" should be a moot point. You should have a singular format for model data in additional to a singular class. I assume you have model and animation data tightly coupled together(*) in your file format. So a model file might look like this:
(number of vertices)(number of indices)(big list of vertices)(big list of indices)(number of animations)(big list of animation data)

A "static model" has a 0 for the number of animations, and thus the loader won't read any animation data. Likewise, the model class stores this zero, and so when told to Update(), it tries to update its current animation, realizes that it has no animations, and does nothing.

Splitting up your model classes into three different, district types is just giving you duplication for the sake of duplication, increasing the number of points you have to to monitor in maintaining your code, and decreasing the flexibility of your code (because you have to treat each location where a model is required as a decision -- is this model going to ever need to animate, because if you make the wrong choice now it requires a code change. If you make it so that all models might be animated, but some models are loaded from data files that don't have animation, you tie expansion to data rather than code, as well as remove a bunch of duplicated code and overall streamlining your product. This "extra work" you seem to be concerned about for detecting "if the model has is animated" is trivial - if(numAnimations == 0) and other similar boilerplate.

Okay, now the second issue I mentioned I noticed. You're not going to like this, because on the surface it's going to sound like I'm countering my own advice above. But here we go. Your level/map data should not be a model. It should have very similar stuff - perhaps you can reuse underlying geometry buffer objects, or something. But treating levels or maps as "large pieces of geometry" is very inefficient. The needs of a model, that is, some kind of displayable actor or character, are vastly different from those of a level, and it is poor design to comingle them (failure of the single responsibility principal). Levels, for example, should be stored in way that is efficient for visibility checks and collision, usually in some kind of spatial hierarchy of sorts. This is often because you rarely render the entire level at one time, or even perform processing on the entire level at once. You work with visible subsets, or something similar.

But a model doesn't need the ability to be sliced up into an octree for efficient partitioning -- a model you're either going to draw, or not. Even those they are ultimately composed of similar fundamentals (geometry), they have wildly different interface characteristics and requirements, and similarly wildly different extra data (levels, as you pointed out, probably don't ever contain animation, but they might contain an extra set of specialized geometry for navigation or collision, et cetera).

(*) A third point is that I find this coupled (model and animation) to be distasteful and limiting as well. Animations can easily be used to drive multiple models, so the animation should not be a part of the model data, but a separate entity that is later associated with the model(s) it drives. This only makes sense for skeletal animations, however, as vertex-blended animations (being by nature tightly coupled to the vertex data they animate) don't have as strong a need for separation.
I understand your 2nd point. Taking into account that maps wouldn't be solid models, there'd really be no need for a static format/loader/drawer, cutting the classes down to 2. I can also see the sense in molding the formats into one, having the less complex formats the same as the more complex formats but without the data they're intended to hold. I suppose the overhead in the files wouldn't be that great.

Now... I'm left with further confusion about worlds/maps. Confused mainly about the specific differences between two things which are basically made of the same minerals, but... in different ways? How would you build a non-random map without storing its information in a file? That's my definition of model. I'm not college educated, so exact meanings of terms evade me.

This topic is closed to new replies.

Advertisement