public CollDetectInfo(CollisionSkin skin0, CollisionSkin skin1, int indexPrim0, int indexPrim1)
 {
     this.IndexPrim0 = indexPrim0;
     this.IndexPrim1 = indexPrim1;
     this.Skin0 = skin0;
     this.Skin1 = skin1;
 }
        public override void AddCollisionSkin(CollisionSkin skin)
        {
            if (skins.Contains(skin))
                System.Diagnostics.Debug.WriteLine("Warning: tried to add skin to CollisionSystemBrute but it's already registered");
            else
                skins.Add(skin);

            skin.CollisionSystem = this;
        }
        /// <summary>
        /// Loads a physics world object.
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="skin"></param>
        /// <param name="body"></param>
        /// <param name="massProperties"></param>
        /// <returns></returns>
        public static bool Load(string filePath, out CollisionSkin skin, out Body body, out PrimitiveProperties primitiveProperties, out MassProperties massProperties)
        {
            skin = null;
            body = null;
            primitiveProperties = new PrimitiveProperties(PrimitiveProperties.MassDistributionEnum.Solid, PrimitiveProperties.MassTypeEnum.Mass, 0.001f);
            massProperties = MassProperties.Zero;

            if (File.Exists(filePath))
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(PhysicsObjectData));
                TextReader textReader = new StreamReader(filePath);

                PhysicsObjectData data = (PhysicsObjectData)xmlSerializer.Deserialize(textReader);
                textReader.Close();

                if (data != null && data.MaterialPrimitivePairs != null && data.MaterialPrimitivePairs.Count > 0)
                {
                    body = new JigLibSDX.Physics.Body();
                    skin = new JigLibSDX.Collision.CollisionSkin(body);
                    body.CollisionSkin = skin;

                    primitiveProperties = data.PrimitiveProperties;

                    for (int i = 0; i < data.MaterialPrimitivePairs.Count; i++)
                    {
                        if (data.MaterialPrimitivePairs[i].MaterialID == (int)MaterialTable.MaterialID.UserDefined)
                        {
                            skin.AddPrimitive(data.MaterialPrimitivePairs[i].Primitive, data.MaterialPrimitivePairs[i].MaterialID);
                        }
                        else
                        {
                            skin.AddPrimitive(data.MaterialPrimitivePairs[i].Primitive, data.MaterialPrimitivePairs[i].MaterialProperties);
                        }
                    }

                    massProperties = data.MassProperties;

                    body.BodyInertia = massProperties.InertiaTensorCoM;
                    body.Mass = massProperties.Mass;

                    body.MoveTo(Vector3.Zero, Matrix.Identity);
                    skin.ApplyLocalTransform(new Transform(-massProperties.CenterOfMass, Matrix.Identity));

                    body.EnableBody();
                }

                return true;
            }
            else
            {
                MessageBox.Show("File \"" + filePath + "\" not found.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }
        public void CalcGridForSkin(out int i, out int j, out int k, out float fi,
            out float fj, out float fk, CollisionSkin skin)
        {
            Vector3 sides = skin.WorldBoundingBox.Maximum - skin.WorldBoundingBox.Minimum;
            if ((sides.X > dx) || (sides.Y > dy) || (sides.Z > dz))
            {
                System.Diagnostics.Debug.WriteLine("CollisionSkin too big for gridding system - putting it into overflow list.");

                i = j = k = -1;
                fi = fj = fk = 0.0f;
                return;
            }

            Vector3 min = skin.WorldBoundingBox.Minimum;

            min.X = JiggleMath.Wrap(min.X, 0.0f, sizeX);
            min.Y = JiggleMath.Wrap(min.Y, 0.0f, sizeY);
            min.Z = JiggleMath.Wrap(min.Z, 0.0f, sizeZ);

            fi = min.X / dx;
            fj = min.Y / dy;
            fk = min.Z / dz;

            i = (int)fi;
            j = (int)fj;
            k = (int)fk;

            if (i < 0) { i = 0; fi = 0.0f; }
            else if (i >= (int)nx) { i = 0; fi = 0.0f; }
            else fi -= (float)i;

            if (j < 0) { j = 0; fj = 0.0f; }
            else if (j >= (int)ny) { j = 0; fj = 0.0f; }
            else fj -= (float)j;

            if (k < 0) { k = 0; fk = 0.0f; }
            else if (k >= (int)nz) { k = 0; fk = 0.0f; }
            else fk -= (float)k;
        }
        public void CalculateMassProperties()
        {
            CollisionSkin skin = new CollisionSkin();

            #region Mass Variables
            Vector3 centerOfMass;
            float mass;
            Matrix inertiaTensor;
            Matrix inertiaTensorCoM;
            #endregion

            for (int i = 0; i < MaterialPrimitivePairs.Count; i++)
            {
                if (this.MaterialPrimitivePairs[i].MaterialID == (int)MaterialTable.MaterialID.UserDefined)
                {
                    skin.AddPrimitive(this.MaterialPrimitivePairs[i].Primitive, this.MaterialPrimitivePairs[i].MaterialID);
                }
                else
                {
                    skin.AddPrimitive(this.MaterialPrimitivePairs[i].Primitive, this.MaterialPrimitivePairs[i].MaterialProperties);
                }
            }

            skin.GetMassProperties(PrimitiveProperties, out mass, out centerOfMass, out inertiaTensor, out inertiaTensorCoM);
            skin.RemoveAllPrimitives();

            _massProperties.Mass = mass;
            _massProperties.CenterOfMass = centerOfMass;
            _massProperties.InertiaTensor = inertiaTensor;
            _massProperties.InertiaTensorCoM = inertiaTensorCoM;
        }
 /// <summary>
 /// Don't remove skins whilst doing detection!
 /// </summary>
 /// <param name="collisionSkin"></param>
 public abstract bool RemoveCollisionSkin(CollisionSkin collisionSkin);
 /// <summary>
 /// Decides whether a CollisionSkin should be considered while
 /// doing SegmentIntersecting tests or not.
 /// </summary>
 /// <param name="skin0">Skin to be considered.</param>
 /// <returns>True if the skin should be considered otherwise false.</returns>
 public abstract bool ConsiderSkin(CollisionSkin skin0);
 public WheelPred(CollisionSkin carSkin)
 {
     mSkin = carSkin;
 }
        public override bool RemoveCollisionSkin(CollisionSkin skin)
        {
            GridEntry entry = (GridEntry)skin.ExternalData;

            if (entry != null)
            {
                entry.Skin = null;
                freeGrids.Push(entry);
                GridEntry.RemoveGridEntry(entry);
                skin.ExternalData = null;
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("Warning - skin being deleted without a grid entry");
            }

            if (!skins.Contains(skin)) return false;
            skins.Remove(skin);
            return true;
        }
        public override bool SegmentIntersect(out float fracOut,out CollisionSkin skinOut,out Vector3 posOut,out Vector3 normalOut, Segment seg, CollisionSkinPredicate1 collisionPredicate)
        {
            int numSkins = skins.Count;
            BoundingBox segBox = BoundingBoxHelper.InitialBox;
            BoundingBoxHelper.AddSegment(seg, ref segBox);

            //initialise the outputs
            fracOut = float.MaxValue;
            skinOut = null;
            posOut = normalOut = Vector3.Zero;

            // working vars
            float frac;
            Vector3 pos;
            Vector3 normal;

            for (int iskin = 0; iskin < numSkins; ++iskin)
            {
                CollisionSkin skin = skins[iskin];
                if ((collisionPredicate == null) ||
                    collisionPredicate.ConsiderSkin(skin))
                {
                    // basic bbox test
                    if (BoundingBoxHelper.OverlapTest(ref skin.WorldBoundingBox, ref segBox))
                    {
                        if (skin.SegmentIntersect(out frac, out pos, out normal, seg))
                        {
                            if (frac < fracOut)
                            {
                                posOut = pos;
                                normalOut = normal;
                                skinOut = skin;
                                fracOut = frac;
                            }
                        }

                    }
                }
            }

            if (fracOut > 1.0f) return false;
            fracOut = MathHelper.Clamp(fracOut, 0.0f, 1.0f);
            return true;
        }
        private static bool CheckCollidables(CollisionSkin skin0,
            CollisionSkin skin1)
        {
            List<CollisionSkin> nonColl0 = skin0.NonCollidables;
            List<CollisionSkin> nonColl1 = skin1.NonCollidables;

            //most common case
            if (nonColl0.Count == 0 && nonColl1.Count == 0)
                return true;

            for (int i0 = nonColl0.Count; i0-- != 0; )
            {
                if (nonColl0[i0] == skin1)
                    return false;
            }

            for (int i1 = nonColl1.Count; i1-- != 0; )
            {
                if (nonColl1[i1] == skin0)
                    return false;
            }

            return true;
        }
 public GridEntry(CollisionSkin skin)
 {
     this.Skin = skin;
     this.Previous = this.Next = null;
 }
 public override bool RemoveCollisionSkin(CollisionSkin skin)
 {
     if (!skins.Contains(skin)) return false;
     skins.Remove(skin);
     return true;
 }
        private void GetListsToCheck(List<GridEntry> entries, CollisionSkin skin)
        {
            entries.Clear();

            GridEntry entry = (GridEntry)skin.ExternalData;
            if (entry == null)
            {
                System.Diagnostics.Debug.WriteLine("Warning skin has grid entry null!");
                //TRACE("Warning = skin %s has grid entry 0!\n", skin);
                return;
            }

            // todo - work back from the mGridIndex rather than calculating it again...
            int i, j, k;
            float fi, fj, fk;
            CalcGridForSkin(out i, out j, out k, out fi, out fj, out fk, skin);

            if (i == -1)
            {
                // oh dear - add everything
                for (i = 0; i < gridEntries.Count; ++i)
                {
                    if (gridEntries[i].Next != null)
                    {
                        entries.Add(gridEntries[i]);
                    }
                }
                //entries = gridEntries;
                entries.Add(overflowEntries);
                return;
            }

            // always add the overflow
            entries.Add(overflowEntries);

            Vector3 delta = skin.WorldBoundingBox.Maximum - skin.WorldBoundingBox.Minimum;
            int maxI = 1, maxJ = 1, maxK = 1;
            if (fi + (delta.X / dx) < 1.0f)
                maxI = 0;
            if (fj + (delta.Y / dy) < 1.0f)
                maxJ = 0;
            if (fk + (delta.Z / dz) < 1.0f)
                maxK = 0;

            // now add the contents of all 18 grid boxes - their contents may extend beyond the bounds
            for (int di = -1; di <= maxI; ++di)
            {
                for (int dj = -1; dj <= maxJ; ++dj)
                {
                    for (int dk = -1; dk <= maxK; ++dk)
                    {
                        int thisIndex = CalcIndex(nx + i + di, ny + j + dj, nz + k + dk);
                        GridEntry start = gridEntries[thisIndex];
                        if (start.Next != null)
                            entries.Add(start);
                    }
                }
            }
        }
 private int CalcGridIndexForSkin(CollisionSkin skin)
 {
     int i, j, k;
     CalcGridForSkin(out i, out j, out k, skin);
     if (i == -1) return -1;
     return CalcIndex(i, j, k);
 }
        private void CalcGridForSkin(out int i, out int j, out int k, CollisionSkin skin)
        {
            Vector3 sides = skin.WorldBoundingBox.Maximum - skin.WorldBoundingBox.Minimum;
            if ((sides.X > dx) || (sides.Y > dy) || (sides.Z > dz))
            {
                System.Diagnostics.Debug.WriteLine("CollisionSkin too big for gridding system - putting it into overflow list.");
                i = j = k = -1;
                return;
            }

            Vector3 min = skin.WorldBoundingBox.Minimum;

            min.X = JiggleMath.Wrap(min.X, 0.0f, sizeX);
            min.Y = JiggleMath.Wrap(min.Y, 0.0f, sizeY);
            min.Z = JiggleMath.Wrap(min.Z, 0.0f, sizeZ);

            i = (int)(min.X / dx) % nx;
            j = (int)(min.Y / dy) % ny;
            k = (int)(min.Z / dz) % nz;
        }
        /// <summary>
        /// Saves all needed information to recreate an physics world object.
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="overwrite"></param>
        /// <param name="skin"></param>
        /// <param name="primitiveProperties"></param>
        /// <param name="massProperties">"Null" will cause re-calculation of the mass properties. If you are saving loaded data: Re-calc might cause data loss!</param>
        /// <returns></returns>
        public static bool Save(string filePath, bool overwrite, CollisionSkin skin, PrimitiveProperties primitiveProperties, MassProperties? massProperties)
        {
            if (!File.Exists(filePath) || (File.Exists(filePath) && overwrite))
            {
                PhysicsObjectData data = new PhysicsObjectData();
                data.SetPrimitiveProperties(primitiveProperties);

                for (int i = 0; i < skin.NumPrimitives; i++)
                {
                    data.Add(skin.GetPrimitiveLocal(i), skin.GetMaterialID(i), skin.GetMaterialProperties(i));
                }

                if (massProperties.HasValue)
                {
                    data.MassProperties = massProperties.Value;
                }
                else
                {
                    data.CalculateMassProperties();
                }

                XmlSerializer xmlSerializer = new XmlSerializer(typeof(PhysicsObjectData));
                TextWriter textWriter = new StreamWriter(filePath);

                xmlSerializer.Serialize(textWriter, data);
                textWriter.Close();

                return true;
            }
            else
            {
                MessageBox.Show("Can't write to file \"" + filePath + "\".", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }
        public Body()
        {
            this.ID = idCounter++;

            bodiesToBeActivatedOnMovement = new List<Body>();
            bodyEnabled = false;
            collSkin = null;

            this.Mass = 1.0f;
            this.BodyInertia = Matrix.Identity;

            transform = new Transform();
            transform.Position = Vector3.Zero;
            transform.Orientation = Matrix.Identity;

            immovable = false;
            origImmovable = false;
            doShockProcessing = true;

            force = Vector3.Zero;
            torque = Vector3.Zero;

            velChanged = true;

            activity = Activity.Active;
            inactiveTime = 0.0f;
            deactivationTime = 1.0f;
            SetActivityThreshold(0.5f, 20.0f);
            allowFreezing = true;
            lastPositionForDeactivation = transform.Position;
            lastOrientationForDeactivation = transform.Orientation;

            CopyCurrentStateToOld();
        }
 public bool OnCollisionEvent(CollisionSkin skin0, CollisionSkin skin1)
 {
     if (callbackFn != null)
     {
         return callbackFn(skin0, skin1);
     }
     else
     {
         return true;
     }
 }
 /// <summary>
 /// Don't add skins whilst doing detection!
 /// </summary>
 /// <param name="collisionSkin"></param>
 public abstract void AddCollisionSkin(CollisionSkin collisionSkin);
 public override bool ConsiderSkin(CollisionSkin skin)
 {
     return (skin.ID != mSkin.ID);
 }
        public override void CollisionSkinMoved(CollisionSkin skin)
        {
            GridEntry entry = (GridEntry)skin.ExternalData;
            if (entry == null)
            {
                System.Diagnostics.Debug.WriteLine("Warning skin has grid entry null!");
                return;
            }

            int gridIndex = CalcGridIndexForSkin(skin);

            // see if it's moved grid
            if (gridIndex == entry.GridIndex)
                return;

            GridEntry start;
            if (gridIndex >= 0)
                start = gridEntries[gridIndex];
            else
                start = overflowEntries;

            GridEntry.RemoveGridEntry(entry);
            GridEntry.InsertGridEntryAfter(entry, start);
        }
        private void SavePhysicsObjectFile(ref Project project)
        {
            if (project != null && project.CollisionPrimitiveInfos != null)
            {
                if (project.CollisionPrimitiveInfos.Count > 0)
                {
                    DialogResult dialogResult = DialogResult.None;
                    bool save = false;

                    try
                    {
                        SaveFileDialog saveFileDialog = new SaveFileDialog();
                        saveFileDialog.Filter = "JigLibSDX Physics Object (*.jlpo)|*.jlpo";

                        dialogResult = saveFileDialog.ShowDialog(this);

                        switch (dialogResult)
                        {
                            case DialogResult.OK:
                                save = true;
                                break;

                            default:
                                save = false;
                                break;
                        }

                        if (save)
                        {
                            JLC.CollisionSkin skin = new JLC.CollisionSkin();

                            JLG.Box box;
                            JLG.Sphere sphere;
                            JLG.Capsule capsule;

                            JLG.Primitive primitive;

                            Quaternion orientation;
                            Vector3 scale;
                            Vector3 translation;

                            Vector3 position;

                            for (int i = 0; i < project.CollisionPrimitiveInfos.Count; i++)
                            {
                                switch ((JLG.PrimitiveType)project.CollisionPrimitiveInfos[i].Primitive.Type)
                                {
                                    case JLG.PrimitiveType.Box:
                                        box = (JLG.Box)project.CollisionPrimitiveInfos[i].Primitive.Clone();

                                        box.Orientation.Decompose(out scale, out orientation, out translation);
                                        box.Position += Vector3.TransformCoordinate(box.SideLengths * -0.5f, Matrix.RotationQuaternion(orientation));

                                        skin.AddPrimitive(box, project.CollisionPrimitiveInfos[i].MaterialProperties);
                                        break;

                                    case JLG.PrimitiveType.Sphere:
                                        skin.AddPrimitive(project.CollisionPrimitiveInfos[i].Primitive.Clone(), project.CollisionPrimitiveInfos[i].MaterialProperties);
                                        break;

                                    case JLG.PrimitiveType.Capsule:
                                        capsule = (JLG.Capsule)project.CollisionPrimitiveInfos[i].Primitive.Clone();

                                        capsule.Orientation.Decompose(out scale, out orientation, out translation);
                                        capsule.Position += Vector3.TransformCoordinate(new Vector3(0f, 0f, capsule.Length * -0.5f), Matrix.RotationQuaternion(orientation));

                                        skin.AddPrimitive(capsule, project.CollisionPrimitiveInfos[i].MaterialProperties);
                                        break;
                                }
                            }

                            JLU.PhysicsObjectFile.Save(saveFileDialog.FileName, true, skin, project.PrimitiveProperties, null);
                        }

                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(this, "An error occured:\n" + e.Message, "Error", MessageBoxButtons.OK);
                    }
                }
                else
                {
                    MessageBox.Show(this, "You need at least one primitive.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            else
            {
                MessageBox.Show(this, "Create a new project first.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
 public override void CollisionSkinMoved(CollisionSkin skin)
 {
     // not needed
 }
 /// <summary>
 /// Whenever a skin changes position it will call this to let us
 /// update our internal state.
 /// </summary>
 /// <param name="skin"></param>
 public abstract void CollisionSkinMoved(CollisionSkin skin);
 public void Dispose()
 {
     _primitive = null;
     _body = null;
     _skin = null;
 }
 /// <summary>
 /// Intersect a segment with the world. If non-zero the predicate
 /// allows certain skins to be excluded
 /// </summary>
 /// <param name="seg"></param>
 /// <param name="collisionPredicate"></param>
 /// <returns></returns>
 public abstract bool SegmentIntersect(out float fracOut, out CollisionSkin skinOut, out Vector3 posOut, out Vector3 normalOut,
     Segment seg, CollisionSkinPredicate1 collisionPredicate);
        private void Initialize(Primitive primitive, MaterialProperties materialProperties, PrimitiveProperties primitiveProperties, bool enableBody)
        {
            float mass;
            Vector3 centerOfMass;
            Matrix inertiaTensor;
            Matrix inertiaTensorCoM;

            // Set variables ...
            _primitive = primitive;
            _primitiveProperties = primitiveProperties;
            _materialProperties = materialProperties;

            // Create and link Body and CollisionSkin.
            _body = new Body();
            _skin = new CollisionSkin(_body);
            _body.CollisionSkin = _skin;

            // Add primitive to CollisionSkin.
            _skin.AddPrimitive(primitive, materialProperties);

            // Set body properties.
            _skin.GetMassProperties(primitiveProperties, out mass, out centerOfMass, out inertiaTensor, out inertiaTensorCoM);

            _body.BodyInertia = inertiaTensorCoM;
            _body.Mass = mass;

            // Sync CollisionSkin and Body.
            _body.MoveTo(Vector3.Zero, Matrix.Identity);
            _skin.ApplyLocalTransform(new Transform(-centerOfMass, Matrix.Identity));

            // Enable Body.
            if (enableBody)
            {
                _body.EnableBody();
            }
            else
            {
                _body.DisableBody();
            }
        }
 /// <summary>
 /// Decides whether a pair of skins should be considered for collision
 /// or not.
 /// </summary>
 /// <param name="skin0"></param>
 /// <param name="skin1"></param>
 /// <returns>True if the pair should be considered otherwise false.</returns>
 public abstract bool ConsiderSkinPair(CollisionSkin skin0, CollisionSkin skin1);
        public override void AddCollisionSkin(CollisionSkin skin)
        {
            if (skins.Contains(skin))
                System.Diagnostics.Debug.WriteLine("Warning: tried to add skin to CollisionSkinGrid but it's already registered");
            else
                skins.Add(skin);

            skin.CollisionSystem = this;

            if (freeGrids.Count == 0)
            {
                freeGrids.Push(new GridEntry());
            }

            // also do the grid stuff - for now put it on the overflow list
            GridEntry entry = freeGrids.Pop();
            skin.ExternalData = entry;
            entry.Skin = skin;
            // add entry to the start of the list
            GridEntry.InsertGridEntryAfter(entry, overflowEntries);
            CollisionSkinMoved(skin);
        }