GithubHelp home page GithubHelp logo

codingben / box2d-netstandard Goto Github PK

View Code? Open in Web Editor NEW
261.0 261.0 51.0 1.23 MB

C# port of Box2D - Erin Catto's 2D Physics Engine

Home Page: https://box2d.org

License: MIT License

C# 100.00%
box2d

box2d-netstandard's People

Contributors

codingben avatar hughph avatar thomasvt avatar winster332 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

box2d-netstandard's Issues

ContactListener Issue

I'm having an issue with the ContactListener.

I added a simple ContactListener to the RubeGoldbergWorld in the samples, and I'm having trouble identifying the two Fixture objects involved in the Contact, and their parent Body objects.

I turned this line:

world = RubeGoldbergWorld.CreateWorld(out Body[] bodies, out Joint[] joints);

into these two lines:

world = RubeGoldbergWorld.CreateWorld(out Body[] bodies, out Joint[] joints);
world.SetContactListener(new TestContactListener());

And I added the following class:

    public class TestContactListener : ContactListener
    {
        public override void BeginContact(in Contact contact)
        {
            Fixture fixtureA = contact.GetFixtureA();
            Fixture fixtureB = contact.GetFixtureB();

            Body bodyA = fixtureA.GetBody();
            Body bodyB = fixtureB.GetBody();

            if (bodyA == null || bodyB == null)
            {
                File.AppendAllText(@"C:\Users\username\Desktop\nothing.txt", "just making sure this function does something so it is not optimized out");
            }
        }

        public override void EndContact(in Contact contact)
        {

        }

        public override void PostSolve(in Contact contact, in ContactImpulse impulse)
        {

        }

        public override void PreSolve(in Contact contact, in Manifold oldManifold)
        {

        }
    }

Setting a breakpoint on the if statement and inspecting the objects above it indicates problems:

image

image

All four of the functions in the ContactListener behave the same way. What am I doing wrong?

FrictionJoint not implemented?

I'm trying to use a FrictionJointDef, but when I try to create one, I get:

System.Runtime.CompilerServices.SwitchExpressionException: 'Non-exhaustive switch expression failed to match its input.
Unmatched value was Box2D.NetStandard.Dynamics.Joints.Friction.FrictionJointDef.'

   at Box2D.NetStandard.Dynamics.Joints.Joint.Create(JointDef def)
   at Box2D.NetStandard.Dynamics.World.World.CreateJoint(JointDef def)
   ...

In source code, it doesn't look like that joint def is in the switch statement. Being that FrictionJoint and FrictionJointDef do exist, I'm wondering if this was just missed (or incomplete)?

Using Box2D.NetStandard 2.4.2-alpha

CircleShape a work in progress?

I am using 2.4.5-alpha.

I created a PolygonShape, and it appears to behave as expected (collisions, rotations, etc).

I then created a CircleShape in the same way as the polygon, but it does not detect collisions properly, and at times just spins off and fly's around out of control. Is CircleShape working? If so then I must be misunderstanding something in the shape's creation. I will paste some code here, but it's kind of messy since I'm trying different things to figure this out.

Thanks for any help!

Working (colliding etc):

    public RectangleBody(float x, float y, float w, float h, World world, BodyType type)
    {
        this.w = w;
        this.h = h;
        this.aliveBuffer = w + h;

        this.position = new Vector2(x, y);

        BodyDef bodyDef = new BodyDef();
        bodyDef.position = Box2DHelper.CoordPixelsToWorld(x, y);
        bodyDef.type = type;
        if (type == BodyType.Dynamic)
        {
            bodyDef.angularVelocity = (float)Random(-10, 10);
            bodyDef.linearVelocity = new Vector2((float)Random(-5, 5), (float)Random(10));
        }
        body = world.CreateBody(bodyDef);

        PolygonShape shape = new PolygonShape();
        float scalarW = Box2DHelper.ScalarPixelsToWorld(w / 2);
        float scalarH = Box2DHelper.ScalarPixelsToWorld(h / 2);
        shape.SetAsBox(scalarW, scalarH);

        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = shape;

        float rngDensity = (float)Random(5, 15);
        this.density = (int)rngDensity;
        fixtureDef.density = rngDensity;

        fixtureDef.friction = 1f;
        fixtureDef.restitution = 0.15f;
        body.CreateFixture(fixtureDef);
    }

Not working (no collisions, etc):

    public CircleBody(float x, float y, float r, World world, BodyType type)
    {
        this.r = r;
        this.aliveBuffer = r * 2;

        this.position = new Vector2(x, y);
        Vector2 worldPos = Box2DHelper.CoordPixelsToWorld(position);

        BodyDef bodyDef = new BodyDef();
        bodyDef.position = worldPos;
        bodyDef.type = type;
        if (type == BodyType.Dynamic)
        {
            //bodyDef.angularVelocity = (float)Random(-10, 10);
            bodyDef.linearVelocity = new Vector2((float)Random(-5, 5), (float)Random(10));
        }
        body = world.CreateBody(bodyDef);

        CircleShape shape = new CircleShape();
        float scalarR = Box2DHelper.ScalarPixelsToWorld(r);
        shape.Set(worldPos, scalarR);

        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = shape;

        float rngDensity = (float)Random(5, 15);
        this.density = (int)rngDensity;
        fixtureDef.density = 10000;

        fixtureDef.friction = 0.3f;
        fixtureDef.restitution = 0.1f;
        body.CreateFixture(fixtureDef);
    }

Unable to set CircleShape radius

Description

I'm not sure if I'm missing something, but I can't seem to set the radius of a CircleShape. There isn't a 'Radius' property as is shown in the example, there isn't a way for it to use a CircleDef object.

How To Reproduce

  • Create a CircleShape object CircleShape shape = new CircleShape();
  • Be unable to set the radius? shape.Radius //not a thing

Expected Behavior

There should be a 'shape.Radius' property like in the example

Body.DestroyFixture Fails when Fixture is the first in list

I believe I found a bug with Body.DestroyFixture. Body tracks fixtures using a linked list. When calling Body.DestroyFixture, and the fixture to be destroyed is the first fixture in the linked list, m_fixtureList isn't updated, and continues to point to the fixture getting destroyed. This results in Body.m_fixtureList pointing to a single, broken fixture (where both m_body and m_next are null), and all other fixtures are lost (no longer in Body's linked list).

I believe the fix should be simple enough. If the fixture to be destroyed is the first in the linked list, update m_fixtureList to point to that fixture's m_next.

This bug also exists in the C++ implementation, and currently have a thread for it on discord: https://discord.com/channels/460295137705197568/460295137705197570/927374070515900416. Just wanted to track it here as well, as I'm currently halted on my project due to this.

Manifold properties are all internal

Description

Properties of a Manifold are all set to "internal". Manifold.cs

Additionally, Contact.GetWorldManifold Contact.cs

This means while using the nuget package, I have no access to contact manifolds in a ContactListener

How To Reproduce

Create a new project using the nuget package and try to access oldManifold.points

Expected Behavior

Manifolds are accessible

DistanceJoint grows over time

Evident in RubeGoldberg test world: after the ball hits the ragdoll, the ball gradually sinks lower as it swings.

Null Reference Exceptions when running

I fixed these and somehow the files went walkabout.

In summary, in some places structs are expected, and that's fine in the C++ code because they're accessed by reference. In C#, when an item is picked from an array and it's a value type (e.g. a struct), what you get is a copy. The upshot is that mutating the object mutates the copy that you got, and not the item in the array. As a consequence, I had to use classes for several types. And a knock-on effect is that they then must be explicitly instantiated with the new keyword.

Get vertices of PolygonShape

Description

I'm thinking how to implement my own box2d renderer.
DebugDraw is fine but its really made for debug purposes only.
Callbacks in DebugDraw do not provide anything to link to my objects. I cant select texture, fox example.

To render PolygonShape myself I must get its current vertices coordinates.
C++ box2d engine holds them inside b2PolygonShape.m_vertices.
C# interface do not provide any methods to access vertices

Breaking solid objects in half

Description

This isn't actually an issue, I'm just looking for guidance.

Suppose I have a rectangle (representing a brick) and a circle (representing a slow-ish bullet) and if the bullet hits the brick with enough speed I want to turn the brick from one object into two or three objects along fracture lines that seem intuitive.

Do you think it would work for me to modify the ContactManager.Collide() method in such a way that it does two passes... The first pass could replace the bottom part of the function that looks like

// Here we destroy contacts that cease to overlap in the broad-phase.
if (overlap == false)
{
    Contact cNuke = c;
    c = cNuke.GetNext();
    Destroy(cNuke);
    continue;
}

// The contact persists.
c.Update(m_contactListener);
c = c.GetNext();

with something like

if (overlap == true)
{
    ...break brick into pieces if conditions are met...
}

and then the second pass would be exactly the code that's in the ContactManager.Collide() method normally?

Or would this not work? Maybe I would need to rewind positions after the first pass? Possibly by capturing the world state at the beginning of the first pass and resetting it to that (except for the broken brick) before doing the second pass?

[Bug] Prismatic Joint affected by Vector2.Normalize

Description

When applying a Prismatic Joint, the localAxisA is normalized. This causes {NaN, NaN} when the joint is new Vector2(0,0)

See

m_localXAxisA = Vector2.Normalize(def.localAxisA);

How To Reproduce

Create a new prismatic joint where the localAxisA is new Vector2(0,0)

You can work around the issue by using Reflection to update the private values:

var jdef = new PrismaticJointDef();
jdef.bodyA = body1;
jdef.bodyB = body2;
jdef.collideConnected = false;
jdef.localAxisA = new Vector2(0, 0);

var pJoint = world.CreateJoint(jdef);

var propX = pJoint.GetType().GetField("m_localXAxisA", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var propY = pJoint.GetType().GetField("m_localYAxisA", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
propX.SetValue(pJoint, new Vector2(0, 0));
propY.SetValue(pJoint, new Vector2(0, 0));

Expected Behavior

Something similar to:

https://github.com/erincatto/box2d/blob/c6cc3646d1701ab3c0750ef397d2d68fc6dbcff2/src/dynamics/b2_prismatic_joint.cpp#L88

The mask and category bits seem to be ignored - 1.0.3

In Version 1.0.3 of the project, the Filter.MaskBits and Filter.CategoryBits seem to be ignored.

I have created a really simple scene where I have a square and a static floor. I have set the filter data up like below which I expect would allow the square to not collide with the floor as the mask and category bits for each are different.

FilterData cubeFilter = new() { CategoryBits = 0b0001, MaskBits = 0b0010 };
FilterData floorFilter = new() { CategoryBits = 0b0100, MaskBits = 0b1000 };

However, the square and the floor still collide and do not pass through each other.

I created the project as a .NET 5 console application.

NuGets

Install-Package Box2D.NetStandard -Version 1.0.3
Install-Package Box2D.Window -Version 1.0.3

Code

using Box2D.Window;
using Box2DX.Collision;
using Box2DX.Common;
using Box2DX.Dynamics;
using System.Threading;

namespace Box2dMcve
{
    internal static class Program
    {
        private static void Main()
        {
            AABB aabb = new();
            aabb.LowerBound.Set(-20, -10);
            aabb.UpperBound.Set(20, 110);

            World world = new(aabb, new Vec2(0.0f, -9.81f), false);

            BodyDef cubeDefinition = new();
            cubeDefinition.Position.Set(0, 70);

            PolygonDef cubeFixture = new();
            cubeFixture.SetAsBox(5, 5);
            cubeFixture.Friction = 0;
            cubeFixture.Restitution = 0;
            cubeFixture.Density = 1;
            FilterData cubeFilter = new() { CategoryBits = 0b0001, MaskBits = 0b0010 };
            cubeFixture.Filter = cubeFilter;

            Body basicCube = world.CreateBody(cubeDefinition);
            basicCube.CreateFixture(cubeFixture);
            basicCube.SetMassFromShapes();

            BodyDef floorDefinition = new();
            floorDefinition.Position.Set(0, 20);

            PolygonDef floorFixture = new();
            floorFixture.SetAsBox(20, 5);
            floorFixture.Friction = 0;
            floorFixture.Restitution = 0;
            FilterData floorFilter = new() { CategoryBits = 0b0100, MaskBits = 0b1000 };
            floorFixture.Filter = floorFilter;

            Body floor = world.CreateBody(floorDefinition);
            floor.CreateFixture(floorFixture);
            floor.SetStatic();

            Thread windowThread = new(() =>
            {
                SimulationWindow game = new("Physics Simulation", 800, 600);
                game.UpdateFrame += (_, _) => { world.Step(0.02f, 8, 3); };
                game.SetView(new CameraView());

                DrawPhysics physicsDrawer = new(game);
                physicsDrawer.AppendFlags(DebugDraw.DrawFlags.Aabb);
                physicsDrawer.AppendFlags(DebugDraw.DrawFlags.Shape);

                world.SetDebugDraw(physicsDrawer);

                game.VSync = OpenTK.VSyncMode.Adaptive;
                game.Run(60, 0);
            });

            windowThread.Start();
        }
    }
}

How to use Raycast?

Hi, i was wondering if somebody has an example on how to use Raycast. The implementation showed in the docs does not quite work for me

DebugDraw has obsolete methods without non obsolete replacement methods

Description

The following methods in DebugDraw are obsolete but without new Vector2 based version:

        [Obsolete("Look out for new calls using Vector2")]
        public abstract void DrawPolygon(in Vec2[] vertices, int vertexCount, in Color color);

        [Obsolete("Look out for new calls using Vector2")]
        public abstract void DrawSolidPolygon(in Vec2[] vertices, int vertexCount, in Color color);

        [Obsolete("Look out for new calls using Vector2")]
        public abstract void DrawCircle(in Vec2 center, float radius, in Color color);

        [Obsolete("Look out for new calls using Vector2")]
        public abstract void DrawSolidCircle(in Vec2 center, float radius, in Vec2 axis, in Color color);

        [Obsolete("Look out for new calls using Vector2")]
        public abstract void DrawSegment(in Vec2 p1, in Vec2 p2, in Color color);


### How To Reproduce

Implement inherited class and compiler spits out warnings

### Expected Behavior

The abstract DebugDraw class should provide non obsolete method versions:

[Obsolete("Look out for new calls using Vector2")]
public abstract void DrawPolygon(in Vec2[] vertices, int vertexCount, in Color color);

public abstract void DrawPolygon(in Vector2[] vertices, int vertexCount, in Color color);

DebugDraw doesn't work

It was left out as a "to-do-later" job. Debug Draw changed significantly between Box2DX (2008) and today (2020!! 12 years on!!)

PolygonDef SetAsBox(....) Angle maybe radian?

test code

var b = world.CreateBody(new BodyDef { Position = new Vec2(0, 0), MassData = new MassData { Mass = 0 } });
var s = new PolygonDef();
s.SetAsBox(10, 10, Vec2.Zero, 30 * 0.01745f);
b.CreateFixture(s);

need the convert angle to radian, current i test meet expectation, i am correct?
not found need radian in SetAsBox params comment
thank

ChainShape

Hello! just wanted to know if anyone is going work on/add the ChainShape soon or not.
because I really want it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.