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); }