Page 1 of 1

Obtaining collision information in the latest BETA.

Posted: Thu Mar 03, 2011 11:07 am
by Spankenstein
I'm probably being a bit slow but I've created my method for handling the initial collision detection and come unstuck.

Code: Select all

private void Events_InitialCollisionDetected(EntityCollisionInformation info, CollisionEntry entry, INarrowPhasePair pair)
{

}
How can I obtain the contact details (normal, point of collision, t0, etc.) from this method for each pair in the collision?

Also, is there a 'CharacterController' class for the v0.15 BETA to demonstrate some of these methods?

Thank you.

Re: Obtaining collision information in the latest BETA.

Posted: Thu Mar 03, 2011 8:51 pm
by Norbo
How can I obtain the contact details (normal, point of collision, t0, etc.) from this method for each pair in the collision?
The INarrowPhasePair pair object is what would contain that information, if it is in fact a pair that contains contacts. Not all INarrowPhasePairs have to generate contacts, but all CollisionInformationPairHandlers (which implements INarrowPhasePair) do. Once the object is known to be a CollisionInformationPairHandler, you can use its GetContacts method.
Also, is there a 'CharacterController' class for the v0.15 BETA to demonstrate some of these methods?
I have updated the SimpleCharacterController to use v0.15.0, but neither character controller uses contact data. The SimpleCharacterController uses raycasting and the normal CharacterController uses convex sweeps. I've attached the current version of the SimpleCharacterController.

Re: Obtaining collision information in the latest BETA.

Posted: Thu Mar 03, 2011 9:44 pm
by Spankenstein
Correct me if I'm wrong but I'm now getting the contacts as follows:

Code: Select all

            CollisionInformationPairHandler p = pair as CollisionInformationPairHandler;

            List<Contact> contacts = new List<Contact>();
            p.GetContacts(contacts);
Why do I have to create a contact list for the contacts? I know I could pool the lists but can they not be automatically stored in an array and accessed that way?

Are the contacts ordered by time of collision? There's no 't0' property to differentiate between them otherwise.

Thank you for uploading the SimpleCharacterController, I'll be playing around with it tonight.

Re: Obtaining collision information in the latest BETA.

Posted: Thu Mar 03, 2011 10:10 pm
by Norbo
Why do I have to create a contact list for the contacts? I know I could pool the lists but can they not be automatically stored in an array and accessed that way?
The internal representation depends on the type of pair. If you wanted, you could do some annoying work to identify the specific type, and then access that type's unique representation without having to deal with the extra list. The purpose of the method is to allow you to ignore how the contacts are managed internally, so that the fact that it may have to traverse a hierarchy or collect from multiple manifolds is transparent.

One thing I've toyed with is creating a semi-enumerator that would allow you to go through the list of contacts without explicitly consolidating them, either using IEnumerable or just providing interpreted indexing. This might make it in eventually.
Are the contacts ordered by time of collision? There's no 't0' property to differentiate between them otherwise.
Contacts have no time of collision; just position, normal, depth, and ID. The ID is sometimes used to determine the feature from which the contact originated internally.

A CollisionInformationPairHandler (which owns the contact) does have a 'TimeOfImpact' property, but I don't think it is what you are looking for. TimeOfImpact is the amount of a frame's motion that can be completed before a CCD-blocked collision. If neither object in a pair is continuous, then the TimeOfImpact will just be 1.

If you'd like to know the age of a collision, you'll have to do it using events.

Re: Obtaining collision information in the latest BETA.

Posted: Sun Mar 06, 2011 12:21 pm
by Spankenstein
I had a chance to play with the CharacterController and the character constantly rises when Jump is called. Changing the mass of the character has no effect either:

Code: Select all

    public class CharacterControllerInput
    {
        private Camera camera;                              // Current camera being controlled
        //private CharacterController characterController;    // Physics representation of the character
        private SimpleCharacterController characterController;

        /// <summary>
        /// Current offset from the position of the character to the 'eyes'
        /// </summary>
        public Vector3 CameraOffset = new Vector3();

        /// <summary>
        /// Whether or not to use the character controller's input
        /// </summary>
        public bool IsActive = true;

        private Game1 game;

        /// <summary>
        /// Constructs the character and internal physics character controller.
        /// </summary>
        /// <param name="owningSpace">Space to add the character to.</param>
        /// <param name="cameraToUse">Camera to attach to the character.</param>
        public CharacterControllerInput(Game1 game, Camera cameraToUse)
        {
            this.game = game;

            camera = cameraToUse;
            //characterController = new CharacterController(Vector3.Zero, 3, 1, 20f, 1.4f, .01f, .04f);
            characterController = new SimpleCharacterController(Vector3.Zero, 3, 1, 1.4f, 100f);

            game.Space.Add(characterController);

            Deactivate();
        }

        /// <summary>
        /// Gives the character control over the camera and movement input.
        /// </summary>
        public void Activate()
        {
            if (!IsActive)
            {
                IsActive = true;
                camera.IsIgnoreInput = true;
                characterController.Activate();
                //characterController.Body.TeleportTo(camera.Position);
                characterController.Body.Position = camera.Position;
            }
        }

        /// <summary>
        /// Returns input control to the camera.
        /// </summary>
        public void Deactivate()
        {
            if (IsActive)
            {
                IsActive = false;
                camera.IsIgnoreInput = false;
                characterController.Deactivate();
            }
        }

        /// <summary>
        /// Handles the input and movement of the character.
        /// </summary>
        /// <param name="dt">Time since last frame in simulation seconds.</param>
        /// <param name="previousKeyboardInput">The last frame's keyboard state.</param>
        /// <param name="keyboardInput">The current frame's keyboard state.</param>
        /// <param name="previousGamePadInput">The last frame's gamepad state.</param>
        /// <param name="gamePadInput">The current frame's keyboard state.</param>
        public void Update(GameTime gameTime)
        {
            if (IsActive)
            {
                float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;

                // Note that the character controller's update method is not called here; this is because it is handled within its owning space.
                // This method's job is simply to tell the character to move around based on the camera and input.

                // Puts the camera at eye level
                //camera.Position = characterController.Body.CenterPosition + CameraOffset;
                camera.Position = characterController.Body.Position + CameraOffset;
                Vector2 totalMovement = new Vector2();

                Vector3 forward = camera.Forward;
                forward.Y = 0;
                forward.Normalize();
                Vector3 right = camera.Right;

                totalMovement += game.HID.LeftY(PlayerIndex.One) * new Vector2(forward.X, forward.Z);
                totalMovement += game.HID.LeftX(PlayerIndex.One) * new Vector2(right.X, right.Z);
                characterController.MovementDirection = totalMovement;

                // Jumping
                if (game.HID.IsButtonHit(PlayerIndex.One, Buttons.A))
                {
                    characterController.Jump();
                }

                Vector3 movementDir;

                //Collect the movement impulses.
                if (game.HID.IsKeyDown(PlayerIndex.One, Keys.W))
                {
                    movementDir = camera.Forward;
                    totalMovement += Vector2.Normalize(new Vector2(movementDir.X, movementDir.Z));
                }
                if (game.HID.IsKeyDown(PlayerIndex.One, Keys.S))
                {
                    movementDir = -camera.Forward;
                    totalMovement += Vector2.Normalize(new Vector2(movementDir.X, movementDir.Z));
                }
                if (game.HID.IsKeyDown(PlayerIndex.One, Keys.A))
                {
                    movementDir = -camera.Right;
                    totalMovement += Vector2.Normalize(new Vector2(movementDir.X, movementDir.Z));
                }
                if (game.HID.IsKeyDown(PlayerIndex.One, Keys.D))
                {
                    movementDir = camera.Right;
                    totalMovement += Vector2.Normalize(new Vector2(movementDir.X, movementDir.Z));
                }
                if (totalMovement.X == 0 & totalMovement.Y == 0)
                    characterController.MovementDirection = totalMovement;
                else
                    characterController.MovementDirection = Vector2.Normalize(totalMovement);

                // Jumping
                if (game.HID.IsMouseButtonHit(MouseButtons.Right))
                {
                    characterController.Jump();
                }

                // Shooting
                if (game.HID.IsMouseButtonHit(MouseButtons.Left))
                {
                    //characterController.Jump();
                }
            }
        }

        /// <summary>
        /// Camera to use for input
        /// </summary>
        public Camera Camera
        {
            get { return camera; }
            set
            {
                camera.IsIgnoreInput = false;
                camera = value;
            }
        }

Re: Obtaining collision information in the latest BETA.

Posted: Sun Mar 06, 2011 9:53 pm
by Norbo
I remember seeing a similar bug caused by the CollisionRules of the collisionPairCollector and the character body being such that they still generated a pair, though I thought I fixed this bug before I posted the character up here. Make sure the SimpleCharacterController constructor has this in it:

Code: Select all

            CollisionRules.AddRule(collisionPairCollector, Body, CollisionRule.NoBroadPhase);//Prevents the creation of any collision pairs between the body and the collector.
Also make sure the body isn't later replaced with some other entity. If it is replaced, the collision rules would need to be changed too.

I've attached the latest versions of the SimpleCharacterController and SimpleCharacterControllerInput just in case I forgot something.

Re: Obtaining collision information in the latest BETA.

Posted: Sun Mar 06, 2011 10:55 pm
by Spankenstein
Thank you Norbo. This is much appreciated. :)