-

   rss_rss_hh_new

 - e-mail

 

 -

 LiveInternet.ru:
: 17.03.2011
:
:
: 51

:


[ ] WPF Box2D. c WPF

, 14 2017 . 11:33 +
image

. , Box2D. . Box2D C#, . . , . , . WPF Viewport3D. , .

Box2D , . Box2D . (. Erin Catto), C++ zlib.
, Angry Birds, Limbo, Crayon Physics Deluxe, Rolando, Fantastic Contraption, Incredibots, Transformice, Happy Wheels, Color Infection, Shovel Knight, King of Thieves.
Box2D.dll

WPF Viewport3D


WPF, , Grphics PictureBox, .. Graphics .
. XAML:


        
            
                
            
            
                
                    
						
						
						
					
				
			
		
    


ClipToBounds , .. 2D , .

. FarPlaneDistance , NearPlaneDistance , , . Model3DGroup models, 3 .

, XAML , :

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


. . .

imageimage

Box2D Hello world


, . Box2D , () .

image

, . , . Physics :

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


, 3 . Physics :

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


model AddCircle AddBox body.SetUserDate()? , MyModel3D model = (MyModel3D)list.GetUserData(); Box2D.

, :

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


image

, Physics px.SetModelsGroup(); Model3DGroup. , .

, . Box2D , , 30. bDef.SetPosition(x / 30.0f, y / 30.0f); .

, Box2D , . , .. Solver:

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


ContactListener. Box2D . world Physics, :

public void SetSolver(ContactListener listener)
{
	world.SetContactListener(listener);
}

:

Game.Solver solver = new Game.Solver();
px.SetSolver(solver);

Solver , :

solver.OnAdd += (model1, model2) =>
{
	//    model1  model2
};

MyModel3D string name, OnAdd .
Box2D . , :

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


b1 b2 x, y. RevoluteJointDef. , , . :

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


, , hz . , .


Box2D. , , . Xamarin 4.1.1 , - Box2D . ART , .

GitHub: github.com/Winster332/Habrahabr
dotnet core: github.com/Winster332/box2d-dotnet-core-1.0
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333040/

:  

: [1] []
 

:
: 

: ( )

:

  URL