mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Fix centre of mass (#2212)
This commit is contained in:
@@ -589,7 +589,7 @@ namespace Robust.Shared.GameObjects
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float Inertia
|
||||
{
|
||||
get => _inertia + Mass * Vector2.Dot(LocalCenter, LocalCenter);
|
||||
get => _inertia + _mass * Vector2.Dot(_localCenter, _localCenter);
|
||||
set
|
||||
{
|
||||
DebugTools.Assert(!float.IsNaN(value));
|
||||
@@ -600,7 +600,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
if (value > 0.0f && !_fixedRotation)
|
||||
{
|
||||
_inertia = value - Mass * Vector2.Dot(LocalCenter, LocalCenter);
|
||||
_inertia = value - Mass * Vector2.Dot(_localCenter, _localCenter);
|
||||
DebugTools.Assert(_inertia > 0.0f);
|
||||
InvI = 1.0f / _inertia;
|
||||
Dirty();
|
||||
@@ -644,7 +644,6 @@ namespace Robust.Shared.GameObjects
|
||||
[DataField("fixedRotation")]
|
||||
private bool _fixedRotation = true;
|
||||
|
||||
// TODO: Will be used someday
|
||||
/// <summary>
|
||||
/// Get this body's center of mass offset to world position.
|
||||
/// </summary>
|
||||
@@ -658,6 +657,7 @@ namespace Robust.Shared.GameObjects
|
||||
set
|
||||
{
|
||||
if (_bodyType != BodyType.Dynamic) return;
|
||||
|
||||
if (value.EqualsApprox(_localCenter)) return;
|
||||
|
||||
_localCenter = value;
|
||||
@@ -991,7 +991,13 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
internal Transform GetTransform()
|
||||
{
|
||||
return new(Owner.Transform.WorldPosition, (float) Owner.Transform.WorldRotation.Theta);
|
||||
var position = Owner.Transform.WorldPosition;
|
||||
var angle = (float) Owner.Transform.WorldRotation.Theta;
|
||||
|
||||
var xf = new Transform(position, angle);
|
||||
// xf.Position -= Transform.Mul(xf.Quaternion2D, LocalCenter);
|
||||
|
||||
return xf;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1115,8 +1121,7 @@ namespace Robust.Shared.GameObjects
|
||||
_invMass = 0.0f;
|
||||
_inertia = 0.0f;
|
||||
InvI = 0.0f;
|
||||
LocalCenter = Vector2.Zero;
|
||||
// Sweep
|
||||
_localCenter = Vector2.Zero;
|
||||
|
||||
if (((int) _bodyType & (int) BodyType.Kinematic) != 0)
|
||||
{
|
||||
@@ -1124,33 +1129,18 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
|
||||
var localCenter = Vector2.Zero;
|
||||
var shapeManager = IoCManager.Resolve<IShapeManager>();
|
||||
|
||||
foreach (var fixture in _fixtures)
|
||||
{
|
||||
if (fixture.Mass <= 0.0f) continue;
|
||||
|
||||
var fixMass = fixture.Mass;
|
||||
var data = new MassData {Mass = fixture.Mass};
|
||||
shapeManager.GetMassData(fixture.Shape, ref data);
|
||||
|
||||
_mass += fixMass;
|
||||
|
||||
var center = Vector2.Zero;
|
||||
|
||||
// TODO: God this is garbage
|
||||
switch (fixture.Shape)
|
||||
{
|
||||
case PhysShapeAabb aabb:
|
||||
center = aabb.Centroid;
|
||||
break;
|
||||
case PolygonShape poly:
|
||||
center = poly.Centroid;
|
||||
break;
|
||||
case PhysShapeCircle circle:
|
||||
center = circle.Position;
|
||||
break;
|
||||
}
|
||||
|
||||
localCenter += center * fixMass;
|
||||
_inertia += fixture.Inertia;
|
||||
_mass += data.Mass;
|
||||
localCenter += data.Center * data.Mass;
|
||||
_inertia += data.I;
|
||||
}
|
||||
|
||||
if (BodyType == BodyType.Static)
|
||||
@@ -1173,7 +1163,7 @@ namespace Robust.Shared.GameObjects
|
||||
if (_inertia > 0.0f && !_fixedRotation)
|
||||
{
|
||||
// Center inertia about center of mass.
|
||||
_inertia -= _mass * Vector2.Dot(Vector2.Zero, Vector2.Zero);
|
||||
_inertia -= _mass * Vector2.Dot(localCenter, localCenter);
|
||||
|
||||
DebugTools.Assert(_inertia > 0.0f);
|
||||
InvI = 1.0f / _inertia;
|
||||
@@ -1184,16 +1174,19 @@ namespace Robust.Shared.GameObjects
|
||||
InvI = 0.0f;
|
||||
}
|
||||
|
||||
LocalCenter = Vector2.Zero;
|
||||
_localCenter = localCenter;
|
||||
|
||||
// TODO: Calculate Sweep
|
||||
|
||||
/*
|
||||
var oldCenter = _sweep.Center;
|
||||
_sweep.LocalCenter = localCenter;
|
||||
_sweep.Center0 = _sweep.Center = Physics.Transform.Mul(GetTransform(), _sweep.LocalCenter);
|
||||
var oldCenter = Sweep.Center;
|
||||
Sweep.LocalCenter = localCenter;
|
||||
Sweep.Center0 = Sweep.Center = Transform.Mul(GetTransform(), Sweep.LocalCenter);
|
||||
*/
|
||||
|
||||
// Update center of mass velocity.
|
||||
var a = _sweep.Center - oldCenter;
|
||||
_linVelocity += new Vector2(-_angVelocity * a.y, _angVelocity * a.x);
|
||||
*/
|
||||
// _linVelocity += Vector2.Cross(_angVelocity, Worl - oldCenter);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -29,6 +29,7 @@ using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Vector2 = Robust.Shared.Maths.Vector2;
|
||||
|
||||
namespace Robust.Shared.Physics.Collision.Shapes
|
||||
{
|
||||
@@ -127,53 +128,11 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
Normals[i] = temp.Normalized;
|
||||
}
|
||||
|
||||
Centroid = ComputeCentroid(Vertices);
|
||||
|
||||
// Compute the polygon mass data
|
||||
// TODO: Update fixture. Maybe use events for it? Who tf knows.
|
||||
// If we get grid polys then we'll actually need runtime updating of bbs.
|
||||
}
|
||||
|
||||
private Vector2 ComputeCentroid(Vector2[] vertices)
|
||||
{
|
||||
var count = vertices.Length;
|
||||
|
||||
DebugTools.Assert(count >= 3);
|
||||
|
||||
var c = new Vector2(0.0f, 0.0f);
|
||||
float area = 0.0f;
|
||||
|
||||
// Get a reference point for forming triangles.
|
||||
// Use the first vertex to reduce round-off errors.
|
||||
var s = vertices[0];
|
||||
|
||||
const float inv3 = 1.0f / 3.0f;
|
||||
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
// Triangle vertices.
|
||||
var p1 = vertices[0] - s;
|
||||
var p2 = vertices[i] - s;
|
||||
var p3 = i + 1 < count ? vertices[i+1] - s : vertices[0] - s;
|
||||
|
||||
var e1 = p2 - p1;
|
||||
var e2 = p3 - p1;
|
||||
|
||||
float D = Vector2.Cross(e1, e2);
|
||||
|
||||
float triangleArea = 0.5f * D;
|
||||
area += triangleArea;
|
||||
|
||||
// Area weighted centroid
|
||||
c += (p1 + p2 + p3) * triangleArea * inv3;
|
||||
}
|
||||
|
||||
// Centroid
|
||||
DebugTools.Assert(area > float.Epsilon);
|
||||
c = c * (1.0f / area) + s;
|
||||
return c;
|
||||
}
|
||||
|
||||
public ShapeType ShapeType => ShapeType.Polygon;
|
||||
|
||||
public PolygonShape()
|
||||
|
||||
@@ -163,9 +163,6 @@ namespace Robust.Shared.Physics.Dynamics.Contacts
|
||||
positionConstraint.IndexA = bodyA.IslandIndex[data.IslandIndex];
|
||||
positionConstraint.IndexB = bodyB.IslandIndex[data.IslandIndex];
|
||||
(positionConstraint.InvMassA, positionConstraint.InvMassB) = (invMassA, invMassB);
|
||||
// TODO: Dis
|
||||
// positionConstraint.LocalCenterA = bodyA._sweep.LocalCenter;
|
||||
// positionConstraint.LocalCenterB = bodyB._sweep.LocalCenter;
|
||||
positionConstraint.LocalCenterA = bodyA.LocalCenter;
|
||||
positionConstraint.LocalCenterB = bodyB.LocalCenter;
|
||||
|
||||
|
||||
@@ -273,6 +273,7 @@ namespace Robust.Shared.Physics.Dynamics
|
||||
fixture._hard = _hard;
|
||||
fixture._collisionLayer = _collisionLayer;
|
||||
fixture._collisionMask = _collisionMask;
|
||||
fixture._mass = _mass;
|
||||
}
|
||||
|
||||
// Moved from Shape because no MassData on Shape anymore (due to serv3 and physics ease-of-use etc etc.)
|
||||
@@ -430,7 +431,8 @@ namespace Robust.Shared.Physics.Dynamics
|
||||
_collisionMask == other.CollisionMask &&
|
||||
Shape.Equals(other.Shape) &&
|
||||
Body == other.Body &&
|
||||
ID.Equals(other.ID);
|
||||
ID.Equals(other.ID) &&
|
||||
MathHelper.CloseTo(_mass, other._mass);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,10 +28,8 @@ using System;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Shared.Physics.Dynamics.Joints
|
||||
@@ -287,8 +285,8 @@ namespace Robust.Shared.Physics.Dynamics.Joints
|
||||
{
|
||||
_indexA = BodyA.IslandIndex[data.IslandIndex];
|
||||
_indexB = BodyB.IslandIndex[data.IslandIndex];
|
||||
_localCenterA = Vector2.Zero; //BodyA->m_sweep.localCenter;
|
||||
_localCenterB = Vector2.Zero; //BodyB->m_sweep.localCenter;
|
||||
_localCenterA = BodyA.LocalCenter;
|
||||
_localCenterB = BodyB.LocalCenter;
|
||||
_invMassA = BodyA.InvMass;
|
||||
_invMassB = BodyB.InvMass;
|
||||
_invIA = BodyA.InvI;
|
||||
|
||||
@@ -173,8 +173,8 @@ namespace Robust.Shared.Physics.Dynamics.Joints
|
||||
{
|
||||
_indexA = BodyA.IslandIndex[data.IslandIndex];
|
||||
_indexB = BodyB.IslandIndex[data.IslandIndex];
|
||||
_localCenterA = Vector2.Zero; // BodyA._sweep.LocalCenter;
|
||||
_localCenterB = Vector2.Zero; //BodyB._sweep.LocalCenter;
|
||||
_localCenterA = BodyA.LocalCenter;
|
||||
_localCenterB = BodyB.LocalCenter;
|
||||
_invMassA = BodyA.InvMass;
|
||||
_invMassB = BodyB.InvMass;
|
||||
_invIA = BodyA.InvI;
|
||||
|
||||
@@ -141,8 +141,8 @@ namespace Robust.Shared.Physics.Dynamics.Joints
|
||||
{
|
||||
_indexA = BodyA.IslandIndex[data.IslandIndex];
|
||||
_indexB = BodyB.IslandIndex[data.IslandIndex];
|
||||
_localCenterA = Vector2.Zero; //BodyA->m_sweep.localCenter;
|
||||
_localCenterB = Vector2.Zero; //BodyB->m_sweep.localCenter;
|
||||
_localCenterA = BodyA.LocalCenter;
|
||||
_localCenterB = BodyB.LocalCenter;
|
||||
_invMassA = BodyA.InvMass;
|
||||
_invMassB = BodyB.InvMass;
|
||||
_invIA = BodyA.InvI;
|
||||
|
||||
38
Robust.Shared/Physics/Dynamics/MassData.cs
Normal file
38
Robust.Shared/Physics/Dynamics/MassData.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019 Erin Catto
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Shared.Physics.Dynamics
|
||||
{
|
||||
public struct MassData
|
||||
{
|
||||
/// The mass of the shape, usually in kilograms.
|
||||
public float Mass;
|
||||
|
||||
/// The position of the shape's centroid relative to the shape's origin.
|
||||
public Vector2 Center;
|
||||
|
||||
/// The rotational inertia of the shape about the local origin.
|
||||
public float I;
|
||||
}
|
||||
}
|
||||
@@ -337,7 +337,7 @@ stored in a single array since multiple arrays lead to multiple misses.
|
||||
|
||||
// Didn't use the old variable names because they're hard to read
|
||||
var transform = _physicsManager.EnsureTransform(body);
|
||||
var position = transform.Position;
|
||||
var position = Transform.Mul(transform, body.LocalCenter);
|
||||
// DebugTools.Assert(!float.IsNaN(position.X) && !float.IsNaN(position.Y));
|
||||
var angle = transform.Quaternion2D.Angle;
|
||||
|
||||
@@ -516,6 +516,9 @@ stored in a single array since multiple arrays lead to multiple misses.
|
||||
// Temporary NaN guards until PVS is fixed.
|
||||
if (!float.IsNaN(bodyPos.X) && !float.IsNaN(bodyPos.Y))
|
||||
{
|
||||
var q = new Quaternion2D(angle);
|
||||
|
||||
bodyPos -= Transform.Mul(q, body.LocalCenter);
|
||||
// body.Sweep.Center = bodyPos;
|
||||
// body.Sweep.Angle = angle;
|
||||
|
||||
|
||||
@@ -20,26 +20,78 @@
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.Physics.Dynamics
|
||||
{
|
||||
/// This describes the motion of a body/shape for TOI computation.
|
||||
/// Shapes are defined with respect to the body origin, which may
|
||||
/// no coincide with the center of mass. However, to support dynamics
|
||||
/// we must interpolate the center of mass position.
|
||||
internal struct Sweep
|
||||
{
|
||||
/// <summary>
|
||||
/// Local center of mass position
|
||||
/// </summary>
|
||||
public Vector2 LocalCenter;
|
||||
|
||||
// AKA A in box2d
|
||||
public float Angle;
|
||||
|
||||
// AKA A0 in box2d
|
||||
/// <summary>
|
||||
/// Fraction of the current time step in the range [0,1]
|
||||
/// c0 and a0 are the positions at alpha0.
|
||||
/// </summary>
|
||||
public float Angle0;
|
||||
|
||||
public float Alpha0;
|
||||
|
||||
/// <summary>
|
||||
/// Generally reflects the body's worldposition but not always.
|
||||
/// Can be used to temporarily store it during CCD.
|
||||
/// </summary>
|
||||
// AKA C in box2d
|
||||
public Vector2 Center;
|
||||
|
||||
public float Center0;
|
||||
// AKA C0 in box2d
|
||||
public Vector2 Center0;
|
||||
|
||||
// I Didn't copy LocalCenter because it's also on the Body and it will normally be rarely set sooooo
|
||||
/// <summary>
|
||||
/// Get the interpolated transform at a specific time.
|
||||
/// </summary>
|
||||
/// <param name="beta">beta is a factor in [0,1], where 0 indicates alpha0.</param>
|
||||
/// <returns>the output transform</returns>
|
||||
public Transform GetTransform(float beta)
|
||||
{
|
||||
var xf = new Transform(Center0 * (1.0f - beta) + Center * beta, (1.0f - beta) * Angle0 + beta * Angle);
|
||||
|
||||
// Shift to origin
|
||||
xf.Position -= Transform.Mul(xf.Quaternion2D, LocalCenter);
|
||||
|
||||
return xf;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Advance the sweep forward, yielding a new initial state.
|
||||
/// </summary>
|
||||
/// <param name="alpha">the new initial time.</param>
|
||||
public void Advance(float alpha)
|
||||
{
|
||||
DebugTools.Assert(Alpha0 < 1.0f);
|
||||
float beta = (alpha - Alpha0) / (1.0f - Alpha0);
|
||||
Center0 += (Center - Center0) * beta;
|
||||
Angle0 += beta * (Angle - Angle0);
|
||||
Alpha0 = alpha;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalize the angles.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
float twoPi = 2.0f * MathF.PI;
|
||||
float d = twoPi * MathF.Floor(Angle0 / twoPi);
|
||||
Angle0 -= d;
|
||||
Angle -= d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics.Collision.Shapes;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.Physics
|
||||
{
|
||||
@@ -10,6 +12,8 @@ namespace Robust.Shared.Physics
|
||||
/// Returns whether a particular point intersects the specified shape.
|
||||
/// </summary>
|
||||
bool TestPoint(IPhysShape shape, Transform xform, Vector2 worldPoint);
|
||||
|
||||
void GetMassData(IPhysShape shape, ref MassData data);
|
||||
}
|
||||
|
||||
public class ShapeManager : IShapeManager
|
||||
@@ -43,5 +47,110 @@ namespace Robust.Shared.Physics
|
||||
throw new ArgumentOutOfRangeException($"No implemented TestPoint for {shape.GetType()}");
|
||||
}
|
||||
}
|
||||
|
||||
public void GetMassData(IPhysShape shape, ref MassData data)
|
||||
{
|
||||
DebugTools.Assert(data.Mass > 0f);
|
||||
|
||||
// Box2D just calls fixture.GetMassData which just calls the shape method anyway soooo
|
||||
// we can just cut out the middle-man
|
||||
switch (shape)
|
||||
{
|
||||
case EdgeShape edge:
|
||||
data.Mass = 0.0f;
|
||||
data.Center = (edge.Vertex1 + edge.Vertex2) * 0.5f;
|
||||
data.I = 0.0f;
|
||||
break;
|
||||
case PhysShapeCircle circle:
|
||||
// massData->mass = density * b2_pi * m_radius * m_radius;
|
||||
data.Center = circle.Position;
|
||||
|
||||
// inertia about the local origin
|
||||
data.I = data.Mass * (0.5f * circle.Radius * circle.Radius + Vector2.Dot(circle.Position, circle.Position));
|
||||
break;
|
||||
case PhysShapeAabb aabb:
|
||||
var polygon = (PolygonShape) aabb;
|
||||
GetMassData(polygon, ref data);
|
||||
break;
|
||||
case PolygonShape poly:
|
||||
// Polygon mass, centroid, and inertia.
|
||||
// Let rho be the polygon density in mass per unit area.
|
||||
// Then:
|
||||
// mass = rho * int(dA)
|
||||
// centroid.x = (1/mass) * rho * int(x * dA)
|
||||
// centroid.y = (1/mass) * rho * int(y * dA)
|
||||
// I = rho * int((x*x + y*y) * dA)
|
||||
//
|
||||
// We can compute these integrals by summing all the integrals
|
||||
// for each triangle of the polygon. To evaluate the integral
|
||||
// for a single triangle, we make a change of variables to
|
||||
// the (u,v) coordinates of the triangle:
|
||||
// x = x0 + e1x * u + e2x * v
|
||||
// y = y0 + e1y * u + e2y * v
|
||||
// where 0 <= u && 0 <= v && u + v <= 1.
|
||||
//
|
||||
// We integrate u from [0,1-v] and then v from [0,1].
|
||||
// We also need to use the Jacobian of the transformation:
|
||||
// D = cross(e1, e2)
|
||||
//
|
||||
// Simplification: triangle centroid = (1/3) * (p1 + p2 + p3)
|
||||
//
|
||||
// The rest of the derivation is handled by computer algebra.
|
||||
|
||||
var count = poly.Vertices.Length;
|
||||
DebugTools.Assert(count >= 3);
|
||||
|
||||
Vector2 center = new(0.0f, 0.0f);
|
||||
float area = 0.0f;
|
||||
float I = 0.0f;
|
||||
|
||||
// Get a reference point for forming triangles.
|
||||
// Use the first vertex to reduce round-off errors.
|
||||
var s = poly.Vertices[0];
|
||||
|
||||
const float k_inv3 = 1.0f / 3.0f;
|
||||
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
// Triangle vertices.
|
||||
var e1 = poly.Vertices[i] - s;
|
||||
var e2 = i + 1 < count ? poly.Vertices[i+1] - s : poly.Vertices[0] - s;
|
||||
|
||||
float D = Vector2.Cross(e1, e2);
|
||||
|
||||
float triangleArea = 0.5f * D;
|
||||
area += triangleArea;
|
||||
|
||||
// Area weighted centroid
|
||||
center += (e1 + e2) * triangleArea * k_inv3;
|
||||
|
||||
float ex1 = e1.X, ey1 = e1.Y;
|
||||
float ex2 = e2.X, ey2 = e2.Y;
|
||||
|
||||
float intx2 = ex1*ex1 + ex2*ex1 + ex2*ex2;
|
||||
float inty2 = ey1*ey1 + ey2*ey1 + ey2*ey2;
|
||||
|
||||
I += (0.25f * k_inv3 * D) * (intx2 + inty2);
|
||||
}
|
||||
|
||||
// Total mass
|
||||
// data.Mass = density * area;
|
||||
var density = data.Mass / area;
|
||||
|
||||
// Center of mass
|
||||
DebugTools.Assert(area > float.Epsilon);
|
||||
center *= 1.0f / area;
|
||||
data.Center = center + s;
|
||||
|
||||
// Inertia tensor relative to the local origin (point s).
|
||||
data.I = density * I;
|
||||
|
||||
// Shift to center of mass then to original body origin.
|
||||
data.I += data.Mass * (Vector2.Dot(data.Center, data.Center) - Vector2.Dot(center, center));
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException($"Cannot get MassData for {shape} as it's not implemented!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ namespace Robust.UnitTesting.Shared.GameObjects.Systems
|
||||
{
|
||||
f.LoadString(Prototypes);
|
||||
})
|
||||
.RegisterDependencies(f =>
|
||||
{
|
||||
f.Register<IShapeManager, ShapeManager>();
|
||||
})
|
||||
.InitializeInstance();
|
||||
|
||||
var mapManager = sim.Resolve<IMapManager>();
|
||||
|
||||
Reference in New Issue
Block a user