-
Notifications
You must be signed in to change notification settings - Fork 288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#291 Fixing Pickshapes using farseer #579
Changes from 4 commits
0d53bf4
e5f5262
e243a80
ccb3e57
e7e308c
7a9c401
b0b3f49
0462b48
c6f6499
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,9 @@ | |
using Duality.Cloning; | ||
using Duality.Resources; | ||
using Duality.Properties; | ||
using FarseerPhysics.Common; | ||
using FarseerPhysics.Collision; | ||
using FarseerPhysics.Collision.Shapes; | ||
|
||
namespace Duality.Components.Physics | ||
{ | ||
|
@@ -208,7 +211,7 @@ public float Friction | |
{ | ||
if (this.shapes != null) | ||
{ | ||
foreach (var s in this.shapes) | ||
foreach (ShapeInfo s in this.shapes) | ||
s.Friction = value; | ||
} | ||
} | ||
|
@@ -225,7 +228,7 @@ public float Restitution | |
{ | ||
if (this.shapes != null) | ||
{ | ||
foreach (var s in this.shapes) | ||
foreach (ShapeInfo s in this.shapes) | ||
s.Restitution = value; | ||
} | ||
} | ||
|
@@ -772,50 +775,65 @@ public bool PickShapes(Vector2 worldCoord, Vector2 size, List<ShapeInfo> pickedS | |
{ | ||
if (this.body == null) return false; | ||
|
||
Vector2 fsWorldCoord = PhysicsUnit.LengthToPhysical * worldCoord; | ||
FarseerPhysics.Collision.AABB fsWorldAABB = new FarseerPhysics.Collision.AABB(fsWorldCoord, PhysicsUnit.LengthToPhysical * (worldCoord + size)); | ||
|
||
PolygonShape boxShape = new PolygonShape(new Vertices(new List<Vector2>() { | ||
PhysicsUnit.LengthToPhysical * worldCoord, | ||
PhysicsUnit.LengthToPhysical * new Vector2(worldCoord.X + size.X, worldCoord.Y), | ||
PhysicsUnit.LengthToPhysical * (worldCoord + size), | ||
PhysicsUnit.LengthToPhysical * new Vector2(worldCoord.X, worldCoord.Y + size.Y) }), 1); | ||
Mat22 rot = new Mat22(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add a newline, so the box transform creation is its own block, similar to the body transform retrieval below. Also, maybe move the oldCount and manifold declarations down to directly in front of the loop, so it doesn't get mixes up with the transform creation blocks? |
||
rot.SetIdentity(); | ||
Vector2 pos = new Vector2(0, 0); | ||
FarseerPhysics.Common.Transform boxTransform = new FarseerPhysics.Common.Transform(ref pos, ref rot); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are transform position and rotation public fields? If so, no need to declare and assign rotation and position separately! Just call SetIdentity directly on the box transform rotation field, and assign the position directly without declaring an extra variable. Could also use the default / empty constructor in that case. (If they are not public fields, disregard my comment.) |
||
Manifold manifold = new Manifold(); | ||
int oldCount = pickedShapes.Count; | ||
|
||
FarseerPhysics.Common.Transform bodyTransform; | ||
this.body.GetTransform(out bodyTransform); | ||
|
||
for (int i = 0; i < this.body.FixtureList.Count; i++) | ||
{ | ||
Fixture f = this.body.FixtureList[i]; | ||
ShapeInfo s = f.UserData as ShapeInfo; | ||
|
||
FarseerPhysics.Collision.AABB fAABB; | ||
FarseerPhysics.Common.Transform transform; | ||
this.body.GetTransform(out transform); | ||
f.Shape.ComputeAABB(out fAABB, ref transform, 0); | ||
|
||
if (fsWorldAABB.Contains(ref fAABB)) | ||
PolygonShape polygonShape = f.Shape as PolygonShape; | ||
if (polygonShape != null) | ||
{ | ||
pickedShapes.Add(s); | ||
continue; | ||
Collision.CollidePolygons(ref manifold, boxShape, ref boxTransform, polygonShape, ref bodyTransform); | ||
if (manifold.PointCount > 0) | ||
{ | ||
pickedShapes.Add(s); | ||
continue; | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it's a polygon shape, but does not have any collisions, it will continue checking whether it could be a circle shape next. Consider changing this to an if-else structure, or moving the continue statement out of the point count check! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ye missed that, it should obviously not do the circle check after it already done the polygon one. Too bad we dont have C# 7 as pattern matching would make this so much more readable. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Found out there is a ShapeType enum property on the fixture so I can use that in a switch. Much more readable. |
||
else if (!FarseerPhysics.Collision.AABB.TestOverlap(ref fsWorldAABB, ref fAABB)) | ||
continue; | ||
|
||
FarseerPhysics.Collision.AABB fAABBIntersect; | ||
fAABBIntersect.LowerBound = Vector2.Max(fAABB.LowerBound, fsWorldAABB.LowerBound); | ||
fAABBIntersect.UpperBound = Vector2.Min(fAABB.UpperBound, fsWorldAABB.UpperBound); | ||
|
||
Vector2 fsWorldCoordStep = PhysicsUnit.LengthToPhysical * (new Vector2(MathF.Max(s.AABB.W, 1.0f), MathF.Max(s.AABB.H, 1.0f)) * 0.05f); | ||
Vector2 fsTemp = fAABBIntersect.LowerBound; | ||
do | ||
CircleShape circleShape = f.Shape as CircleShape; | ||
if (circleShape != null) | ||
{ | ||
if (f.TestPoint(ref fsTemp)) | ||
Collision.CollidePolygonAndCircle(ref manifold, boxShape, ref boxTransform, circleShape, ref bodyTransform); | ||
if (manifold.PointCount > 0) | ||
{ | ||
pickedShapes.Add(s); | ||
break; | ||
continue; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above! |
||
} | ||
} | ||
|
||
fsTemp.X += fsWorldCoordStep.X; | ||
if (fsTemp.X > fAABBIntersect.UpperBound.X) | ||
{ | ||
fsTemp.X = fAABBIntersect.LowerBound.X; | ||
fsTemp.Y += fsWorldCoordStep.Y; | ||
} | ||
if (fsTemp.Y > fAABBIntersect.UpperBound.Y) break; | ||
} while (true); | ||
// This one is still buggy | ||
//var chainShape = f.Shape as ChainShape; | ||
//if (chainShape != null) | ||
//{ | ||
|
||
// for (int j = 0; j < chainShape.Vertices.Count - 1; j++) | ||
// { | ||
// var jNext = j + 1; | ||
// if (jNext >= chainShape.Vertices.Count) jNext = 0; | ||
// var edgeShape = new EdgeShape(chainShape.Vertices[j], chainShape.Vertices[jNext]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if that will fix it, but instead of creating a new edge shape every loop iteration, create it once and let the chain shape configure it. There's a Alternatively, if you want to keep chain shapes our of this PR for now, maybe just add a note to the commented out section regarding this, for future reference. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was still experimenting with this part. I already tried it with GetChildEdge but got some weird results so have to investigate that some more. Not for this PR though so Ill put a clarifying comment there |
||
// Collision.CollideEdgeAndPolygon(ref manifold, edgeShape, ref bodyTransform, boxShape, ref boxTransform); | ||
// if (manifold.PointCount > 0) | ||
// { | ||
// pickedShapes.Add(s); | ||
// break; | ||
// } | ||
// } | ||
//} | ||
} | ||
|
||
return pickedShapes.Count > oldCount; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Glad you didn't bother keeping the old
fsWorldCoord
naming / variable scheme. That was terrible. This one looks definitely cleaner.