/// <summary> /// Register a static scene element for getting hit. /// </summary> /// <param name="owner"></param> public static void RegisterBlocker(GameActor owner) { CollisionPrimitive prim = owner.SRO.CollisionPrim(owner); if (prim != null) { Sys.Register(prim); } else { // We're looking for collision prims here but haven't found any. // What should happen here? } }
private void AddChildClone(GameActor owner, CollisionPrimitive src) { CollisionPrimitive child = src.Clone(owner); if (children.Count > 0) { /// The world sphere for a primitive with no owner is /// the sphere when the root is at the origin. That is, /// the local sphere with any bone transforms folded in. /// That is our local space. LocalSphere = UnionBounds(LocalSphere, src.WorldSphere); } else { LocalSphere = src.WorldSphere; } children.Add(child); }
private void Register(CollisionPrimitive prim) { things.Add(prim); }
/// <summary> /// Start, end and radii are passed in from a mover. This method tests /// this mover's swept ellipsoid against all the non-moving things as /// well as all the other movers which appear after it in the list. /// The "first" param is the index of the next item in the list. /// /// The listAll param seems to determine whether we just keep the nearest hit /// or keep them all. It appears that listAll=false is used for physics collision /// testing while listAll=true is used for WHEN Bumped testing. But, of course, /// this is just a guess on my part since it's not documented. Argh. /// </summary> /// <param name="startPos0">start position of swept sphere</param> /// <param name="endPos0">end position of swept sphere</param> /// <param name="radii0">Radii of swept ellipsoid.</param> /// <param name="first">This is the index of the first mover to check for collisions with. Start, end, and radii come from the previous mover. TODO (****) Change numbering so this is more clear.</param> /// <param name="listAll">When true, all hits are listed. When false, only the nearest hit is listed.</param> /// <param name="hits"></param> /// <returns></returns> private bool CollisionCheck(Vector3 startPos0, Vector3 endPos0, Vector3 radii0, int first, bool listAll, List <HitInfo> hits) { /// These are structs, no real allocation done here. CollInfo curCollPrim = new CollInfo(); curCollPrim.DistSq = Single.MaxValue; CollInfo best = new CollInfo(); best.DistSq = Single.MaxValue; bool hit = false; // Test the current swept ellipsoid against all the non-moving things. List <CollisionPrimitive> relevants = things; for (int ithing = 0; ithing < relevants.Count; ++ithing) { CollisionPrimitive thing = relevants[ithing]; if (thing.Owner.Ignored) { continue; } // Note we used the Z part of the radii. So, on squashed movers we // might get some intersection. // TODO (****) Actually figure out how to test a swept ellipsoid against // the Primitive based collision shapes. if (thing.Collide(startPos0, endPos0, radii0.Z, ref curCollPrim)) { if (listAll) { HitInfo hitScratch = MakeHitScratch(curCollPrim, radii0.X); hits.Add(hitScratch); curCollPrim.DistSq = Single.MaxValue; } else if (curCollPrim.DistSq <= best.DistSq) { hit = true; best = curCollPrim; endPos0 = best.Center; if (best.Touching) { HitInfo hitScratch = MakeHitScratch(best, radii0.X); hits.Add(hitScratch); } } } } // Test the current mover against the remaining movers in the list. // Note that in the case of hit testing blips this index may be -1. int curMoverIndex = first - 1; // If listAll is true, then we're testing for bump so test the full // list since we have to worry about TouchCushions. if (listAll) { first = 0; } for (int second = first; second < movers.Count; ++second) { Mover sphere = movers[second]; // Don't test against self. if (second == curMoverIndex) { continue; } if (sphere.Owner.Ignored) { continue; } // Don't collide missiles with their launcher. Note that this assumes // that the launcher is always in the list _ahead_ of the missile. MissileChassis mc = movers[second].Owner.Chassis as MissileChassis; if (mc != null && curMoverIndex >= 0 && mc.Launcher == movers[curMoverIndex].Owner) { continue; } Vector3 radii1 = sphere.Radius * sphere.Owner.SquashScale; Vector3 hitContactPosition = Vector3.Zero; Vector3 hitNormal = Vector3.UnitZ; float hitT = -1; bool hitTest = SweptPrims.SweptEllipsoidSweptEllipsoid(startPos0, endPos0, radii0, sphere.Center, sphere.Center + sphere.Delta, sphere.Radius * sphere.Owner.SquashScale, ref hitContactPosition, ref hitNormal, ref hitT); if (hitTest) { Vector3 posAtCollision = MyMath.Lerp(startPos0, endPos0, hitT); // Already touching? if (hitT <= 0) { sphere.SetCollPrimTouching(startPos0, posAtCollision, hitContactPosition, -hitNormal, sphere.Center + hitT * sphere.Delta, ref curCollPrim); } else { sphere.SetCollPrim(startPos0, posAtCollision, hitContactPosition, -hitNormal, sphere.Center + hitT * sphere.Delta, ref curCollPrim); } if (listAll) { HitInfo hitScratch = MakeHitScratch(curCollPrim, radii0.X); hits.Add(hitScratch); curCollPrim.DistSq = Single.MaxValue; } else if (curCollPrim.DistSq <= best.DistSq) { best = curCollPrim; hit = true; if (best.Touching) { HitInfo hitScratch = MakeHitScratch(best, radii0.X); hits.Add(hitScratch); } } } // end if hitTest } // end of loop over other movers. if (hit) { Debug.Assert(!listAll, "Hit shouldn't get set when listing all hits"); /// If it's touching, we've already applied, otherwise /// do it here. if (!best.Touching) { HitInfo hitScratch = MakeHitScratch(best, radii0.X); hits.Add(hitScratch); } } if (listAll && (hits.Count > 1)) { hits.Sort(comparer); } return(hits.Count > 0); }