[ ] WPF Box2D. c WPF |
public class MyModel3D
{
public Vector3D Position { get; set; } //
public Size Size { get; set; } //
private TranslateTransform3D translateTransform; //
private RotateTransform3D rotationTransform; //
public MyModel3D(Model3DGroup models, double x, double y, double z, string path, Size size, float axis_x = 0, double angle = 0, float axis_y = 0, float axis_z = 1)
{
this.Size = size;
this.Position = new Vector3D(x, y, z);
MeshGeometry3D mesh = new MeshGeometry3D();
//
mesh.Positions = new Point3DCollection(new List
{
new Point3D(-size.Width/2, -size.Height/2, 0),
new Point3D(size.Width/2, -size.Height/2, 0),
new Point3D(size.Width/2, size.Height/2, 0),
new Point3D(-size.Width/2, size.Height/2, 0)
});
//
mesh.TriangleIndices = new Int32Collection(new List { 0, 1, 2, 0, 2, 3 });
mesh.TextureCoordinates = new PointCollection();
//
mesh.TextureCoordinates.Add(new Point(0, 1));
mesh.TextureCoordinates.Add(new Point(1, 1));
mesh.TextureCoordinates.Add(new Point(1, 0));
mesh.TextureCoordinates.Add(new Point(0, 0));
//
ImageBrush brush = new ImageBrush(new BitmapImage(new Uri(path)));
Material material = new DiffuseMaterial(brush);
GeometryModel3D geometryModel = new GeometryModel3D(mesh, material);
models.Children.Add(geometryModel);
translateTransform = new TranslateTransform3D(x, y, z);
rotationTransform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(axis_x, axis_y, axis_z), angle), 0.5, 0.5, 0.5);
Transform3DGroup tgroup = new Transform3DGroup();
tgroup.Children.Add(translateTransform);
tgroup.Children.Add(rotationTransform);
geometryModel.Transform = tgroup;
}
//
public void SetPosition(Vector3D v3)
{
translateTransform.OffsetX = v3.X;
translateTransform.OffsetY = v3.Y;
translateTransform.OffsetZ = v3.Z;
}
public Vector3D GetPosition()
{
return new Vector3D(translateTransform.OffsetX, translateTransform.OffsetY, translateTransform.OffsetZ);
}
//
public void Rotation(Vector3D axis, double angle, double centerX = 0.5, double centerY = 0.5, double centerZ = 0.5)
{
rotationTransform.CenterX = translateTransform.OffsetX;
rotationTransform.CenterY = translateTransform.OffsetY;
rotationTransform.CenterZ = translateTransform.OffsetZ;
rotationTransform.Rotation = new AxisAngleRotation3D(axis, angle);
}
public Size GetSize()
{
return Size;
}
}
public class Physics
{
private World world;
public Physics(float x, float y, float w, float h, float g_x, float g_y, bool doSleep)
{
AABB aabb = new AABB();
aabb.LowerBound.Set(x, y); //
aabb.UpperBound.Set(w, h); //
Vec2 g = new Vec2(g_x, g_y); //
world = new World(aabb, g, doSleep); //
}
}
private const string PATH_CIRCLE = @"Assets\circle.png"; //
private const string PATH_RECT = @"Assets\rect.png"; //
public MyModel3D AddBox(float x, float y, float w, float h, float density, float friction, float restetution)
{
//
MyModel3D model = new MyModel3D(models, x, -y, 0, PATH_RECT, new System.Windows.Size(w, h));
// , , ..
BodyDef bDef = new BodyDef();
bDef.Position.Set(x, y);
bDef.Angle = 0;
//
PolygonDef pDef = new PolygonDef();
pDef.Restitution = restetution;
pDef.Friction = friction;
pDef.Density = density;
pDef.SetAsBox(w / 2, h / 2);
//
Body body = world.CreateBody(bDef);
body.CreateShape(pDef);
body.SetMassFromShapes();
body.SetUserData(model); // , object, , step
return model;
}
public MyModel3D AddCircle(float x, float y, float radius, float angle, float density,
float friction, float restetution)
{
MyModel3D model = new MyModel3D(models, x, -y, 0, PATH_CIRCLE, new System.Windows.Size(radius * 2, radius * 2));
BodyDef bDef = new BodyDef();
bDef.Position.Set(x, y);
bDef.Angle = angle;
CircleDef pDef = new CircleDef();
pDef.Restitution = restetution;
pDef.Friction = friction;
pDef.Density = density;
pDef.Radius = radius;
Body body = world.CreateBody(bDef);
body.CreateShape(pDef);
body.SetMassFromShapes();
body.SetUserData(model);
return model;
}
public MyModel3D AddVert(float x, float y, Vec2[] vert, float angle, float density,
float friction, float restetution)
{
MyModel3D model = new MyModel3D(models, x, y, 0, Environment.CurrentDirectory + "\\" + PATH_RECT, new System.Windows.Size(w, h)); //
BodyDef bDef = new BodyDef();
bDef.Position.Set(x, y);
bDef.Angle = angle;
PolygonDef pDef = new PolygonDef();
pDef.Restitution = restetution;
pDef.Friction = friction;
pDef.Density = density;
pDef.SetAsBox(model.Size.Width / 2, model.Size.Height / 2);
pDef.Vertices = vert;
Body body = world.CreateBody(bDef);
body.CreateShape(pDef);
body.SetMassFromShapes();
body.SetUserData(model);
return info;
}
public void Step(float dt, int iterat)
{
//
world.Step(dt / 1000.0f, iterat, iterat);
for (Body list = world.GetBodyList(); list != null; list = list.GetNext())
{
if (list.GetUserData() != null)
{
System.Windows.Media.Media3D.Vector3D position = new System.Windows.Media.Media3D.Vector3D(
list.GetPosition().X, list.GetPosition().Y, 0);
float angle = list.GetAngle() * 180.0f / (float)System.Math.PI; //
MyModel3D model = (MyModel3D)list.GetUserData();
model.SetPosition(position); // x,y
model.Rotation(new System.Windows.Media.Media3D.Vector3D(0, 0, 1), angle); // x
}
}
}
public partial class MainWindow : Window
{
private Game.Physics px;
public MainWindow()
{
InitializeComponent();
px = new Game.Physics(-1000, -1000, 1000, 1000, 0, -0.005f, false);
px.SetModelsGroup(models);
px.AddBox(0.6f, -2, 1, 1, 0, 0.3f, 0.2f);
px.AddBox(0, 0, 1, 1, 0.5f, 0.3f, 0.2f);
this.LayoutUpdated += MainWindow_LayoutUpdated;
}
private void MainWindow_LayoutUpdated(object sender, EventArgs e)
{
px.Step(1.0f, 20); // , :)
this.InvalidateArrange();
}
}
public class Solver : ContactListener
{
public delegate void EventSolver(MyModel3D body1, MyModel3D body2);
public event EventSolver OnAdd;
public event EventSolver OnPersist;
public event EventSolver OnResult;
public event EventSolver OnRemove;
public override void Add(ContactPoint point)
{
base.Add(point);
OnAdd?.Invoke((MyModel3D)point.Shape1.GetBody().GetUserData(), (MyModel3D)point.Shape2.GetBody().GetUserData());
}
public override void Persist(ContactPoint point)
{
base.Persist(point);
OnPersist?.Invoke((MyModel3D)point.Shape1.GetBody().GetUserData(), (MyModel3D)point.Shape2.GetBody().GetUserData());
}
public override void Result(ContactResult point)
{
base.Result(point);
OnResult?.Invoke((MyModel3D)point.Shape1.GetBody().GetUserData(), (MyModel3D)point.Shape2.GetBody().GetUserData());
}
public override void Remove(ContactPoint point)
{
base.Remove(point);
OnRemove?.Invoke((MyModel3D)point.Shape1.GetBody().GetUserData(), (MyModel3D)point.Shape2.GetBody().GetUserData());
}
}
public void SetSolver(ContactListener listener)
{
world.SetContactListener(listener);
}
Game.Solver solver = new Game.Solver();
px.SetSolver(solver);
solver.OnAdd += (model1, model2) =>
{
// model1 model2
};
public Joint AddJoint(Body b1, Body b2, float x, float y)
{
RevoluteJointDef jd = new RevoluteJointDef();
jd.Initialize(b1, b2, new Vec2(x, y));
Joint joint = world.CreateJoint(jd);
return joint;
}
public Joint AddDistanceJoint(Body b1, Body b2, float x1, float y1, float x2, float y2,
bool collideConnected = true, float hz = 1f)
{
DistanceJointDef jd = new DistanceJointDef();
jd.Initialize(b1, b2, new Vec2(x1, y1), new Vec2(x2, y2));
jd.CollideConnected = collideConnected;
jd.FrequencyHz = hz;
Joint joint = world.CreateJoint(jd);
return joint;
}