Collision Detection in own content

Nov 14, 2007 at 2:17 PM
We're working with this engine for a few weeks now (tryin' to get into the whole thing et cetera) and now we've got a more or less big problem: When loading own content (a Coke-machine and a person) the objects stick in the terrain at about half-height. I made a screenshot for showing you: http://picasaweb.google.de/miriamluecke/DiesesUndJenes/photo#5132698149077359106

What I did:
Derived a Class "weltobjekt" from DynamicEntity. In method LoadEntities() created a new weltobjekt with the following code:
{" weltobjekt held;

if (sceneTerrain != null)
{
#region held laden
held = new weltobjekt(Device, Content, this);
held.Initialize(new Vector3(954, 954, 240), new Vector3(0, 0, 3.25f), "./Models/held", "held");
held.SetMass(1f);
held.SetRoughness(1f);
entityManager.AddEntity(held);
ArcBallCamera.SetCameraTarget(held);
#endregion
..."}
I tried enlarging the radius of the bounding sphere: no result. I played around with the mass: no result.
I implemented a bounding box: no result.
I'm at my wits' end. Any further ideas?
Thanks a lot,
Kuschelknaeuel
Nov 14, 2007 at 3:13 PM
Edited Nov 14, 2007 at 3:13 PM
Your offset of the model is wrong. If you look inside the Sphere.ProcessGroundCollision you will see that the position is adjusted according to the radius of the spehere.

You will need to do something similar in WorldObject ("WeltObjekt")
Coordinator
Nov 14, 2007 at 7:37 PM
Edited Nov 14, 2007 at 7:39 PM
The physics for models hasn't been fully setup yet, were prototyping a new framework first. What I'd suggest is finding the bounds of your model, like a bounding box, and then find the height from the bottom of that to your model's center. Which is basically what is going on right now for the sphere, just like Sturm said.

Basically until the physics component is truly started (right now it is just a placeholder), we're not checking the sphere's mesh against the terrain, only its center point + radius. If your models are centered you need to calculate the model's height and divide it by 2. This should give you your offset value.
Coordinator
Nov 26, 2007 at 4:54 PM
This issue has been addressed in v0.182. It is still only a placeholder, but it should be much more useful now to get you by until the physics component is finished.
Nov 27, 2007 at 9:02 AM
Edited Nov 27, 2007 at 12:34 PM
Well, I got it working in version 0.17 with the ProcessGroundCollision-method and changing the model's balance point in the modelling software, but by now, just replacing this blue "Player"-model with the figure, the figure again sticks in the ground. I updated the XNA to 2.0 Beta and compiled it as 'release', like it was told in the release notes. Maybe I'm just too stupid to understand the whole thing...?
I got rid of the blue figure, but the figure bounces a little bit. Where to change this?
Coordinator
Nov 27, 2007 at 3:12 PM
Go to CommonVars.cs and change LOCK_FRAMERATE to false. This should help with bouncing figures.

To keep your figure from sticking in the ground, you need to actually create your models as if they were standing on a plane, if that is how you want them in the game (this may change later). I tested a few different models of different shapes and sizes, but when I exported them from my modeler (which was 3dsMax in my case), I made sure the bottom on the model was at the ground plane level.

If you want to leave all of your models centered in your modeler, then you need to take Radius into account when you use Position in all physics checks.

public virtual bool ProcessWaterPhysics(GameTime gameTime)
        {
            // If under level of water plane
            if (Physics.SceneWater.IsUnderWater(new Vector3(this.Position.X, this.Position.Y, this.Position.Z + BoundingSphere.Radius)))
            {

You'll notice where the Radius is taken into account for water. This keeps the model at water height. So if you decide to leave your models centered you need to change this code above to this:

public virtual bool ProcessWaterPhysics(GameTime gameTime)
        {
            // If under level of water plane
            if (Physics.SceneWater.IsUnderWater(this.Position))
            {

You'll also need to change this function:

public virtual void ProcessGroundCollision(GameTime gameTime)
        {
            // Only check collision with terrain if this entity is in 
            // the x,y bounds of the heightmap
            if (Physics.SceneTerrain.IsAboveTerrain(this.Position.X, this.Position.Y))
            {
                Vector3 TerrainNormal = Physics.SceneTerrain.GetNormal(this.Position.X, this.Position.Y);
 
                // Check if player has hit or is touching the ground
                if (this.Position.Z <= TerrainHeightBelowEntity)
                {
                    this.Position.Z = TerrainHeightBelowEntity;  // Sticks entity back above ground
 
                    // Process bouncing of entity
                    Physics.ProcessBounce(ref VelocityVector, Elasticity, ref TerrainNormal, out VelocityVector);
 
                    // Process friction of item to ground
                    Physics.ProcessFriction(gameTime, ref VelocityVector, Roughness, out VelocityVector);
                }
            }
        }

You'll need to change TerrainHeightBelowEntity to TerrainHeightBelowEntity - this.BoundingSphere.Radius, or something similar.

Its probably easier to simply center your models.
Coordinator
Nov 27, 2007 at 3:30 PM
I meant to say to go to CommonVars.cs and change LOCK_FRAMERATE to TRUE. Sorry.
Nov 27, 2007 at 5:56 PM
Maybe I didn't express clearly: the model has its centre actually at its feet - but as soon as I have my IDE re-installed, I will take a closer look at this
Coordinator
Nov 27, 2007 at 8:26 PM
If you need you can send me the project and I can take a look at what is going on. Every model I tried, even ones I'd formerly used from other projects ended up working fine, as long as I placed the model so its bottom was at the exporter's center position.
Nov 27, 2007 at 8:50 PM
I'm totally sorry - I took the wrong model ashamed
But by now there's another problem: No matter which rotation angle I choose for the model, when applying the camera (ArcBall and Fixed) to the model it always shows the model from front (we got that fixed in one of the older versions with try-and-error).
Coordinator
Nov 27, 2007 at 9:36 PM
I believe this might be a bug in the code, I noticed this recently as well. I believe the forward vector might be reversed somewhere in the code that sets the rotation of model, and I didn't notice because my models were backwards.

However, I'll have to double check. Could you verify that the front of your model is facing along the +Y axis in your modeler? If so it is a bug I will fix soon.
Coordinator
Nov 28, 2007 at 4:30 AM
The pyramid models for the blue and yellow entities in the demo are facing in the +Y direction, so I believe everything should be working properly. In 3dsMax it is slightly confusing, as the default view has +Y going away from the screen. But in the engine, +Y is the default forward direction, which means it is going away from the camera, just like in 3dsMax. Your modeler might be different however. When I'm in fixed camera mode the model does face away from my camera.

If someone else wants to give feedback on this that'd be great too, I'm not 100% confident in my matrix rotation math at all times.

Nov 28, 2007 at 10:42 AM
Fixed it with the CameraArc. There's still the problem, that the ArcBallCam is fixed to the feet (center) of the model. Looks allright if the starting distance and angle of the camera are far away from the model (I played around and wrote the fitting values into the log). By now, the next thing to get working is the control of the player-figure via keyboard while keeping the camera controlled by mouse. But I think I'm on the right way to do this (if not, I will post again ;))
Coordinator
Nov 28, 2007 at 3:39 PM
Glad its working ok for you, be interesting to see what you come up with. As someone that is making a game, it'd be cool if you'd post any obstacles you run into along the way, it'll be a great way to gauge what the engine is lacking, or what problems/bugs might need to be fixed.
Nov 29, 2007 at 9:38 AM
Edited Nov 29, 2007 at 10:46 AM
Well, one thing which isn't fitting for a (bigger) game, like we plan it, is the management of memory: on my machine (2 x 1,7Ghz, 1GB RAM, ATI Mobility Radeon X1400 with 256 MB) the engine gives up (framerate 1) at about 700 spheres and even if I'm moving away from these, the memory isn't de-allocated. Should be something like load when you get towards the object(s) and unload when you are far away from them, for better performance.
One thing I'm currently changing: The baseEntity-class got a fTempo-Variable and the move()-methods get a "direction" instead of amount so they calculate the movement depending on forward or backward-direction and the tempo, the entity has. At the moment I'm annoyed with me, because this idea came to my mind after changing the whole input-thing - now I have to change it again sigh But my lectures aren't that interesting so I have something to do ;)
If there are further problems upcoming, I will inform you.

Edit: I also changed the player-model's center again and worked with the radius, so now the cam is focused on the hip.

Edit II: Another thing I realized/need: for performing a step to the right/left (no rotation), I used the MoveX-method, but my model moves in the global x-direction, not in its local x-direction, i.e. if the model is somehow rotated, it may move forward from the model's sight. It may also be the cam, but that wouldn't make sense, would it?
Coordinator
Nov 29, 2007 at 2:25 PM
Edited Nov 29, 2007 at 2:26 PM
All the movement methods for BaseEntity should already be included. Front/Back, and Left/Right already exist.

In BaseEntity you will see this

public void MoveFrontBack(float amount)
{
      Position += Forward * amount;
}
 
public void Strafe(float amount)
{
      Position += RightVector * amount;
}

MoveFrontBack will move the character depending on their speed(tempo) and direction they are facing, and Strafe will move the player left/right (without rotating them) depending on the way they're facing. Amount can be a positive or negative number. For instance, if you give Strafe a negative value your character should strafe to the left, without rotating.
Nov 29, 2007 at 3:10 PM
Allright, didn't know what 'strafe' means, dict.leo.org only translates it with something like 'fire at'. But it is the other way round: negative values move my model to the right and positive to the left. Same thing with MoveFrontBack - negative values move the figure forwards and positive ones backwards - a bit tricky.

The move and strafe methods look now like this:
        /// <summary>
        /// Moves the entity forwards or backwards
        /// Please check that fSpeed of this entity has a value > 0
        /// </summary>
        /// <param name="direction">forward (1) or backward (-1) incl. modifications
        /// (e.g. for slower backwards you choose a value between 0 & -1)</param>
        public void MoveFrontBack(float direction)
        {
            Position += Forward * direction * this.fSpeed;
        }
That way round, if I have more than one controllable entity (maybe more than one player figure), I don't have to re-write my input-settings if one entity is slower than the other one, I just have to adjust the fSpeed-variable of the entity-object.
Coordinator
Nov 29, 2007 at 3:20 PM
Well the function already takes amount as the speed, you would simply pass the entity's speed into the original function.

And direction being a float is very confusing, a direction (in 3D space), must have at least 3 vectors. In fact, 'Forward' is the direction of the player.

Using a direction (Forward), and speed (amount), you should be able to move in ANY direction in 3D space, at ANY speed.

If you have an Xbox360 gamepad you should try using it to control the player, you'll notice I've already got complete movement controls setup. In fact, because ControllableEntity has these controls setup for it, you should be able to use them even with a keyboard if you setup keyboard to send messages to your entity (which you should also now be able to do because I setup a way to associate players with the input class).
Nov 29, 2007 at 3:59 PM

LordIkon wrote:
Well the function already takes amount as the speed, you would simply pass the entity's speed into the original function.

That sure is right, but I currently need the input via keyboard and if I really once have several player figures (there will be, one day, aliens to play which are faster than humans but less intelligent) and if I'm using amount as speed, I have to change the whole thing in input.cs (case Keys.A etc.)


And direction being a float is very confusing, a direction (in 3D space), must have at least 3 vectors. In fact, 'Forward' is the direction of the player.

Using a direction (Forward), and speed (amount), you should be able to move in ANY direction in 3D space, at ANY speed.

That's is in fact a thing I didn't think about. For my team that works fine as I am (currently) the only programmer and made those summary-tags (I love them).


If you have an Xbox360 gamepad you should try using it to control the player, you'll notice I've already got complete movement controls setup. In fact, because ControllableEntity has these controls setup for it, you should be able to use them even with a keyboard if you setup keyboard to send messages to your entity (which you should also now be able to do because I setup a way to associate players with the input class).

I don't have one.
Any ideas for jumping? I'm trying with
protected Vector3 UpVector = QSVector3.Up;
 
[...]
        public void MoveUp()
        {
            if (Position.Z - game.sceneTerrain.GetTerrainHeight(Position.X, Position.Y) < 60)
            {
                Position += UpVector;
            }
        }
Doesn't work properly:
If method is called in the 'keys held in'-section and the you keep the 'jump'-button pressed, the figure stays in the air
If method is called in the 'keys aren't held in'-section, figure jumps only a little bit.
Coordinator
Nov 29, 2007 at 4:06 PM
If you want to have different players controlled through keyboard, each with its own speed, then I would use the function as it is, but do like you did by adding in a speed multiplier.

If you'd like to create a jump I would create a function to add an amount to the player's Z velocity. If you simply change position it will seem odd. Think of it in physics terms, when you jump in real life you don't simply change position, your legs add upward force to your body and that makes you move up.

Try something like this:
public void Jump()
        {
            this.Velocity.Z += jumpForce;
        }

In this case, jumpForce would be a float that all ControllableEntities could have.
Nov 29, 2007 at 5:06 PM
We really should have jump implemeted along with strafe and move forward.


LordIkon wrote:

I setup a way to associate players with the input class


Were is this found? Id like to give it a once over, as I think we should implement a player class, to tie in with the network. If youve already got the beginnings of one (whihc is how it souds), Id like to take a look, to see how I can get the network to interact with it.
Coordinator
Nov 29, 2007 at 5:12 PM
ControllableEntity is essentially the player. If we had things like health, damage, strength, speed, etc, we would probably derive a Player class from ControllableEntity. ControllableEntity is not player because not everything you may control would need to be a player.

If I made a jump function I would likely put it in a Player class, which isn't around just yet. Sounds like it will need to be soon. If that is the case Bot will derive from Player rather than ControllableEntity. Heirarchy is getting big now. For a bot it would be like this:

BaseEntity -> DynamicEntity -> ControllableEntity -> Player -> Bot
Nov 29, 2007 at 5:46 PM
LordIkon could you consider making a post where you outline the difference between the base Entities? How and when you a dev should consider using one over the other?
Coordinator
Nov 29, 2007 at 5:59 PM
Well, the reason I've held off on documentation is because I don't know how the structure will end up after prototype.
Nov 29, 2007 at 6:35 PM
I guess that it would help those currently using the template, but also it might be a good idea to document the thoughts you have been making when we design the new OM, it might prove to be similar, and if we can keep it similar then the transition for existing devs.
Nov 29, 2007 at 7:22 PM
If you were trully doing the hierachy, you missed the start:
Object -> BaseEntity -> DynamicEntity -> ControllableEntity -> Player -> Bot :)

I wouldnt worry about it. It may be big, but no-one should have more than a handfull of bots at once, and a maximum of 32 players (live restriction). Have you considered the differance between local and remote players? A local player could be a derivative of player, handling the network side and input side. This cleans up the Player class quite a bit, as it would not need to be common.
Coordinator
Nov 29, 2007 at 8:02 PM
Edited Nov 29, 2007 at 8:05 PM
Well the way Shaw described the new framework, it sounds like even local framework will be treated like it is networked. This is similar to how some engines work. I know that Torque does this, as well as Unreal3. If you simply treat the message properly it shouldn't matter.

For instance, if you kill a bot in single player, and send a 'killbot' message to the framework, it may call the bot's death sequence, play a death sound, etc. However, if you send the same message in a multiplayer game, when the framework recieves that message it would send it to the server, which would send it to all the other clients, and when the clients' framework recieved the message it would then call the bot's death sequence, play a death sound, etc, on each client's computer. A 'Player' object only needs to be concerned with the messages it is recieving.
Nov 29, 2007 at 8:58 PM
In all honesty, its not something I had considered. I will need a better idea of the kind of messages the network engine will have to handle. I had only realey considered entity sync, with the ability to create and delete them. I was going to make the clients treat remote players as static objects, meaning that it was simpler on their end. Ill reconsider my options, once everyone tells me what they need from the engine, but I still feel my way has merits.

Anyway, surely it still makes sense to seperate Players into local and remote. This minimises on the amount of superfluoues code, reducing memory needs, if only by a little bit. Surely every little helps though?
Coordinator
Nov 29, 2007 at 10:56 PM
Well what kinds of processing goes on for a player right now?

A flexible system won't care, and wouldn't be any less efficient. Take 3D sound for instance.

Lets say there are two players, PlayerRED and PlayerBLUE.

Local situation (RED is human, blue is CPU):
They're standing 10 feet apart, and BLUE fires a shotgun. The sound manager would recieve a message that a sound needs to be played, this message would come from the BLUE bot. The sound manager would then determine positioning from red to blue, determine how to play the sound, and then actually play it.

Networked situation (RED and BLUE are both human, on different machines):
Still standing 10 feet apart, blue fires a shotgun. The sound manager on RED's computer recieves a message from the server that a sound needs to be player, this message still comes from the BLUE player. From here, nothing is different.

It didn't matter whether blue was a bot or player, same messages, only different is messages are sent through server.

Some messages should be sent to server and client. But I still don't see a compelling reason to have networked players, and local players a whole lot different. Obviously there has to be some level of abstraction so the code knows which player is yours, but I don't know if that requires seperate classes.

Sound checks: local and networked
Nov 30, 2007 at 6:39 AM
Also the scanario you are outlining here is FPS. Consider that there are also other types of games available. Strategy games like AOE, C&C, Halo Wars have a different interaction model. My point is that if you make a specific class for the player which is a FPS minded class, please create it in a seperate assembly as this is bacially a game related class not really framework, unless we want to make a FPS specific engine.
Nov 30, 2007 at 11:03 AM
Ok, youre right. I will have it so that the network enigne converts system messages into networked ones and back again at the other end. if I do it right there will be no need to explicitly add conversion rules for each emssage. This should give enough flexabbility.
Coordinator
Nov 30, 2007 at 2:27 PM
mike:
I don't know if you'd even have to convert the messages, I believe the messages themselves would do the job. When a message is sent it would have a type like "LocalOnly", "Networked", "ServerOnly". If you sent a networked message and it was a local game, then the local part would be processed but there would be no networked message sent.

Sturm:
I agree, I will begin separating gametype-specific things into a separate project. This way when the project is removed you're left only with the template.
Nov 30, 2007 at 2:35 PM
I like your suggestion. Ill ask Sturm to add the type flag if he hasnt already. I would still need to convert it into bytes for transmission and vice versa, but the flag would help reduce network traffic.
Nov 30, 2007 at 3:40 PM
Sturm, could you quickly outline the new messaging system, as you envision it? I'm specifically curious about the message hierarchy... will there be one message class, or multiple message classes derived from a common type, or ... ?
Coordinator
Dec 1, 2007 at 1:05 AM
kuschelknaeuel, I should add that 700 spheres which physics calculations on all of them is tough on any computer. Granted physics will eventually be multithreaded and more efficient, I wouldn't expect a great framerate with 700 spheres. Much of it is the polygon count if you're looking at them.

For example, if I have 700 spheres in view my framerate drops to around 7-10, but if I look away from them I get back up to around 40-45.

You cannot really de-allocate the memory for the spheres unless you wanted to store their info on the HD and stream it there once you were at a fairly good distance from them, otherwise you couldn't stream them back in fast enough as they came into view. There will eventually be the ability to unload and load at distances, but not anytime real soon.

I don't see many games that will need hundreds of physics objects.
Dec 1, 2007 at 12:40 PM
There are certainly scenarios for games which will have hundreds of models on screen at the same time, just think N3 and similar games. Of cause these implement various technichs in order to optimize this, but throughout the gameworld there are even more items.

It's not, or at least shouldn't be, a problem having 1000's of ubjects which have to be updated every cycle. The only real performance issue should be rendering. But since only a very limited subset of elements are rendered (and using LOD only a subset of that) having 1000's of object isn't a problem.

By "not a problem" I of cause assume that we have optimized the update to only update what's needed and not lets say suddently desice to load the mesches again. There are a lot of optimizations that can be done, like the fact that the view frustrum doesn't change on each update, which means that if a object hasn't moved it's still within the view frustrum. All of these will help when having many object in the engine.
Dec 1, 2007 at 2:23 PM
For reference, a game I made for a class project last Winter maxed out (physics-wise) around 400-500 spheres in the scene on Xbox, and 700-800 spheres on Windows (P4 3.0GHz, single-threaded). This is with no spatial culling (all objects are viewable at all times) and no partitioning of the physics simulator (every frame checked every sphere against every other sphere). With a much better approach, I don't see a problem getting to 700 spheres on Xbox, and much more on Windows. If you start generalizing the meshes though, things will be many times slower.
Dec 1, 2007 at 3:00 PM
Theres no need to do it now, but we need to take this into account when designing the new enginge. We dont want a mamoth optimization task later on. How come the PC got twice that of the Xbox? I thought it was a weaker processor in terms of GHz but, I was under the impression it was specially designed to be faster at games than a standard "general" processor.
Dec 1, 2007 at 6:06 PM
Edited Dec 1, 2007 at 6:09 PM
There are a lot of factors that play into it, but suffice it to say that the Xbox CLR is really not all that great at what it does. The PowerPC processor in the Xbox is a good processor, but the Compact Framework CLR just isn't able to take advantage of it at this time. The processor is actually clocked higher than most multi-core desktop processors at 3.2 GHz per core, and is able to execute 6 hardware threads in parallel, but its a RISC processor while Intel/AMD desktop processors (Core 2 Duo, Pentium 4, Athlon, etc.) are CISC, so the clock speed numbers can't really be compared. Even if they were both RISC or CISC, you still wouldn't be able to compare them. You can't even compare clock speeds on Athlon vs. Pentium. They're different processors with different architectures, the Pentium and Athlon just happen to have the same instruction set.

Then you have the issue of instruction order, modern desktop processors being speculative out-of-order processors while as far as I know the Xenon processor is an in-order processor, so is more susceptible to instruction scheduling issues (something you cannot resolve in .NET, you're completely at the mercy of the CLR here).

For intense calculations with C#/XNA, you'll usually see roughly an order of magnitude difference between Windows performance on a good processor and the Xenon processor. It's one of those sad, disappointing, but true facts of working with XNA. I have to mention (though plenty on the XNA boards like to dispute this) that this is not completely a result of the Xbox hardware. Based on the calculations you're doing, there are of course performance differences between Intel/AMD hardware and the Xenon processor, but a large chunk of the performance lost in the Xbox environment is in the CLR. It's still immature and is a whole league behind native PowerPC compilers.