//CompountShape public CompoundShape AddCompoundShape(bool enableDynamicAabbTree) { ICompoundShapeImp iCompoundImp = _dwi.AddCompoundShape(enableDynamicAabbTree); var retval = new CompoundShape(); retval.CompoundShapeImp = iCompoundImp; iCompoundImp.UserObject = retval; return retval; }
public CompoundShape GetShape() { var h = NormalizedCorners (); var shape = new CompoundShape (); var pos = World.TileSizeYVector / 2f + World.IndexToIso (Index) + World.TileSizeZVector * (MinCorner ()); shape.AddTriangle ( pos - World.TileSizeXVector / 2f + World.TileSizeZVector * h [D], pos + World.TileSizeYVector / 2f + World.TileSizeZVector * h [C] + new Vector2 (1, 0) * 0.01f, pos - World.TileSizeYVector / 2f + World.TileSizeZVector * h [A] + new Vector2 (1, 0) * 0.01f); shape.AddTriangle ( pos + World.TileSizeXVector / 2f + World.TileSizeZVector * h [B], pos + World.TileSizeYVector / 2f + World.TileSizeZVector * h [C], pos - World.TileSizeYVector / 2f + World.TileSizeZVector * h [A]); return shape; }
private void AddBodyToDrawList(RigidBody rb) { if (rb.Tag is BodyTag && ((BodyTag)rb.Tag) == BodyTag.DontDrawMe) { return; } bool isCompoundShape = (rb.Shape is CompoundShape); if (!isCompoundShape) { //GraphicsDevice.BlendState = BlendState.Opaque; //GraphicsDevice.DepthStencilState = DepthStencilState.Default; AddShapeToDrawList(rb.Shape, rb.Orientation, rb.Position); } else { //GraphicsDevice.BlendState = BlendState.Opaque; //GraphicsDevice.DepthStencilState = DepthStencilState.None; CompoundShape cShape = rb.Shape as CompoundShape; JMatrix orientation = rb.Orientation; JVector position = rb.Position; foreach (var ts in cShape.Shapes) { JVector pos = ts.Position; JMatrix ori = ts.Orientation; JVector.Transform(ref pos, ref orientation, out pos); JVector.Add(ref pos, ref position, out pos); JMatrix.Multiply(ref ori, ref orientation, out ori); AddShapeToDrawList(ts.Shape, ori, pos); } } }
public MobileChunkShape(Vector3i csize, BlockInternal[] blocks, out Vector3 center) { Matrix3x3 boxMat = new BoxShape(csize.X, csize.Y, csize.Z).VolumeDistribution; ChunkSize = csize; Blocks = blocks; double weightInv = 1f / blocks.Length; center = new Vector3(csize.X / 2f, csize.Y / 2f, csize.Z / 2f); // TODO: More accurately get center of weight based on which blocks are solid or not!? Matrix3x3 volumeDistribution = new Matrix3x3(); RigidTransform transform = new RigidTransform(center); Matrix3x3 contribution; CompoundShape.TransformContribution(ref transform, ref center, ref boxMat, blocks.Length, out contribution); Matrix3x3.Add(ref volumeDistribution, ref contribution, out volumeDistribution); Matrix3x3.Multiply(ref volumeDistribution, weightInv, out volumeDistribution); UpdateEntityShapeVolume(new EntityShapeVolumeDescription() { Volume = csize.X * csize.Y * csize.Z, VolumeDistribution = volumeDistribution }); Center = center; }
private void BuildCar() { var demo = Game as JitterDemo; var world = demo.World; var lower = new CompoundShape.TransformedShape( new BoxShape(2.5f, 1f, 6.0f), JMatrix.Identity, JVector.Zero); var upper = new CompoundShape.TransformedShape( new BoxShape(2.0f, 0.5f, 3.0f), JMatrix.Identity, (JVector.Up * 0.75f) + (JVector.Backward * 1.0f)); CompoundShape.TransformedShape[] subShapes = { lower, upper }; Shape chassis = new CompoundShape(subShapes); //chassis = new BoxShape(2.5f, 1f, 6.0f); carBody = new DefaultCar(world, chassis) { // use the inertia of the lower box. // adjust some driving values SteerAngle = 30, DriveTorque = 155, AccelerationRate = 10, SteerRate = 2f }; carBody.AdjustWheelValues(); carBody.Tag = BodyTag.DontDrawMe; carBody.AllowDeactivation = false; // place the car two units above the ground. carBody.Position = new JVector(0, 5, 0); world.AddBody(carBody); }
public Constr3DFaceExtrude(GeoObjectList selectedObjectsList) : this() { selectedMode = (selectedObjectsList != null); if (selectedMode) { GeoObjectList clonedList = selectedObjectsList.Clone(); GeoObjectList curves = new GeoObjectList(); for (int i = clonedList.Count - 1; i >= 0; --i) { if (clonedList[i] is ICurve) { curves.Add(clonedList[i]); clonedList.Remove(i); } } Plane pln; CompoundShape cs = CompoundShape.CreateFromList(curves, Precision.eps, out pln); if (cs != null && !cs.Empty) { // man konnte ein CompoundShape erzeugen, dann dieses zu Faces machen und verwenden for (int i = 0; i < cs.SimpleShapes.Length; i++) { PlaneSurface ps = new PlaneSurface(pln); Face toAdd = Face.MakeFace(ps, cs.SimpleShapes[i]); toAdd.CopyAttributes(curves[0]); clonedList.Add(toAdd); } this.selectedObjectsList = clonedList; } else { this.selectedObjectsList = selectedObjectsList.Clone(); } ListDefault(this.selectedObjectsList.Count); // setzt alle Listen auf gleiche Länge, Inhalte "null" } ; }
void Create_RbUpStack(int count) { const float mass = 10.0f; CompoundShape cylinderCompound = new CompoundShape(); CollisionShape cylinderShape = new CylinderShapeX(4, 1, 1); CollisionShape boxShape = new BoxShape(4, 1, 1); cylinderCompound.AddChildShape(Matrix.Identity, boxShape); Quaternion orn = Quaternion.RotationYawPitchRoll((float)Math.PI / 2.0f, 0.0f, 0.0f); Matrix localTransform = Matrix.RotationQuaternion(orn); //localTransform *= Matrix.Translation(new Vector3(1,1,1)); cylinderCompound.AddChildShape(localTransform, cylinderShape); CollisionShape[] shape = new CollisionShape[] { cylinderCompound, new BoxShape(new Vector3(1, 1, 1)), new SphereShape(1.5f) }; for (int i = 0; i < count; ++i) { LocalCreateRigidBody(mass, Matrix.Translation(0, 2 + 6 * i, 0), shape[i % shape.Length]); } }
void SetInnerPointInput(GeoPoint p) { if (innerPointUp) { CompoundShape shape = FindShape(p, base.ActiveDrawingPlane); if (!(shape == null)) { Face[] faces = shape.MakeFaces(base.ActiveDrawingPlane); if (faces.Length > 0) { selectedObjectsList.Clear(); base.FeedBack.ClearSelected(); base.Frame.Project.SetDefaults(faces[0]); selectedObjectsList.Add(faces[0]); // das eine in die Liste ListDefault(1); // die Listen löschen und mit "1" vorbesetzen if (makeFaceOrg()) { OnDone(); } } } } innerPointUp = false; }
/// <summary> /// Overrides IGeoObjectImpl.<see cref="IGeoObjectImpl.Modify"/> and implements IGeoObject.<see cref="IGeoObject.Modify"/>. /// </summary> /// <param name="m">see <see cref="IGeoObject.Modify"/></param> public override void Modify(ModOp m) { using (new Changing(this, "ModifyInverse", m)) { // die ModOp wird in zwei Komponente aufgeteilt: // eine Skalierungsfreie, die auf die Ebene angewendet wird // und eine Skalierung, die nochmal auf die compoundShape wirkt try { Plane newPlane = new Plane(m * plane.Location, m * plane.DirectionX, m * plane.DirectionY); // die Ebene verändert sich gemäß der Matrix m, wie verändert sich die Umrandung im 2D? // Die brutale Methode: aus den bekannten Veränderungen von 3 Punkten die Matrix bestimmen // das funktioniert, alles andere hat bislang nicht geklappt GeoPoint2D[] src = new GeoPoint2D[3]; GeoPoint2D[] dst = new GeoPoint2D[3]; src[0] = GeoPoint2D.Origin; src[1] = GeoPoint2D.Origin + GeoVector2D.XAxis; src[2] = GeoPoint2D.Origin + GeoVector2D.YAxis; dst[0] = newPlane.Project(m * plane.ToGlobal(src[0])); dst[1] = newPlane.Project(m * plane.ToGlobal(src[1])); dst[2] = newPlane.Project(m * plane.ToGlobal(src[2])); ModOp2D m2d = ModOp2D.Fit(src, dst, true); compoundShape = compoundShape.GetModified(m2d); plane = newPlane; if (m.Mode == ModOp.ModificationMode.Translation && base.Count > 0) { containedObjects.Modify(m); } else { needsRecalc = true; } } catch (PlaneException) { } // neue Ebene enthält Nullvector } }
private void btnTestCompound_Click(object sender, EventArgs e) { List <Shape> shapes = new List <Shape>(); for (int i = 0; i < 5; ++i) { var l = new Line(new PointF(10, 100 + i * 8), new PointF(245, 100 + i * 8)); shapes.Add(l); } var b = new Box(new PointF(10, 200), new PointF(230, 220)); shapes.Add(b); b.TopLeft = new PointF(-10, 200); b.BottomRight = new PointF(245, 245); var comp = new CompoundShape(); comp.AddSubShapes(shapes.ToArray()); comp.Angle = hsbAngle.Value; vbxImage.AddShape(comp); compShape = comp; }
public SurCollider(string path) { surs.Add(GetSur(path)); btCompound = new CompoundShape(); }
protected override void OnInitializePhysics() { ManifoldPoint.ContactAdded += MyContactCallback; SetupEmptyDynamicsWorld(); WavefrontObj wo = new WavefrontObj(); int tcount = wo.LoadObj("data/file.obj"); if (tcount > 0) { TriangleMesh trimesh = new TriangleMesh(); trimeshes.Add(trimesh); Vector3 localScaling = new Vector3(6, 6, 6); List <int> indices = wo.Indices; List <Vector3> vertices = wo.Vertices; int i; for (i = 0; i < tcount; i++) { int index0 = indices[i * 3]; int index1 = indices[i * 3 + 1]; int index2 = indices[i * 3 + 2]; Vector3 vertex0 = vertices[index0] * localScaling; Vector3 vertex1 = vertices[index1] * localScaling; Vector3 vertex2 = vertices[index2] * localScaling; trimesh.AddTriangle(vertex0, vertex1, vertex2); } ConvexShape tmpConvexShape = new ConvexTriangleMeshShape(trimesh); //create a hull approximation ShapeHull hull = new ShapeHull(tmpConvexShape); float margin = tmpConvexShape.Margin; hull.BuildHull(margin); tmpConvexShape.UserObject = hull; ConvexHullShape convexShape = new ConvexHullShape(); foreach (Vector3 v in hull.Vertices) { convexShape.AddPoint(v); } if (sEnableSAT) { convexShape.InitializePolyhedralFeatures(); } tmpConvexShape.Dispose(); //hull.Dispose(); CollisionShapes.Add(convexShape); float mass = 1.0f; LocalCreateRigidBody(mass, Matrix.Translation(0, 2, 14), convexShape); const bool useQuantization = true; CollisionShape concaveShape = new BvhTriangleMeshShape(trimesh, useQuantization); LocalCreateRigidBody(0, Matrix.Translation(convexDecompositionObjectOffset), concaveShape); CollisionShapes.Add(concaveShape); // Bullet Convex Decomposition FileStream outputFile = new FileStream("file_convex.obj", FileMode.Create, FileAccess.Write); StreamWriter writer = new StreamWriter(outputFile); DecompDesc desc = new DecompDesc { mVertices = wo.Vertices.ToArray(), mTcount = tcount, mIndices = wo.Indices.ToArray(), mDepth = 5, mCpercent = 5, mPpercent = 15, mMaxVertices = 16, mSkinWidth = 0.0f }; MyConvexDecomposition convexDecomposition = new MyConvexDecomposition(writer, this); desc.mCallback = convexDecomposition; // HACD Hacd myHACD = new Hacd(); myHACD.SetPoints(wo.Vertices); myHACD.SetTriangles(wo.Indices); myHACD.CompacityWeight = 0.1; myHACD.VolumeWeight = 0.0; // HACD parameters // Recommended parameters: 2 100 0 0 0 0 int nClusters = 2; const double concavity = 100; //bool invert = false; const bool addExtraDistPoints = false; const bool addNeighboursDistPoints = false; const bool addFacesPoints = false; myHACD.NClusters = nClusters; // minimum number of clusters myHACD.VerticesPerConvexHull = 100; // max of 100 vertices per convex-hull myHACD.Concavity = concavity; // maximum concavity myHACD.AddExtraDistPoints = addExtraDistPoints; myHACD.AddNeighboursDistPoints = addNeighboursDistPoints; myHACD.AddFacesPoints = addFacesPoints; myHACD.Compute(); nClusters = myHACD.NClusters; myHACD.Save("output.wrl", false); if (true) { CompoundShape compound = new CompoundShape(); CollisionShapes.Add(compound); Matrix trans = Matrix.Identity; for (int c = 0; c < nClusters; c++) { //generate convex result Vector3[] points; int[] triangles; myHACD.GetCH(c, out points, out triangles); ConvexResult r = new ConvexResult(points, triangles); convexDecomposition.ConvexDecompResult(r); } for (i = 0; i < convexDecomposition.convexShapes.Count; i++) { Vector3 centroid = convexDecomposition.convexCentroids[i]; trans = Matrix.Translation(centroid); ConvexHullShape convexShape2 = convexDecomposition.convexShapes[i] as ConvexHullShape; compound.AddChildShape(trans, convexShape2); RigidBody body = LocalCreateRigidBody(1.0f, trans, convexShape2); } #if true mass = 10.0f; trans = Matrix.Translation(-convexDecompositionObjectOffset); RigidBody body2 = LocalCreateRigidBody(mass, trans, compound); body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback; convexDecompositionObjectOffset.Z = 6; trans = Matrix.Translation(-convexDecompositionObjectOffset); body2 = LocalCreateRigidBody(mass, trans, compound); body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback; convexDecompositionObjectOffset.Z = -6; trans = Matrix.Translation(-convexDecompositionObjectOffset); body2 = LocalCreateRigidBody(mass, trans, compound); body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback; #endif } writer.Dispose(); outputFile.Dispose(); } }
//---------------------------------------------------------------------------------------------------------------- public override void InitializeDemo() { CollisionShape groundShape = new BoxShape(new IndexedVector3(50, 3, 50)); //CollisionShape groundShape = new StaticPlaneShape(IndexedVector3.Up, 0f); m_collisionShapes.Add(groundShape); m_collisionConfiguration = new DefaultCollisionConfiguration(); m_dispatcher = new CollisionDispatcher(m_collisionConfiguration); IndexedVector3 worldMin = new IndexedVector3(-1000, -1000, -1000); IndexedVector3 worldMax = new IndexedVector3(1000, 1000, 1000); //m_broadphase = new AxisSweep3Internal(ref worldMin, ref worldMax, 0xfffe, 0xffff, 16384, null, false); m_broadphase = new SimpleBroadphase(100, null); m_constraintSolver = new SequentialImpulseConstraintSolver(); m_dynamicsWorld = new DiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_constraintSolver, m_collisionConfiguration); //m_dynamicsWorld.setGravity(new IndexedVector3(0,0,0)); IndexedMatrix tr = IndexedMatrix.CreateTranslation(0, -10, 0); //either use heightfield or triangle mesh //create ground object LocalCreateRigidBody(0f, ref tr, groundShape); CollisionShape chassisShape = new BoxShape(new IndexedVector3(1.0f, 0.5f, 2.0f)); m_collisionShapes.Add(chassisShape); CompoundShape compound = new CompoundShape(); m_collisionShapes.Add(compound); //localTrans effectively shifts the center of mass with respect to the chassis IndexedMatrix localTrans = IndexedMatrix.CreateTranslation(0, 1, 0); compound.AddChildShape(ref localTrans, chassisShape); { CollisionShape suppShape = new BoxShape(new IndexedVector3(0.5f, 0.1f, 0.5f)); //localTrans effectively shifts the center of mass with respect to the chassis IndexedMatrix suppLocalTrans = IndexedMatrix.CreateTranslation(0f, 1.0f, 2.5f); compound.AddChildShape(ref suppLocalTrans, suppShape); } tr._origin = IndexedVector3.Zero; m_carChassis = LocalCreateRigidBody(800f, ref tr, compound);//chassisShape); //m_carChassis = LocalCreateRigidBody(800f, ref tr, chassisShape);//chassisShape); //CollisionShape liftShape = new BoxShape(new IndexedVector3(0.5f, 2.0f, 0.05f)); //m_collisionShapes.Add(liftShape); //m_liftStartPos = new IndexedVector3(0.0f, 2.5f, 3.05f); //IndexedMatrix liftTrans = IndexedMatrix.CreateTranslation(m_liftStartPos); //m_liftBody = LocalCreateRigidBody(10f, ref liftTrans, liftShape); //IndexedMatrix localA = MathUtil.SetEulerZYX(0f, MathUtil.SIMD_HALF_PI, 0f); //localA._origin = new IndexedVector3(0f, 1.0f, 3.05f); //IndexedMatrix localB = MathUtil.SetEulerZYX(0f, MathUtil.SIMD_HALF_PI, 0f); //localB._origin = new IndexedVector3(0f, -1.5f, -0.05f); //m_liftHinge = new HingeConstraint(m_carChassis, m_liftBody, ref localA, ref localB); //// m_liftHinge.setLimit(-LIFT_EPS, LIFT_EPS); //m_liftHinge.SetLimit(0.0f, 0.0f); //m_dynamicsWorld.AddConstraint(m_liftHinge, true); //CompoundShape forkCompound = new CompoundShape(); //m_collisionShapes.Add(forkCompound); //IndexedMatrix forkLocalTrans = IndexedMatrix.Identity; //CollisionShape forkShapeA = new BoxShape(new IndexedVector3(1.0f, 0.1f, 0.1f)); //m_collisionShapes.Add(forkShapeA); //forkCompound.AddChildShape(ref forkLocalTrans, forkShapeA); //CollisionShape forkShapeB = new BoxShape(new IndexedVector3(0.1f, 0.02f, 0.6f)); //m_collisionShapes.Add(forkShapeB); //forkLocalTrans = IndexedMatrix.CreateTranslation(-0.9f, -0.08f, 0.7f); //forkCompound.AddChildShape(ref forkLocalTrans, forkShapeB); //CollisionShape forkShapeC = new BoxShape(new IndexedVector3(0.1f, 0.02f, 0.6f)); //m_collisionShapes.Add(forkShapeC); //forkLocalTrans = IndexedMatrix.CreateTranslation(0.9f, -0.08f, 0.7f); //forkCompound.AddChildShape(ref forkLocalTrans, forkShapeC); //m_forkStartPos = new IndexedVector3(0.0f, 0.6f, 3.2f); //IndexedMatrix forkTrans = IndexedMatrix.CreateTranslation(m_forkStartPos); //m_forkBody = LocalCreateRigidBody(5f, ref forkTrans, forkCompound); //localA = MathUtil.SetEulerZYX(0f, 0f, MathUtil.SIMD_HALF_PI); //localA._origin = new IndexedVector3(0.0f, -1.9f, 0.05f); //IndexedVector3 col0 = MathUtil.matrixColumn(ref localA, 0); //IndexedVector3 col1 = MathUtil.matrixColumn(ref localA, 1); //IndexedVector3 col2 = MathUtil.matrixColumn(ref localA, 2); ////localB = MathUtil.setEulerZYX(0f, 0f, MathUtil.SIMD_HALF_PI); //localB = MathUtil.SetEulerZYX(0f, 0f, MathUtil.SIMD_HALF_PI); //localB._origin = new IndexedVector3(0.0f, 0.0f, -0.1f); //m_forkSlider = new SliderConstraint(m_liftBody, m_forkBody, ref localA, ref localB, true); //m_forkSlider.SetLowerLinLimit(0.1f); //m_forkSlider.SetUpperLinLimit(0.1f); //// m_forkSlider.setLowerAngLimit(-LIFT_EPS); //// m_forkSlider.setUpperAngLimit(LIFT_EPS); //m_forkSlider.SetLowerAngLimit(0.0f); //m_forkSlider.SetUpperAngLimit(0.0f); //IndexedMatrix localAVec = IndexedMatrix.Identity; //IndexedMatrix localBVec = IndexedMatrix.Identity; //m_forkSlider2 = new HingeConstraint(m_liftBody, m_forkBody, ref localAVec, ref localBVec); //m_dynamicsWorld.AddConstraint(m_forkSlider, true); //m_dynamicsWorld.addConstraint(m_forkSlider2, true); CompoundShape loadCompound = new CompoundShape(true); m_collisionShapes.Add(loadCompound); CollisionShape loadShapeA = new BoxShape(new IndexedVector3(2.0f, 0.5f, 0.5f)); m_collisionShapes.Add(loadShapeA); IndexedMatrix loadTrans = IndexedMatrix.Identity; loadCompound.AddChildShape(ref loadTrans, loadShapeA); CollisionShape loadShapeB = new BoxShape(new IndexedVector3(0.1f, 1.0f, 1.0f)); m_collisionShapes.Add(loadShapeB); loadTrans = IndexedMatrix.CreateTranslation(2.1f, 0.0f, 0.0f); loadCompound.AddChildShape(ref loadTrans, loadShapeB); CollisionShape loadShapeC = new BoxShape(new IndexedVector3(0.1f, 1.0f, 1.0f)); m_collisionShapes.Add(loadShapeC); loadTrans = IndexedMatrix.CreateTranslation(-2.1f, 0.0f, 0.0f); loadCompound.AddChildShape(ref loadTrans, loadShapeC); m_loadStartPos = new IndexedVector3(0.0f, -3.5f, 7.0f); loadTrans = IndexedMatrix.CreateTranslation(m_loadStartPos); m_loadBody = LocalCreateRigidBody(4f, ref loadTrans, loadCompound); #if false { CollisionShape liftShape = new BoxShape(new IndexedVector3(0.5f, 2.0f, 0.05f)); m_collisionShapes.Add(liftShape); IndexedMatrix liftTrans = IndexedMatrix.CreateTranslation(m_liftStartPos); m_liftBody = localCreateRigidBody(10f, ref liftTrans, liftShape); IndexedMatrix localA = MathUtil.setEulerZYX(0f, MathUtil.SIMD_HALF_PI, 0f); localA._origin = new IndexedVector3(0f, 1.0f, 3.05f); IndexedMatrix localB = MathUtil.setEulerZYX(0f, MathUtil.SIMD_HALF_PI, 0f); localB._origin = new IndexedVector3(0f, -1.5f, -0.05f); m_liftHinge = new HingeConstraint(m_carChassis, m_liftBody, ref localA, ref localB); // m_liftHinge.setLimit(-LIFT_EPS, LIFT_EPS); m_liftHinge.setLimit(0.0f, 0.0f); m_dynamicsWorld.addConstraint(m_liftHinge, true); CollisionShape forkShapeA = new BoxShape(new IndexedVector3(1.0f, 0.1f, 0.1f)); m_collisionShapes.Add(forkShapeA); CompoundShape forkCompound = new CompoundShape(); m_collisionShapes.Add(forkCompound); IndexedMatrix forkLocalTrans = IndexedMatrix.Identity; forkCompound.addChildShape(ref forkLocalTrans, forkShapeA); CollisionShape forkShapeB = new BoxShape(new IndexedVector3(0.1f, 0.02f, 0.6f)); m_collisionShapes.Add(forkShapeB); forkLocalTrans = IndexedMatrix.CreateTranslation(-0.9f, -0.08f, 0.7f); forkCompound.addChildShape(ref forkLocalTrans, forkShapeB); CollisionShape forkShapeC = new BoxShape(new IndexedVector3(0.1f, 0.02f, 0.6f)); m_collisionShapes.Add(forkShapeC); forkLocalTrans = IndexedMatrix.CreateTranslation(0.9f, -0.08f, 0.7f); forkCompound.addChildShape(ref forkLocalTrans, forkShapeC); m_forkStartPos = new IndexedVector3(0.0f, 0.6f, 3.2f); IndexedMatrix forkTrans = IndexedMatrix.CreateTranslation(m_forkStartPos); m_forkBody = localCreateRigidBody(5f, ref forkTrans, forkCompound); localA = MathUtil.setEulerZYX(0f, 0f, MathUtil.SIMD_HALF_PI); localA._origin = new IndexedVector3(0.0f, -1.9f, 0.05f); localB = MathUtil.setEulerZYX(0f, 0f, MathUtil.SIMD_HALF_PI); localB._origin = new IndexedVector3(0.0f, 0.0f, -0.1f); m_forkSlider = new SliderConstraint(m_liftBody, m_forkBody, ref localA, ref localB, true); m_forkSlider.setLowerLinLimit(0.1f); m_forkSlider.setUpperLinLimit(0.1f); // m_forkSlider.setLowerAngLimit(-LIFT_EPS); // m_forkSlider.setUpperAngLimit(LIFT_EPS); m_forkSlider.setLowerAngLimit(0.0f); m_forkSlider.setUpperAngLimit(0.0f); m_dynamicsWorld.addConstraint(m_forkSlider, true); CompoundShape loadCompound = new CompoundShape(); m_collisionShapes.Add(loadCompound); CollisionShape loadShapeA = new BoxShape(new IndexedVector3(2.0f, 0.5f, 0.5f)); m_collisionShapes.Add(loadShapeA); IndexedMatrix loadTrans = IndexedMatrix.Identity; loadCompound.addChildShape(ref loadTrans, loadShapeA); CollisionShape loadShapeB = new BoxShape(new IndexedVector3(0.1f, 1.0f, 1.0f)); m_collisionShapes.Add(loadShapeB); loadTrans = IndexedMatrix.CreateTranslation(2.1f, 0.0f, 0.0f); loadCompound.addChildShape(ref loadTrans, loadShapeB); CollisionShape loadShapeC = new BoxShape(new IndexedVector3(0.1f, 1.0f, 1.0f)); m_collisionShapes.Add(loadShapeC); loadTrans = IndexedMatrix.CreateTranslation(-2.1f, 0.0f, 0.0f); loadCompound.addChildShape(ref loadTrans, loadShapeC); m_loadStartPos = new IndexedVector3(0.0f, -3.5f, 7.0f); loadTrans = IndexedMatrix.CreateTranslation(m_loadStartPos); m_loadBody = localCreateRigidBody(4f, ref loadTrans, loadCompound); } #endif //m_carChassis.setDamping(0.2f, 0.2f); ClientResetScene(); /// create vehicle SetCameraDistance(26.0f); SetTexturing(true); SetShadows(true); }
public Character(DiscreteDynamicsWorld world, Vehiculo vehiculo, TGCVector3 position, float rotation, GameModel gameModel) { //Cargar sonido turboSound = new TgcStaticSound(); turboSound.loadSound(Game.Default.MediaDirectory + Game.Default.FXDirectory + "turbo.wav", gameModel.DirectSound.DsDevice); this.vehiculo = vehiculo; var loader = new TgcSceneLoader(); this.mesh = loader.loadSceneFromFile(vehiculo.ChassisXmlPath).Meshes[0]; this.wheel = loader.loadSceneFromFile(vehiculo.WheelsXmlPath).Meshes[0]; Vehiculo.ChangeTextureColor(this.mesh, vehiculo.Color); this.mesh.AutoTransform = false; this.wheel.AutoTransform = false; maxHitPoints = float.Parse(mesh.UserProperties["maxHitPoints"], CultureInfo.InvariantCulture); engineForce = -float.Parse(mesh.UserProperties["engineForce"], CultureInfo.InvariantCulture); brakeForce = float.Parse(mesh.UserProperties["brakeForce"], CultureInfo.InvariantCulture); steeringAngle = -float.Parse(mesh.UserProperties["steeringAngle"], CultureInfo.InvariantCulture); turboImpulse = float.Parse(mesh.UserProperties["turboImpulse"], CultureInfo.InvariantCulture); frictionSlip = float.Parse(mesh.UserProperties["frictionSlip"], CultureInfo.InvariantCulture); rollInfluence = float.Parse(mesh.UserProperties["rollInfluence"], CultureInfo.InvariantCulture); rearWheelsHeight = float.Parse(mesh.UserProperties["rearWheelsHeight"], CultureInfo.InvariantCulture); frontWheelsHeight = float.Parse(mesh.UserProperties["frontWheelsHeight"], CultureInfo.InvariantCulture); suspensionRestLength = float.Parse(mesh.UserProperties["suspensionRestLength"], CultureInfo.InvariantCulture); suspensionStiffness = float.Parse(mesh.UserProperties["suspensionStiffness"], CultureInfo.InvariantCulture); dampingCompression = float.Parse(mesh.UserProperties["dampingCompression"], CultureInfo.InvariantCulture); dampingRelaxation = float.Parse(mesh.UserProperties["dampingRelaxation"], CultureInfo.InvariantCulture); meshAxisRadius = this.mesh.BoundingBox.calculateAxisRadius().ToBsVector; var wheelRadius = this.wheel.BoundingBox.calculateAxisRadius().Y; //The btBoxShape is centered at the origin CollisionShape chassisShape = new BoxShape(meshAxisRadius.X, meshRealHeight, meshAxisRadius.Z); //A compound shape is used so we can easily shift the center of gravity of our vehicle to its bottom //This is needed to make our vehicle more stable CompoundShape compound = new CompoundShape(); //The center of gravity of the compound shape is the origin. When we add a rigidbody to the compound shape //it's center of gravity does not change. This way we can add the chassis rigidbody one unit above our center of gravity //keeping it under our chassis, and not in the middle of it var localTransform = Matrix.Translation(0, (meshAxisRadius.Y * 1.75f) - (meshRealHeight / 2f), 0); compound.AddChildShape(localTransform, chassisShape); //Creates a rigid body this.rigidBody = CreateChassisRigidBodyFromShape(compound, position, rotation); //Adds the vehicle chassis to the world world.AddRigidBody(this.rigidBody); worldID = world.CollisionObjectArray.IndexOf(this.rigidBody); //RaycastVehicle DefaultVehicleRaycaster vehicleRayCaster = new DefaultVehicleRaycaster(world); VehicleTuning tuning = new VehicleTuning(); //Creates a new instance of the raycast vehicle vehicle = new RaycastVehicle(tuning, this.rigidBody, vehicleRayCaster); //Never deactivate the vehicle this.rigidBody.ActivationState = ActivationState.DisableDeactivation; //Adds the vehicle to the world world.AddAction(vehicle); //Adds the wheels to the vehicle AddWheels(meshAxisRadius, vehicle, tuning, wheelRadius); //Inicializo puntos hitPoints = maxHitPoints; specialPoints = maxSpecialPoints; timerMachineGun = 0f; }
internal CompoundChild(CompoundShape shape, EntityCollidable collisionInformation, int index) { this.shape = shape; this.collisionInformation = collisionInformation; this.shapeIndex = index; }
//[Import()] //VVVV. FLog; public void Evaluate(int SpreadMax) { if (this.FBodies.PluginIO.IsConnected) { this.FId.SliceCount = this.FBodies.SliceCount; this.FPosition.SliceCount = this.FBodies.SliceCount; this.FRotation.SliceCount = this.FBodies.SliceCount; this.FShapes.SliceCount = this.FBodies.SliceCount; this.FCustom.SliceCount = this.FBodies.SliceCount; this.FIsNew.SliceCount = this.FBodies.SliceCount; this.FLinVel.SliceCount = this.FBodies.SliceCount; this.FAngVel.SliceCount = this.FBodies.SliceCount; this.FActive.SliceCount = this.FBodies.SliceCount; this.FContactResponse.SliceCount = this.FBodies.SliceCount; this.FStatic.SliceCount = this.FBodies.SliceCount; this.FKinematic.SliceCount = this.FBodies.SliceCount; this.FShapeTransform.SliceCount = this.FBodies.SliceCount; this.FHasCustomObj.SliceCount = this.FBodies.SliceCount; this.FCustomObj.SliceCount = this.FBodies.SliceCount; List <Matrix4x4> transforms = new List <Matrix4x4>(); for (int i = 0; i < SpreadMax; i++) { RigidBody body = this.FBodies[i]; this.FPosition[i] = new Vector3D(body.MotionState.WorldTransform.M41, body.MotionState.WorldTransform.M42, body.MotionState.WorldTransform.M43); Quaternion rot = body.Orientation; this.FRotation[i] = new Vector4D(rot.X, rot.Y, rot.Z, rot.W); this.FLinVel[i] = body.LinearVelocity.ToVVVVector(); this.FAngVel[i] = body.AngularVelocity.ToVVVVector(); CollisionShape shape = body.CollisionShape; if (shape.IsCompound) { //CompoundShape sp = new CompoundShape( CompoundShape comp = (CompoundShape)shape; this.FShapes[i].SliceCount = comp.NumChildShapes; this.FShapeTransform[i].SliceCount = comp.NumChildShapes; for (int j = 0; j < comp.NumChildShapes; j++) { CollisionShape child = comp.GetChildShape(j); this.FShapes[i][j] = child; Matrix m = comp.GetChildTransform(j); Matrix4x4 mn = new Matrix4x4(m.M11, m.M12, m.M13, m.M14, m.M21, m.M22, m.M23, m.M24, m.M31, m.M32, m.M33, m.M34, m.M41, m.M42, m.M43, m.M44); mn *= VMath.Scale(child.LocalScaling.ToVVVVector()); this.FShapeTransform[i][j] = mn; //comp. //comp.GetChildTransform( //this.FShapes[i][j]. } } else { this.FShapes[i].SliceCount = 1; this.FShapes[i][0] = shape; this.FShapeTransform[i].SliceCount = 1; this.FShapeTransform[i][0] = VMath.Scale(shape.LocalScaling.ToVVVVector()); //transforms.Add(VMath.IdentityMatrix); } BodyCustomData bd = (BodyCustomData)body.UserObject; ShapeCustomData sc = (ShapeCustomData)shape.UserObject; this.FActive[i] = body.IsActive; this.FContactResponse[i] = body.HasContactResponse; this.FStatic[i] = body.IsStaticObject; this.FKinematic[i] = body.IsKinematicObject; //this.FShapeCount[i] = sc.ShapeDef.ShapeCount; this.FId[i] = bd.Id; this.FIsNew[i] = bd.Created; this.FCustom[i] = bd.Custom; if (bd.CustomObject != null) { this.FHasCustomObj[i] = true; this.FCustomObj[i] = bd.CustomObject; } else { this.FHasCustomObj[i] = false; this.FCustomObj[i] = null; } } //this.FShapeTransform.SliceCount = transforms.Count; //this.FShapeTransform.AssignFrom(transforms); } else { this.FId.SliceCount = 0; this.FPosition.SliceCount = 0; this.FRotation.SliceCount = 0; this.FShapes.SliceCount = 0; this.FCustom.SliceCount = 0; this.FIsNew.SliceCount = 0; this.FLinVel.SliceCount = 0; this.FAngVel.SliceCount = 0; this.FShapeTransform.SliceCount = 0; } }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public EntityConstructionDemo(DemosGame game) : base(game) { //An entity is the basic physical simulation object in BEPUphysics. It represents a rigid body which can be dynamic or kinematic. //Dynamic objects can bounce around and respond to collisions using forces. Kinematic entities can move using velocity, //but effectively have infinite inertia and do not respond to collisions or forces. //For each of the below constructors, there are multiple overloads. Half have a mass parameter, half do not. If a mass parameter is specified, //the object is created as a dynamic object. If a mass parameter is not specified, it is created as a kinematic object. This state can be changed later //by using the BecomeDynamic/BecomeKinematic methods. //************************ //There are a variety of ways to construct entities depending on your needs. //The most common approach is to use the 'prefab' types, like the Box, Sphere, ConvexHull, Cylinder, and so on (BEPUphysics.Entities.Prefabs namespace). //These provide a short cut to constructing the objects and generally provide convenience accessors to shape properties. //We'll start with such an entity for the kinematic ground. Notice how it allows the definition of position and shape data all in the constructor. //It has other overloads that allow you to specify a mass (for a dynamic object) or a full MotionState instead of just a position. Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); Space.Add(ground); //If you examine the ground's CollisionInformation property, you'll find that it is a generic method which returns a ConvexCollidable<BoxShape>. //So, in addition to having convenience properties, it also lets you go deeper into the object's data by knowing what the types are. //************************ //Let's go one level up the hierarchy to Entity<T>. This is the superclass of all prefab types. //The generic parameter is the type of the Collidable that the entity uses as its collision proxy. //It is also what allows prefab types' CollisionInformation property to return that type rather than EntityCollidable. Space.Add(new Entity <ConvexCollidable <SphereShape> >(new ConvexCollidable <SphereShape>(new SphereShape(1)), 1) { Position = new Vector3(-10, 1, 0) }); //That's a bit unwieldy<<>><>, but it works. Directly constructing entities in this manner isn't common or generally necessary. //If you want to have a CollisionInformation property that returns a specific type but don't want to use a specific prefab type, this is the way to go. //Note that the constructor itself does not include any position/motion state parameters nor does it include any direct shape data. The position and other auxiliary //properties can be set after it's been constructed. In this case, object initializer syntax is used to set the Position. //The shape data is included within the first EntityCollidable parameter which defines the entity's collision proxy. //The prefab types discussed previously all create such EntityCollidables internally using the data passed into the constructor. //************************ //So let's move onto something a little more convenient. Entity<T> has a non-generic parent Entity. It still has a CollisionInformation property, //but it returns an EntityCollidable rather than a specific type. Space.Add(new Entity(new BoxShape(2, 2, 2), 1) { Position = new Vector3(10, 1, 0) }); //Much better! No more ugly generic type syntax pollution. Notice that there are quite a few overloads in the Entity. //In addition to overloads that accept EntityCollidable instances (as used in the generic entity above), Entity provides constructors that //take shapes directly. Internally, the entity can create its own EntityCollidable instance based on the shape. This further simplifies the construction process. //An object initializer is once again used to set the position, since the constructors do not have all the convenience constructor frills of the prefab types. //************************ //All of the above entity types have read-only CollisionInformation properties. Once an entity of those types is created, it cannot change its fundamental shape. //A sphere may get bigger or smaller, but a sphere entity couldn't become a box entity. //That's where the MorphableEntity comes in. var morphable = new MorphableEntity(new CylinderShape(2, 1), 1) { Position = new Vector3(10, 3, 0) }; Space.Add(morphable); //It is constructed identically to its parent Entity class, but after being created, the EntityCollidable it uses can change! morphable.CollisionInformation = new ConvexCollidable <ConeShape>(new ConeShape(2, 1)); //That's neat, but that collidable constructor with generic type is a bit ugly. We don't care about doing any type-specific configuration //on the EntityCollidable itself, so we can just tell the shape to make us an EntityCollidable instance. This is what the Entity/MorphableEntity constructors //do internally when given an EntityShape instead of an EntityCollidable (which in turn contains an EntityShape). morphable.CollisionInformation = new ConeShape(2, 1).GetCollidableInstance(); //While this is arguably a bit prettier, its major benefit comes from the fact that you don't need to know the type of the shape to call GetCollidableInstance. //If it's an EntityShape, it can create an EntityCollidable for itself. //************************ //That's it for the different types of entities. Another very useful technique is to share shapes and initialization between entities. //Re-using convex hulls is a common use case. They have a fairly expensive initialization, and they tend to be some of the larger shapes memory-wise. //Rather than having a thousand redundant copies of identical geometry, one shape can be made and reused for subsequent entities. //First, create the pointset that composes the convex hull. var vertices = new[] { new Vector3(-1, 0, -1), new Vector3(-1, 0, 1), new Vector3(1, 0, -1), new Vector3(1, 0, 1), new Vector3(0, 2, 0) }; //Construct the shape itself. var convexHullShape = new ConvexHullShape(vertices); //Create an entity using the shape. var convexHull = new Entity(convexHullShape, 2) { Position = new Vector3(0, 1, 0) }; Space.Add(convexHull); //Create a bunch of other shapes using that first shape's properties. //Instead of using a first entity's data, this could also be pulled in from some external source (deserialized save data or something). for (int i = 1; i <= 10; i++) { Space.Add(new Entity(convexHullShape, convexHull.Mass, convexHull.LocalInertiaTensor) { Position = new Vector3(0, 1 + i * 3, 0) }); } //In older versions, initializing the entity was a little expensive if the inertia tensor and some other data wasn't provided. //These days, the cost is done once in the shape and the entity initialization is pretty much always super cheap. //So, you don't need to share inertia tensors for performance reasons. //************************ //All convex shapes are centered on their local origin. If you create a box entity and assign its position to (0,1,0), the box shape's center will end up at (0,1,0). //For simple shapes like the box, that's always the case without doing any work just based on the definition of the shape. //More complicated shapes, like the ConvexHullShape, can be constructed from data which is not initially centered around the origin. For example, consider these vertices: vertices = new[] { new Vector3(-5, 15, -1), new Vector3(-5, 15, 1), new Vector3(-3, 15, -1), new Vector3(-3, 15, 1), new Vector3(-4, 17, 0), new Vector3(-4, 13, 0) }; //The center of those points is obviously going to be very far from the origin. //When we construct a ConvexHullShape, the points get 'recentered.' convexHullShape = new ConvexHullShape(vertices); //If you look at the convexHullShape.Vertices list, you'll see that the points are relative to a local origin now. //So now it's centered on the local origin, as was needed. But there's a problem- what if you wanted your convex hull entity to end up at the original vertex positions? //To get it there, we need to know the offset from the original vertices to the local vertices. //Fortunately, there is a constructor overload which provides it! Vector3 center; convexHullShape = new ConvexHullShape(vertices, out center); //Now, when the entity is created, we can position it at the original point's center. The shape still contains local data, but the entity's location ends up putting the shape in the right spot. convexHull = new Entity(convexHullShape, 2) { Position = center }; Space.Add(convexHull); //************************ //Compound bodies are unique in that they allow you to specify groups of shapes to create a concave shape. //Here's the common simple approach to making a compound body, using a prefab type for now. CompoundBody body = new CompoundBody(new List <CompoundShapeEntry> { new CompoundShapeEntry(new BoxShape(1, 1, 1), new Vector3(-7, 3, 8), 1), new CompoundShapeEntry(new BoxShape(1, 3, 1), new Vector3(-8, 2, 8), 5), new CompoundShapeEntry(new BoxShape(1, 1, 1), new Vector3(-9, 1, 8), 1) }, 10); Space.Add(body); //Each entry has a shape, a rigid transform (orientation and/or translation), and a weight. //The rigid transform defines the position of the shape in world space. They will be recentered into local space within the CompoundShape itself (see previous convex hull example). //The 'weight' parameter does not correspond directly to mass, but rather to the contribution of that shape to the whole relative to other shapes. //It used to compute the center position of the shape. When used by a dynamic entity, it is also used to compute a proper inertia tensor. The resulting inertia tensor is scaled by the entity's actual mass. //************************ //Just like shapes can be shared between entities, you can re-use a shape for multiple entries within a compound body. var compoundShape = new CompoundShape(new List <CompoundShapeEntry> { new CompoundShapeEntry(convexHullShape, new Vector3(7, 3, 8), 1), new CompoundShapeEntry(convexHullShape, new RigidTransform(new Vector3(8, 2, 8), Quaternion.CreateFromAxisAngle(Vector3.Forward, MathHelper.PiOver2)), 5), new CompoundShapeEntry(convexHullShape, new Vector3(9, 1, 8), 1) }); //And just like normal convex shapes can be shared, so can compound shapes! for (int i = 0; i < 3; i++) { Space.Add(new Entity(compoundShape, 10) { Position = new Vector3(8, 10 + i * 4, 8) }); } //************************ //You can also use compound shapes as subshapes, creating nested compounds. Space.Add(new Entity(new CompoundShape(new List <CompoundShapeEntry> { new CompoundShapeEntry(compoundShape, new Vector3(7, 5, 8), 1), new CompoundShapeEntry(compoundShape, new Vector3(9, 1, 8), 1) }), 10) { Position = new Vector3(8, 25, 8) }); //************************ //Sometimes, it's nice to be able to change how subshapes behave. //This example will use a prefab CompoundBody type, but note that there exists a CompoundCollidable that can be constructed independently as well. //Just like a list of CompoundShapeEntry objects can be used to construct a compound object, a list of CompoundChildData objects can too. //CompoundChildData objects contain CompoundShapeEntry objects as well as other data to be used by a Collidable instance. //That extra data includes material, events, and collision rules. var compoundBody = new CompoundBody(new List <CompoundChildData> { new CompoundChildData { Entry = new CompoundShapeEntry(new CylinderShape(1, 1), new Vector3(0, 2, 8)), CollisionRules = new CollisionRules { Personal = CollisionRule.NoBroadPhase } }, new CompoundChildData { Entry = new CompoundShapeEntry(new BoxShape(3, 1, 3), new Vector3(0, 1, 8)), Material = new Material(3, 3, 0) } }, 10); Space.Add(compoundBody); //In this example, one of the two blocks doesn't collide with anything. The other does collide, and has a very high friction material. //************************ //While sharing shapes can help reduce load times, sometimes it's useful to eliminate the shape's initialization cost too. //For this purpose, all shapes have a constructor which takes a bunch of data that fully defines the shape. //The constructor assumes that all of it is correct; it won't catch any errors or do any additional preprocessing. //For example, let's construct a ConvexHullShape from the our earlier ConvexHullShape. //We'll need a ConvexShapeDescription that defines the data common to all convex shapes. var shapeDescription = new ConvexShapeDescription { CollisionMargin = convexHullShape.CollisionMargin, MinimumRadius = convexHullShape.MinimumRadius, MaximumRadius = convexHullShape.MaximumRadius, EntityShapeVolume = new EntityShapeVolumeDescription { Volume = convexHullShape.Volume, VolumeDistribution = convexHullShape.VolumeDistribution } }; //Now, along with the surface vertices from the previous shape, the new shape can be created: var shapeFromCachedData = new ConvexHullShape(convexHullShape.Vertices, shapeDescription); //Usually, the data for these constructors will come from some cache or storage. For example, //a game could store out the above information to disk from a content development tool. //At load time, the matching shape can be created at virtually no cost. //Stuff the shape into the world! Space.Add(new Entity(shapeFromCachedData, 10) { Position = new Vector3(-10, 5, -5) }); Game.Camera.Position = new Vector3(0, 3, 25); }
public override void Evaluate(int SpreadMax) { for (int i = 0; i < SpreadMax; i++) { if (this.CanCreate(i)) { wheelRadius = FwheelRadius[0]; wheelWidth = FwheelWidth[0]; CUBE_HALF_EXTENTS = FwheelDistance[0]; RaycastVehicle vehicle; AbstractRigidShapeDefinition shapedef = this.FShapes[i]; ShapeCustomData sc = new ShapeCustomData(); sc.ShapeDef = shapedef; CompoundShape compound = new CompoundShape(); CollisionShape chassisShape = shapedef.GetShape(sc); Matrix localTrans = Matrix.Translation(Vector3.UnitY); compound.AddChildShape(localTrans, chassisShape); float mass = shapedef.Mass; bool isDynamic = (mass != 0.0f); isFrontWheel = true; Vector3 localInertia = Vector3.Zero; if (isDynamic) { chassisShape.CalculateLocalInertia(mass, out localInertia); } Vector3D pos = this.FPosition[i]; Vector4D rot = this.FRotation[i]; DefaultMotionState ms = BulletUtils.CreateMotionState(pos.x, pos.y, pos.z, rot.x, rot.y, rot.z, rot.w); RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, ms, compound, localInertia); RigidBody carChassis = new RigidBody(rbInfo); BodyCustomData bd = new BodyCustomData(); carChassis.UserObject = bd; bd.Id = this.FWorld[0].GetNewBodyId(); bd.Custom = this.FCustom[i]; this.FWorld[0].Register(carChassis); RaycastVehicle.VehicleTuning tuning = new RaycastVehicle.VehicleTuning(); VehicleRaycaster vehicleRayCaster = new DefaultVehicleRaycaster(this.FWorld[0].World); vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster); carChassis.ActivationState = ActivationState.DisableDeactivation; this.FWorld[0].World.AddAction(vehicle); // choose coordinate system vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex); Vector3 connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), FconnectionHeight[0], 2 * CUBE_HALF_EXTENTS - wheelRadius); WheelInfo a = vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, FsuspensionRestLength[0], wheelRadius, tuning, isFrontWheel); connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), FconnectionHeight[0], 2 * CUBE_HALF_EXTENTS - wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, FsuspensionRestLength[0], wheelRadius, tuning, isFrontWheel); isFrontWheel = false; connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), FconnectionHeight[0], -2 * CUBE_HALF_EXTENTS + wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, FsuspensionRestLength[0], wheelRadius, tuning, isFrontWheel); connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), FconnectionHeight[0], -2 * CUBE_HALF_EXTENTS + wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, FsuspensionRestLength[0], wheelRadius, tuning, isFrontWheel); for (i = 0; i < vehicle.NumWheels; i++) { WheelInfo wheel = vehicle.GetWheelInfo(i); wheel.SuspensionStiffness = FsuspensionStiffness[0]; wheel.WheelDampingRelaxation = FDampingRelaxation[0]; wheel.WheelDampingCompression = FDampingCompression[0]; wheel.FrictionSlip = FwheelFriction[0]; wheel.RollInfluence = FrollInfluence[0]; wheel.MaxSuspensionTravelCm = FmaxSuspensionTravelCm[0]; wheel.MaxSuspensionForce = FmaxSuspensionForce[0]; } FOutVehicle.SliceCount = 1; FOutVehicle[0] = vehicle; } } }
/// <summary> /// Splits a single compound collidable into two separate compound collidables and computes information needed by the simulation. /// </summary> /// <param name="childContributions">List of distribution information associated with each child shape of the whole compound shape used by the compound being split.</param> /// <param name="splitPredicate">Delegate which determines if a child in the original compound should be moved to the new compound.</param> /// <param name="a">Original compound to be split. Children in this compound will be removed and added to the other compound.</param> /// <param name="b">Compound to receive children removed from the original compound.</param> /// <param name="distributionInfoA">Volume, volume distribution, and center information about the new form of the original compound collidable.</param> /// <param name="distributionInfoB">Volume, volume distribution, and center information about the new compound collidable.</param> /// <param name="weightA">Total weight associated with the new form of the original compound collidable.</param> /// <param name="weightB">Total weight associated with the new compound collidable.</param> /// <returns>Whether or not the predicate returned true for any element in the original compound and split the compound.</returns> public static bool SplitCompound(IList <ShapeDistributionInformation> childContributions, Func <CompoundChild, bool> splitPredicate, CompoundCollidable a, CompoundCollidable b, out ShapeDistributionInformation distributionInfoA, out ShapeDistributionInformation distributionInfoB, out float weightA, out float weightB) { bool splitOccurred = false; for (int i = a.children.count - 1; i >= 0; i--) { //The shape doesn't change during this process. The entity could, though. //All of the other collidable information, like the Tag, CollisionRules, Events, etc. all stay the same. var child = a.children.Elements[i]; if (splitPredicate(child)) { splitOccurred = true; a.children.FastRemoveAt(i); b.children.Add(child); } } if (!splitOccurred) { //No split occurred, so we cannot proceed. distributionInfoA = new ShapeDistributionInformation(); distributionInfoB = new ShapeDistributionInformation(); weightA = 0; weightB = 0; return(false); } //Compute the contributions from the original shape to the new form of the original collidable. distributionInfoA = new ShapeDistributionInformation(); weightA = 0; distributionInfoB = new ShapeDistributionInformation(); weightB = 0; for (int i = a.children.count - 1; i >= 0; i--) { var child = a.children.Elements[i]; var entry = child.Entry; var contribution = childContributions[child.shapeIndex]; Vector3.Add(ref contribution.Center, ref entry.LocalTransform.Position, out contribution.Center); Vector3.Multiply(ref contribution.Center, child.Entry.Weight, out contribution.Center); Vector3.Add(ref contribution.Center, ref distributionInfoA.Center, out distributionInfoA.Center); distributionInfoA.Volume += contribution.Volume; weightA += entry.Weight; } for (int i = b.children.count - 1; i >= 0; i--) { var child = b.children.Elements[i]; var entry = child.Entry; var contribution = childContributions[child.shapeIndex]; Vector3.Add(ref contribution.Center, ref entry.LocalTransform.Position, out contribution.Center); Vector3.Multiply(ref contribution.Center, child.Entry.Weight, out contribution.Center); Vector3.Add(ref contribution.Center, ref distributionInfoB.Center, out distributionInfoB.Center); distributionInfoB.Volume += contribution.Volume; weightB += entry.Weight; } //Average the center out. Vector3.Divide(ref distributionInfoA.Center, weightA, out distributionInfoA.Center); Vector3.Divide(ref distributionInfoB.Center, weightB, out distributionInfoB.Center); //Note that the 'entry' is from the Shape, and so the translations are local to the shape's center. //That is not technically the center of the new collidable- distributionInfoA.Center is. //Offset the child collidables by -distributionInfoA.Center using their local offset. Vector3 offsetA; Vector3.Negate(ref distributionInfoA.Center, out offsetA); Vector3 offsetB; Vector3.Negate(ref distributionInfoB.Center, out offsetB); //Compute the unscaled inertia tensor. for (int i = a.children.count - 1; i >= 0; i--) { var child = a.children.Elements[i]; child.CollisionInformation.localPosition = offsetA; var entry = child.Entry; var contribution = childContributions[child.shapeIndex]; CompoundShape.TransformContribution(ref entry.LocalTransform, ref distributionInfoA.Center, ref contribution.VolumeDistribution, entry.Weight, out contribution.VolumeDistribution); Vector3.Add(ref entry.LocalTransform.Position, ref offsetA, out entry.LocalTransform.Position); Matrix3X3.Add(ref contribution.VolumeDistribution, ref distributionInfoA.VolumeDistribution, out distributionInfoA.VolumeDistribution); } for (int i = b.children.count - 1; i >= 0; i--) { var child = b.children.Elements[i]; child.CollisionInformation.localPosition = offsetB; var entry = child.Entry; var contribution = childContributions[child.shapeIndex]; CompoundShape.TransformContribution(ref entry.LocalTransform, ref distributionInfoB.Center, ref contribution.VolumeDistribution, entry.Weight, out contribution.VolumeDistribution); Vector3.Add(ref entry.LocalTransform.Position, ref offsetB, out entry.LocalTransform.Position); Matrix3X3.Add(ref contribution.VolumeDistribution, ref distributionInfoB.VolumeDistribution, out distributionInfoB.VolumeDistribution); } //Normalize the volume distribution. Matrix3X3.Multiply(ref distributionInfoA.VolumeDistribution, 1 / weightA, out distributionInfoA.VolumeDistribution); Matrix3X3.Multiply(ref distributionInfoB.VolumeDistribution, 1 / weightB, out distributionInfoB.VolumeDistribution); //Update the hierarchies of the compounds. //TODO: Create a new method that does this quickly without garbage. Requires a new Reconstruct method which takes a pool which stores the appropriate node types. a.hierarchy.Tree.Reconstruct(a.children); b.hierarchy.Tree.Reconstruct(b.children); return(true); }
public void VisitCompoundShape(CompoundShape shape) { Console.WriteLine("export compound"); }
private void SpawnRandomPrimitive(JVector position, JVector velocity) { RigidBody body = null; int rndn = rndn = random.Next(7); if (rndn == 5 || rndn == 6) { rndn = random.Next(7); } switch (rndn) { case 0: body = new RigidBody(new ConeShape(random.Next(5, 50) / 20.0f, random.Next(10, 20) / 20.0f)); break; case 1: body = new RigidBody(new BoxShape(random.Next(10, 30) / 20.0f, random.Next(10, 30) / 20.0f, random.Next(10, 30) / 20.0f)); break; case 2: body = new RigidBody(new SphereShape(0.4f)); break; case 3: body = new RigidBody(new CylinderShape(1.0f, 0.5f)); break; case 4: body = new RigidBody(new CapsuleShape(1.0f, 0.5f)); break; case 5: Shape b1 = new BoxShape(new JVector(3, 1, 1)); Shape b2 = new BoxShape(new JVector(1, 1, 3)); Shape b3 = new CylinderShape(3.0f, 0.5f); var t1 = new CompoundShape.TransformedShape(b1, JMatrix.Identity, JVector.Zero); var t2 = new CompoundShape.TransformedShape(b2, JMatrix.Identity, JVector.Zero); var t3 = new CompoundShape.TransformedShape(b3, JMatrix.Identity, new JVector(0, 0, 0)); var ms = new CompoundShape(new CompoundShape.TransformedShape[3] { t1, t2, t3 }); body = new RigidBody(ms); break; case 6: var obj2 = new ConvexHullObject(this); Components.Add(obj2); body = obj2.body; body.Material.Restitution = 0.2f; body.Material.StaticFriction = 0.8f; break; } World.AddBody(body); body.Position = position; body.LinearVelocity = velocity; lastBody = body; }
public PhysicalBatchedStaticCompoundComponent(INode node, IPhysicsEngine physicsEngine, CompoundShape shape) : base(node, physicsEngine) { _shape = shape; }
public void Merge() { // \todo #if true if (selectionManager == null) { return; } if (selectionManager.Models.Count <= 1) { return; } // First pass: Find which model to use as new reference // There should be one model which parent is not any // of the models in selection. Model referenceModel = null; foreach (Model referenceCandidate in selectionManager.Models) { if (referenceCandidate == null) { continue; } bool candidateHasParentInSelection = false; foreach (Model otherModel in selectionManager.Models) { if (otherModel == null) { continue; } if (referenceCandidate.Frame.Parent == otherModel.Frame) { candidateHasParentInSelection = true; break; } } if (candidateHasParentInSelection == false) { referenceModel = referenceCandidate; break; } } if (referenceModel == null) { throw new Exception("Unable to pick selection root model for merge operation"); } // This is where compound shapes are collected. // All shapes are added in the coordinate system of the reference model. // Models that have no rigid bodies are skipped List <CompoundShape.TransformedShape> shapes = new List <CompoundShape.TransformedShape>(); // Add reference model (if it has rigidbody) if (referenceModel.RigidBody != null) { //var shape = new CompoundShape.TransformedShape( // referenceModel.RigidBody.Shape, // JMatrix.Identity, // JVector.Zero //); //shapes.Add(shape); Shape oldShape = referenceModel.RigidBody.Shape; CompoundShape compound = oldShape as CompoundShape; if (compound != null) { foreach (var part in compound.Shapes) { var shape = new CompoundShape.TransformedShape( part.Shape, part.Transform //part.Orientation, //part.Position ); shapes.Add(shape); } } else { var shape = new CompoundShape.TransformedShape( referenceModel.RigidBody.Shape, Matrix4.Identity //JMatrix.Identity, //JVector.Zero ); shapes.Add(shape); } } GeometryMesh referencePolymesh = referenceModel.Batch.MeshSource as GeometryMesh; Geometry mergedGeometry = new CloneGeometryOperation(referencePolymesh.Geometry, null).Destination; // Remove original reference model from scene graph sceneManager.RemoveModel(referenceModel); foreach (Model mergeModel in selectionManager.Models) { if (mergeModel == null || mergeModel == referenceModel) { continue; } GeometryMesh addPolymesh = mergeModel.Batch.MeshSource as GeometryMesh; Geometry addGeometry = new CloneGeometryOperation(addPolymesh.Geometry, null).Destination; Matrix4 toSameSpace = referenceModel.Frame.LocalToWorld.InverseMatrix * mergeModel.Frame.LocalToWorld.Matrix; addGeometry.Transform(toSameSpace); if (mergeModel.RigidBody != null) { // TODO: Decompose - for now we only have rotations and translations so this should work /*JMatrix orientation; * orientation.M11 = toSameSpace._00; * orientation.M21 = toSameSpace._01; * orientation.M31 = toSameSpace._02; * orientation.M12 = toSameSpace._10; * orientation.M22 = toSameSpace._11; * orientation.M32 = toSameSpace._12; * orientation.M13 = toSameSpace._20; * orientation.M23 = toSameSpace._21; * orientation.M33 = toSameSpace._22; * orientation.M13 = toSameSpace._20; * orientation.M23 = toSameSpace._21; * orientation.M33 = toSameSpace._22; * Vector3 p = toSameSpace.GetColumn3(3); * JVector position = new JVector(p.X, p.Y, p.Z);*/ Shape oldShape = mergeModel.RigidBody.Shape; CompoundShape compound = oldShape as CompoundShape; if (compound != null) { foreach (var part in compound.Shapes) { var shape = new CompoundShape.TransformedShape( part.Shape, toSameSpace * part.Transform //JMatrix.Multiply(orientation, part.Orientation), //position + JVector.Transform(part.Position, orientation) ); shapes.Add(shape); } } else { var shape = new CompoundShape.TransformedShape( oldShape, toSameSpace //orientation, //position ); shapes.Add(shape); } } mergedGeometry.Merge(addGeometry); sceneManager.RemoveModel(mergeModel); } Matrix4 modelOffset = Matrix4.Identity; CompoundShape compoundShape = null; if (shapes.Count > 0) { compoundShape = new CompoundShape(shapes); Matrix4 vertexOffset = Matrix4.CreateTranslation(compoundShape.Shift.X, compoundShape.Shift.Y, compoundShape.Shift.Z); modelOffset = Matrix4.CreateTranslation(-compoundShape.Shift.X, -compoundShape.Shift.Y, -compoundShape.Shift.Z); mergedGeometry.Transform(vertexOffset); } mergedGeometry.ComputePolygonCentroids(); mergedGeometry.ComputePolygonNormals(); //mergedGeometry.ComputeCornerNormals(0.0f); mergedGeometry.SmoothNormalize("corner_normals", "polygon_normals", (0.0f * (float)Math.PI)); mergedGeometry.BuildEdges(); GeometryMesh mergedPolyMesh = new GeometryMesh(mergedGeometry, NormalStyle.PolygonNormals); // Compute bounding box - debug { var bbox = new BoundingBox(); var pointLocations = mergedGeometry.PointAttributes.Find <Vector3>("point_locations"); bbox.Clear(); foreach (Point point in mergedGeometry.Points) { bbox.ExtendBy(pointLocations[point]); } } Model newModel = new Model( "Merge(" + referenceModel.Name + ", " + selectionManager.Models.Count + ")", mergedPolyMesh, referenceModel.Batch.Material, referenceModel.Frame.LocalToParent.Matrix * modelOffset ); if (compoundShape != null) { newModel.PhysicsShape = compoundShape; } //sceneManager.MakeModelPhysicsConvexHull(newModel); This won't work as Shift is not properly taken into account newModel.Frame.Parent = referenceModel.Frame.Parent; newModel.Static = referenceModel.Static; selectionManager.ClearSelection(); // This will create rigidbody using .PhysicsShape if set, otherwise it will call // MakeModelPhysicsConvexHull(). sceneManager.AddModel(newModel); selectionManager.HoverModel = null; selectionManager.HoverPolygon = null; #endif }
private void CreateVehicle(Matrix transform) { var chassisShape = new BoxShape(1.0f, 0.5f, 2.0f); var compound = new CompoundShape(); //localTrans effectively shifts the center of mass with respect to the chassis Matrix localTrans = Matrix.Translation(Vector3.UnitY); compound.AddChildShape(localTrans, chassisShape); RigidBody carChassis = PhysicsHelper.CreateBody(800, Matrix.Identity, compound, World); carChassis.UserObject = "Chassis"; //carChassis.SetDamping(0.2f, 0.2f); var tuning = new VehicleTuning(); var vehicleRayCaster = new DefaultVehicleRaycaster(World); //vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster); _vehicle = new CustomVehicle(tuning, carChassis, vehicleRayCaster); carChassis.ActivationState = ActivationState.DisableDeactivation; World.AddAction(_vehicle); const float connectionHeight = 1.2f; // choose coordinate system _vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex); Vector3 wheelDirection = Vector3.Zero; Vector3 wheelAxle = Vector3.Zero; wheelDirection[upIndex] = -1; wheelAxle[rightIndex] = -1; bool isFrontWheel = true; var connectionPoint = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius); _vehicle.AddWheel(connectionPoint, wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, isFrontWheel); connectionPoint = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius); _vehicle.AddWheel(connectionPoint, wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, isFrontWheel); isFrontWheel = false; connectionPoint = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius); _vehicle.AddWheel(connectionPoint, wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, isFrontWheel); connectionPoint = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius); _vehicle.AddWheel(connectionPoint, wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, isFrontWheel); for (int i = 0; i < _vehicle.NumWheels; i++) { WheelInfo wheel = _vehicle.GetWheelInfo(i); wheel.SuspensionStiffness = suspensionStiffness; wheel.WheelsDampingRelaxation = suspensionDamping; wheel.WheelsDampingCompression = suspensionCompression; wheel.FrictionSlip = wheelFriction; wheel.RollInfluence = rollInfluence; } _vehicle.RigidBody.WorldTransform = transform; }
public override void OnDrawGizmosSelected() { if (!drawGizmo) { return; } Gizmos.color = Color.yellow; CompoundShape compoundShape = GetCollisionShape() as CompoundShape; for (int i = 0; i < compoundShape.NumChildShapes; i++) { CollisionShape collisionShape = compoundShape.GetChildShape(i); ConvexHullShape convexShape = collisionShape as ConvexHullShape; if (convexShape != null) { BulletSharp.Math.Matrix childShapeTransform = compoundShape.GetChildTransform(i); //childShapeTransform.Invert(); BulletSharp.Math.Matrix shapeTransform = childShapeTransform * this.transform.localToWorldMatrix.ToBullet(); Gizmos.matrix = shapeTransform.ToUnity(); int nbEdges = convexShape.NumEdges; for (int j = 0; j < nbEdges; j++) { BulletSharp.Math.Vector3 vertex1; BulletSharp.Math.Vector3 vertex2; convexShape.GetEdge(j, out vertex1, out vertex2); Vector3 vertexUnity1 = BSExtensionMethods2.ToUnity(vertex1); Vector3 vertexUnity2 = BSExtensionMethods2.ToUnity(vertex2); Gizmos.DrawLine(vertexUnity1, vertexUnity2); } /*Mesh collisionMesh = new Mesh(); * Vector3[] newVertices = new Vector3[convexShape.NumVertices]; * int[] triangles = new int[convexShape.NumVertices * 3]; * for (int j = 0; j < convexShape.NumVertices; j++) * { * BulletSharp.Math.Vector3 vertex1; * convexShape.GetVertex(j, out vertex1); * newVertices[j] = vertex1.ToUnity(); * triangles[j] = j; * } * collisionMesh.vertices = newVertices; * collisionMesh.triangles = triangles; * collisionMesh.RecalculateNormals(); * Gizmos.color = Color.blue; * Gizmos.DrawMesh(collisionMesh); */ } BvhTriangleMeshShape triangleShape = collisionShape as BvhTriangleMeshShape; if (triangleShape != null) { BulletSharp.Math.Matrix shapeTransform = this.transform.localToWorldMatrix.ToBullet() * compoundShape.GetChildTransform(i); Gizmos.matrix = BSExtensionMethods2.ToUnity(shapeTransform); /*int nbEdges = triangleShape.; * for (int j = 0; j < nbEdges; j++) * { * BulletSharp.Math.Vector3 vertex1; * BulletSharp.Math.Vector3 vertex2; * triangleShape.GetEdge(j, out vertex1, out vertex2); * Vector3 vertexUnity1 = BSExtensionMethods2.ToUnity(vertex1); * Vector3 vertexUnity2 = BSExtensionMethods2.ToUnity(vertex2); * Gizmos.DrawLine(vertexUnity1, vertexUnity2); * }*/ } } }
public void Render(CollisionShape shape) { Mesh mesh; if (shapes.TryGetValue(shape, out mesh)) { mesh.DrawSubset(0); return; } if (complexShapes.TryGetValue(shape, out mesh)) { RenderComplexShape(shape, mesh); return; } // Create the graphics mesh or go to child shapes. switch (shape.ShapeType) { case BroadphaseNativeType.BoxShape: mesh = CreateBoxShape(shape as BoxShape); break; case BroadphaseNativeType.CylinderShape: mesh = CreateCylinderShape(shape as CylinderShape); break; case BroadphaseNativeType.ConeShape: mesh = CreateConeShape(shape as ConeShape); break; case BroadphaseNativeType.ConvexHullShape: mesh = CreateConvexHullShape(shape as ConvexHullShape); break; case BroadphaseNativeType.GImpactShape: mesh = CreateGImpactMeshShape(shape as GImpactMeshShape); break; case BroadphaseNativeType.Convex2DShape: Render((shape as Convex2DShape).ChildShape); return; case BroadphaseNativeType.CompoundShape: CompoundShape compoundShape = shape as CompoundShape; //if (compoundShape.NumChildShapes == 0) // return; foreach (CompoundShapeChild child in compoundShape.ChildList) { // do a pre-transform Matrix tempTr = device.GetTransform(TransformState.World); device.SetTransform(TransformState.World, child.Transform * tempTr); Render(child.ChildShape); } return; case BroadphaseNativeType.SphereShape: mesh = CreateSphere(shape as SphereShape); break; case BroadphaseNativeType.TriangleMeshShape: mesh = CreateTriangleMeshShape(shape as TriangleMeshShape); break; } // If the shape has one subset, render it. if (mesh != null) { mesh.DrawSubset(0); return; } switch (shape.ShapeType) { case BroadphaseNativeType.CapsuleShape: mesh = CreateCapsuleShape(shape as CapsuleShape); break; case BroadphaseNativeType.MultiSphereShape: mesh = CreateMultiSphereShape(shape as MultiSphereShape); break; case BroadphaseNativeType.StaticPlaneShape: mesh = CreateStaticPlaneShape(shape as StaticPlaneShape); break; } RenderComplexShape(shape, mesh); }
protected override void OnInitializePhysics() { ManifoldPoint.ContactAdded += MyContactCallback; SetupEmptyDynamicsWorld(); //CompoundCollisionAlgorithm.CompoundChildShapePairCallback = MyCompoundChildShapeCallback; convexDecompositionObjectOffset = new Vector3(10, 0, 0); // Load wavefront file var wo = new WavefrontObj(); //string filename = UnityEngine.Application.dataPath + "/BulletUnity/Examples/Scripts/BulletSharpDemos/ConvexDecompositionDemo/data/file.obj"; UnityEngine.TextAsset bytes = (UnityEngine.TextAsset)UnityEngine.Resources.Load("file.obj"); System.IO.Stream byteStream = new System.IO.MemoryStream(bytes.bytes); int tcount = wo.LoadObj(byteStream); if (tcount == 0) { return; } // Convert file data to TriangleMesh var trimesh = new TriangleMesh(); trimeshes.Add(trimesh); Vector3 localScaling = new Vector3(6, 6, 6); List <int> indices = wo.Indices; List <Vector3> vertices = wo.Vertices; int i; for (i = 0; i < tcount; i++) { int index0 = indices[i * 3]; int index1 = indices[i * 3 + 1]; int index2 = indices[i * 3 + 2]; Vector3 vertex0 = vertices[index0] * localScaling; Vector3 vertex1 = vertices[index1] * localScaling; Vector3 vertex2 = vertices[index2] * localScaling; trimesh.AddTriangleRef(ref vertex0, ref vertex1, ref vertex2); } // Create a hull approximation ConvexHullShape convexShape; using (var tmpConvexShape = new ConvexTriangleMeshShape(trimesh)) { using (var hull = new ShapeHull(tmpConvexShape)) { hull.BuildHull(tmpConvexShape.Margin); convexShape = new ConvexHullShape(hull.Vertices); } } if (sEnableSAT) { convexShape.InitializePolyhedralFeatures(); } CollisionShapes.Add(convexShape); // Add non-moving body to world float mass = 1.0f; LocalCreateRigidBody(mass, Matrix.Translation(0, 2, 14), convexShape); const bool useQuantization = true; var concaveShape = new BvhTriangleMeshShape(trimesh, useQuantization); LocalCreateRigidBody(0, Matrix.Translation(convexDecompositionObjectOffset), concaveShape); CollisionShapes.Add(concaveShape); // HACD var hacd = new Hacd(); hacd.SetPoints(wo.Vertices); hacd.SetTriangles(wo.Indices); hacd.CompacityWeight = 0.1; hacd.VolumeWeight = 0.0; // Recommended HACD parameters: 2 100 false false false hacd.NClusters = 2; // minimum number of clusters hacd.Concavity = 100; // maximum concavity hacd.AddExtraDistPoints = false; hacd.AddNeighboursDistPoints = false; hacd.AddFacesPoints = false; hacd.NVerticesPerCH = 100; // max of 100 vertices per convex-hull hacd.Compute(); hacd.Save("output.wrl", false); // Generate convex result var outputFile = new FileStream("file_convex.obj", FileMode.Create, FileAccess.Write); var writer = new StreamWriter(outputFile); var convexDecomposition = new ConvexDecomposition(writer, this); convexDecomposition.LocalScaling = localScaling; for (int c = 0; c < hacd.NClusters; c++) { int nVertices = hacd.GetNPointsCH(c); int trianglesLen = hacd.GetNTrianglesCH(c) * 3; double[] points = new double[nVertices * 3]; long[] triangles = new long[trianglesLen]; hacd.GetCH(c, points, triangles); if (trianglesLen == 0) { continue; } Vector3[] verticesArray = new Vector3[nVertices]; int vi3 = 0; for (int vi = 0; vi < nVertices; vi++) { verticesArray[vi] = new Vector3( (float)points[vi3], (float)points[vi3 + 1], (float)points[vi3 + 2]); vi3 += 3; } int[] trianglesInt = new int[trianglesLen]; for (int ti = 0; ti < trianglesLen; ti++) { trianglesInt[ti] = (int)triangles[ti]; } convexDecomposition.ConvexDecompResult(verticesArray, trianglesInt); } // Combine convex shapes into a compound shape var compound = new CompoundShape(); for (i = 0; i < convexDecomposition.convexShapes.Count; i++) { Vector3 centroid = convexDecomposition.convexCentroids[i]; var convexShape2 = convexDecomposition.convexShapes[i]; Matrix trans = Matrix.Translation(centroid); if (sEnableSAT) { convexShape2.InitializePolyhedralFeatures(); } CollisionShapes.Add(convexShape2); compound.AddChildShape(trans, convexShape2); LocalCreateRigidBody(1.0f, trans, convexShape2); } CollisionShapes.Add(compound); writer.Dispose(); outputFile.Dispose(); #if true mass = 10.0f; var body2 = LocalCreateRigidBody(mass, Matrix.Translation(-convexDecompositionObjectOffset), compound); body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback; convexDecompositionObjectOffset.Z = 6; body2 = LocalCreateRigidBody(mass, Matrix.Translation(-convexDecompositionObjectOffset), compound); body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback; convexDecompositionObjectOffset.Z = -6; body2 = LocalCreateRigidBody(mass, Matrix.Translation(-convexDecompositionObjectOffset), compound); body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback; #endif }
public Physics(VehicleDemo game) { CollisionShape groundShape = new BoxShape(50, 3, 50); CollisionShapes.Add(groundShape); CollisionConf = new DefaultCollisionConfiguration(); Dispatcher = new CollisionDispatcher(CollisionConf); Solver = new SequentialImpulseConstraintSolver(); Vector3 worldMin = new Vector3(-10000, -10000, -10000); Vector3 worldMax = new Vector3(10000, 10000, 10000); Broadphase = new AxisSweep3(worldMin, worldMax); //Broadphase = new DbvtBroadphase(); World = new DiscreteDynamicsWorld(Dispatcher, Broadphase, Solver, CollisionConf); int i; Matrix tr; Matrix vehicleTr; if (UseTrimeshGround) { const float scale = 20.0f; //create a triangle-mesh ground int vertStride = Vector3.SizeInBytes; int indexStride = 3 * sizeof(int); const int NUM_VERTS_X = 20; const int NUM_VERTS_Y = 20; const int totalVerts = NUM_VERTS_X * NUM_VERTS_Y; const int totalTriangles = 2 * (NUM_VERTS_X - 1) * (NUM_VERTS_Y - 1); TriangleIndexVertexArray vertexArray = new TriangleIndexVertexArray(); IndexedMesh mesh = new IndexedMesh(); mesh.Allocate(totalVerts, vertStride, totalTriangles, indexStride, PhyScalarType.Int32, PhyScalarType.Single); BulletSharp.DataStream data = mesh.LockVerts(); for (i = 0; i < NUM_VERTS_X; i++) { for (int j = 0; j < NUM_VERTS_Y; j++) { float wl = .2f; float height = 20.0f * (float)(Math.Sin(i * wl) * Math.Cos(j * wl)); data.Write((i - NUM_VERTS_X * 0.5f) * scale); data.Write(height); data.Write((j - NUM_VERTS_Y * 0.5f) * scale); } } int index = 0; IntArray idata = mesh.TriangleIndices; for (i = 0; i < NUM_VERTS_X - 1; i++) { for (int j = 0; j < NUM_VERTS_Y - 1; j++) { idata[index++] = j * NUM_VERTS_X + i; idata[index++] = j * NUM_VERTS_X + i + 1; idata[index++] = (j + 1) * NUM_VERTS_X + i + 1; idata[index++] = j * NUM_VERTS_X + i; idata[index++] = (j + 1) * NUM_VERTS_X + i + 1; idata[index++] = (j + 1) * NUM_VERTS_X + i; } } vertexArray.AddIndexedMesh(mesh); groundShape = new BvhTriangleMeshShape(vertexArray, true); tr = Matrix.Identity; vehicleTr = Matrix.Translation(0, -2, 0); } else { // Use HeightfieldTerrainShape int width = 40, length = 40; //int width = 128, length = 128; // Debugging is too slow for this float maxHeight = 10.0f; float heightScale = maxHeight / 256.0f; Vector3 scale = new Vector3(20.0f, maxHeight, 20.0f); //PhyScalarType scalarType = PhyScalarType.PhyUChar; //FileStream file = new FileStream(heightfieldFile, FileMode.Open, FileAccess.Read); // Use float data PhyScalarType scalarType = PhyScalarType.Single; byte[] terr = new byte[width * length * 4]; MemoryStream file = new MemoryStream(terr); BinaryWriter writer = new BinaryWriter(file); for (i = 0; i < width; i++) { for (int j = 0; j < length; j++) { writer.Write((float)((maxHeight / 2) + 4 * Math.Sin(j * 0.5f) * Math.Cos(i))); } } writer.Flush(); file.Position = 0; HeightfieldTerrainShape heightterrainShape = new HeightfieldTerrainShape(width, length, file, heightScale, 0, maxHeight, upIndex, scalarType, false); heightterrainShape.SetUseDiamondSubdivision(true); groundShape = heightterrainShape; groundShape.LocalScaling = new Vector3(scale.X, 1, scale.Z); tr = Matrix.Translation(new Vector3(-scale.X / 2, scale.Y / 2, -scale.Z / 2)); vehicleTr = Matrix.Translation(new Vector3(20, 3, -3)); // Create graphics object file.Position = 0; BinaryReader reader = new BinaryReader(file); int totalTriangles = (width - 1) * (length - 1) * 2; int totalVerts = width * length; game.groundMesh = new Mesh(game.Device, totalTriangles, totalVerts, MeshFlags.SystemMemory | MeshFlags.Use32Bit, VertexFormat.Position | VertexFormat.Normal); SlimDX.DataStream data = game.groundMesh.LockVertexBuffer(LockFlags.None); for (i = 0; i < width; i++) { for (int j = 0; j < length; j++) { float height; if (scalarType == PhyScalarType.Single) { // heightScale isn't applied internally for float data height = reader.ReadSingle(); } else if (scalarType == PhyScalarType.Byte) { height = file.ReadByte() * heightScale; } else { height = 0.0f; } data.Write((j - length * 0.5f) * scale.X); data.Write(height); data.Write((i - width * 0.5f) * scale.Z); // Normals will be calculated later data.Position += 12; } } game.groundMesh.UnlockVertexBuffer(); file.Close(); data = game.groundMesh.LockIndexBuffer(LockFlags.None); for (i = 0; i < width - 1; i++) { for (int j = 0; j < length - 1; j++) { // Using diamond subdivision if ((j + i) % 2 == 0) { data.Write(j * width + i); data.Write((j + 1) * width + i + 1); data.Write(j * width + i + 1); data.Write(j * width + i); data.Write((j + 1) * width + i); data.Write((j + 1) * width + i + 1); } else { data.Write(j * width + i); data.Write((j + 1) * width + i); data.Write(j * width + i + 1); data.Write(j * width + i + 1); data.Write((j + 1) * width + i); data.Write((j + 1) * width + i + 1); } /* * // Not using diamond subdivision * data.Write(j * width + i); * data.Write((j + 1) * width + i); * data.Write(j * width + i + 1); * * data.Write(j * width + i + 1); * data.Write((j + 1) * width + i); * data.Write((j + 1) * width + i + 1); */ } } game.groundMesh.UnlockIndexBuffer(); game.groundMesh.ComputeNormals(); } CollisionShapes.Add(groundShape); //create ground object RigidBody ground = LocalCreateRigidBody(0, tr, groundShape); ground.UserObject = "Ground"; CollisionShape chassisShape = new BoxShape(1.0f, 0.5f, 2.0f); CollisionShapes.Add(chassisShape); CompoundShape compound = new CompoundShape(); CollisionShapes.Add(compound); //localTrans effectively shifts the center of mass with respect to the chassis Matrix localTrans = Matrix.Translation(Vector3.UnitY); compound.AddChildShape(localTrans, chassisShape); RigidBody carChassis = LocalCreateRigidBody(800, Matrix.Identity, compound); carChassis.UserObject = "Chassis"; //carChassis.SetDamping(0.2f, 0.2f); //CylinderShapeX wheelShape = new CylinderShapeX(wheelWidth, wheelRadius, wheelRadius); // clientResetScene(); // create vehicle RaycastVehicle.VehicleTuning tuning = new RaycastVehicle.VehicleTuning(); IVehicleRaycaster vehicleRayCaster = new DefaultVehicleRaycaster(World); vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster); carChassis.ActivationState = ActivationState.DisableDeactivation; World.AddAction(vehicle); float connectionHeight = 1.2f; bool isFrontWheel = true; // choose coordinate system vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex); Vector3 connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius); WheelInfo a = vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); isFrontWheel = false; connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); for (i = 0; i < vehicle.NumWheels; i++) { WheelInfo wheel = vehicle.GetWheelInfo(i); wheel.SuspensionStiffness = suspensionStiffness; wheel.WheelsDampingRelaxation = suspensionDamping; wheel.WheelsDampingCompression = suspensionCompression; wheel.FrictionSlip = wheelFriction; wheel.RollInfluence = rollInfluence; } vehicle.RigidBody.WorldTransform = vehicleTr; }
protected override void OnInitializePhysics() { ManifoldPoint.ContactAdded += MyContactCallback; SetupEmptyDynamicsWorld(); CreateGround(); //CompoundCollisionAlgorithm.CompoundChildShapePairCallback = MyCompoundChildShapeCallback; var wo = WavefrontObj.Load("data/file.obj"); if (wo.Indices.Count == 0) { return; } var localScaling = new Vector3(6, 6, 6); triangleMesh = CreateTriangleMesh(wo.Indices, wo.Vertices, localScaling); // Convex hull approximation ConvexHullShape convexShape = CreateHullApproximation(triangleMesh); CollisionShapes.Add(convexShape); float mass = 1.0f; LocalCreateRigidBody(mass, Matrix.Translation(0, 2, 14), convexShape); // Non-moving body Vector3 convexDecompositionObjectOffset = new Vector3(10, 0, 0); const bool useQuantization = true; var concaveShape = new BvhTriangleMeshShape(triangleMesh, useQuantization); CollisionShapes.Add(concaveShape); LocalCreateRigidBody(0, Matrix.Translation(convexDecompositionObjectOffset), concaveShape); var hacd = new Hacd() { VerticesPerConvexHull = 100, CompacityWeight = 0.1, VolumeWeight = 0, // Recommended HACD parameters NClusters = 2, Concavity = 100, AddExtraDistPoints = false, AddFacesPoints = false, AddNeighboursDistPoints = false }; hacd.SetPoints(wo.Vertices); hacd.SetTriangles(wo.Indices); hacd.Compute(); hacd.Save("output.wrl", false); // Generate convex result var outputFile = new FileStream("file_convex.obj", FileMode.Create, FileAccess.Write); var writer = new StreamWriter(outputFile); var convexDecomposition = new ConvexDecomposition(writer) { LocalScaling = localScaling }; for (int c = 0; c < hacd.NClusters; c++) { int nVertices = hacd.GetNPointsCH(c); int trianglesLen = hacd.GetNTrianglesCH(c) * 3; double[] points = new double[nVertices * 3]; long[] triangles = new long[trianglesLen]; hacd.GetCH(c, points, triangles); if (trianglesLen == 0) { continue; } Vector3[] verticesArray = new Vector3[nVertices]; int vi3 = 0; for (int vi = 0; vi < nVertices; vi++) { verticesArray[vi] = new Vector3( (float)points[vi3], (float)points[vi3 + 1], (float)points[vi3 + 2]); vi3 += 3; } int[] trianglesInt = new int[trianglesLen]; for (int ti = 0; ti < trianglesLen; ti++) { trianglesInt[ti] = (int)triangles[ti]; } convexDecomposition.Result(verticesArray, trianglesInt); } writer.Dispose(); outputFile.Dispose(); // Combine convex shapes into a compound shape var compound = new CompoundShape(); for (int i = 0; i < convexDecomposition.convexShapes.Count; i++) { Vector3 centroid = convexDecomposition.convexCentroids[i]; var convexShape2 = convexDecomposition.convexShapes[i]; Matrix trans = Matrix.Translation(centroid); if (enableSat) { convexShape2.InitializePolyhedralFeatures(); } CollisionShapes.Add(convexShape2); compound.AddChildShape(trans, convexShape2); LocalCreateRigidBody(1.0f, trans, convexShape2); } CollisionShapes.Add(compound); #if true mass = 10.0f; var body2 = LocalCreateRigidBody(mass, Matrix.Translation(-convexDecompositionObjectOffset), compound); body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback; convexDecompositionObjectOffset.Z = 6; body2 = LocalCreateRigidBody(mass, Matrix.Translation(-convexDecompositionObjectOffset), compound); body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback; convexDecompositionObjectOffset.Z = -6; body2 = LocalCreateRigidBody(mass, Matrix.Translation(-convexDecompositionObjectOffset), compound); body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback; #endif }
public override void InitializeDemo() { m_cameraDistance = 10.0f; //string filename = @"e:\users\man\bullet\gimpact-demo-xna.txt"; //FileStream filestream = File.Open(filename, FileMode.Create, FileAccess.Write, FileShare.Read); //BulletGlobals.g_streamWriter = new StreamWriter(filestream); /// Init Bullet m_collisionConfiguration = new DefaultCollisionConfiguration(); m_dispatcher = new CollisionDispatcher(m_collisionConfiguration); //btOverlappingPairCache* broadphase = new btSimpleBroadphase(); //m_broadphase = new btSimpleBroadphase(); int maxProxies = 1024; IndexedVector3 worldAabbMin = new IndexedVector3(-10000, -10000, -10000); IndexedVector3 worldAabbMax = new IndexedVector3(10000, 10000, 10000); //m_broadphase = new AxisSweep3Internal(ref worldAabbMin, ref worldAabbMax, 0xfffe, 0xffff, 16384, null, false); m_broadphase = new SimpleBroadphase(16384, null); m_constraintSolver = new SequentialImpulseConstraintSolver(); m_dynamicsWorld = new DiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_constraintSolver, m_collisionConfiguration); //create trimesh model and shape InitGImpactCollision(); /// Create Scene float mass = 0.0f; IndexedMatrix startTransform = IndexedMatrix.Identity; CollisionShape staticboxShape1 = new BoxShape(new IndexedVector3(200, 1, 200));//floor staticboxShape1.SetUserPointer("Floor"); CollisionShape staticboxShape2 = new BoxShape(new IndexedVector3(1, 50, 200));//left wall staticboxShape1.SetUserPointer("LeftWall"); CollisionShape staticboxShape3 = new BoxShape(new IndexedVector3(1, 50, 200));//right wall staticboxShape1.SetUserPointer("RightWall"); CollisionShape staticboxShape4 = new BoxShape(new IndexedVector3(200, 50, 1));//front wall staticboxShape1.SetUserPointer("FrontWall"); CollisionShape staticboxShape5 = new BoxShape(new IndexedVector3(200, 50, 1));//back wall staticboxShape1.SetUserPointer("BackWall"); CompoundShape staticScenario = new CompoundShape();//static scenario startTransform._origin = new IndexedVector3(0, 0, 0); staticScenario.AddChildShape(ref startTransform, staticboxShape1); startTransform._origin = new IndexedVector3(-200, 25, 0); staticScenario.AddChildShape(ref startTransform, staticboxShape2); startTransform._origin = new IndexedVector3(200, 25, 0); staticScenario.AddChildShape(ref startTransform, staticboxShape3); startTransform._origin = new IndexedVector3(0, 25, 200); staticScenario.AddChildShape(ref startTransform, staticboxShape4); startTransform._origin = new IndexedVector3(0, 25, -200); staticScenario.AddChildShape(ref startTransform, staticboxShape5); startTransform._origin = new IndexedVector3(0, 0, 0); //RigidBody staticBody = LocalCreateRigidBody(mass, startTransform, staticScenario); RigidBody staticBody = LocalCreateRigidBody(mass, startTransform, staticboxShape1); staticBody.SetCollisionFlags(staticBody.GetCollisionFlags() | CollisionFlags.CF_STATIC_OBJECT); //enable custom material callback staticBody.SetCollisionFlags(staticBody.GetCollisionFlags() | CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK); //static plane IndexedVector3 normal = new IndexedVector3(0.4f, 1.5f, -0.4f); normal.Normalize(); CollisionShape staticplaneShape6 = new StaticPlaneShape(ref normal, 0.0f); // A plane startTransform._origin = IndexedVector3.Zero; RigidBody staticBody2 = LocalCreateRigidBody(mass, startTransform, staticplaneShape6); staticBody2.SetCollisionFlags(staticBody2.GetCollisionFlags() | CollisionFlags.CF_STATIC_OBJECT); startTransform = IndexedMatrix.Identity; /// Create Dynamic Boxes { int numBoxes = 1; for (int i = 0; i < numBoxes; i++) { CollisionShape boxShape = new BoxShape(new IndexedVector3(1, 1, 1)); //CollisionShape mesh = new BvhTriangleMeshShape(m_indexVertexArrays2,true,true); startTransform._origin = new IndexedVector3(2 * i - (numBoxes - 1), 2, -3); //startTransform._origin = new IndexedVector3(2 * i - 5, 10, -3); //LocalCreateRigidBody(1, startTransform, m_trimeshShape2); LocalCreateRigidBody(1, startTransform, boxShape); } } }
public void Evaluate(int SpreadMax) { IRigidBulletWorld inputWorld = this.worldInput[0]; SpreadMax = 1; if (inputWorld != null) { this.persistedList.UpdateWorld(inputWorld); if (this.chassisShape.IsConnected) { for (int i = 0; i < SpreadMax; i++) { if (this.doCreate[i]) { RigidBodyPose initialPose = this.initialPoseInput.IsConnected ? this.initialPoseInput[i] : RigidBodyPose.Default; RigidBodyProperties properties = this.initialProperties.IsConnected ? this.initialProperties[i] : RigidBodyProperties.Default; ShapeCustomData shapeData = new ShapeCustomData(); DynamicShapeDefinitionBase chassisShapeDefinition = this.chassisShape[i]; CollisionShape chassisShape = chassisShapeDefinition.GetShape(shapeData); shapeData.ShapeDef = chassisShapeDefinition; RaycastVehicle vehicle; CompoundShape compoundShape = new CompoundShape(); Matrix localTrans = Matrix.Translation(Vector3.UnitY); compoundShape.AddChildShape(localTrans, chassisShape); //Build mass for dynamic object Vector3 localInertia = Vector3.Zero; if (chassisShapeDefinition.Mass > 0.0f) { compoundShape.CalculateLocalInertia(chassisShapeDefinition.Mass, out localInertia); } Tuple <RigidBody, int> createBodyResult = inputWorld.CreateRigidBody(chassisShape, ref initialPose, ref properties, ref localInertia, chassisShapeDefinition.Mass, this.customString[i]); RigidBody carChassis = createBodyResult.Item1; RaycastVehicle.VehicleTuning tuning = new RaycastVehicle.VehicleTuning(); DefaultVehicleRaycaster vehicleRayCaster = new DefaultVehicleRaycaster(inputWorld.World); vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster); vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex); carChassis.ActivationState = ActivationState.DisableDeactivation; inputWorld.World.AddAction(vehicle); int wheelCount = this.wheelConstruction.SliceCount; //Add wheels for (int j = 0; j < this.wheelConstruction[i].SliceCount; j++) { WheelConstructionProperties wcs = this.wheelConstruction[i][j]; Vector3 connectionPointCS0 = wcs.localPosition.ToBulletVector(); WheelInfo wheel = vehicle.AddWheel(connectionPointCS0, wcs.wheelDirection.ToBulletVector(), wcs.wheelAxis.ToBulletVector(), wcs.SuspensionRestLength, wcs.WheelRadius, tuning, wcs.isFrontWheel); } //Set Wheel Properties WheelProperties wis = this.wheelInfoSettings[i] != null ? this.wheelInfoSettings[i] : new WheelProperties(); for (int j = 0; j < vehicle.NumWheels; j++) { WheelInfo wheel = vehicle.GetWheelInfo(j); wheel.SuspensionStiffness = wis.SuspensionStiffness; wheel.WheelsDampingRelaxation = wis.WheelsDampingRelaxation; wheel.WheelsDampingCompression = wis.WheelsDampingCompression; wheel.FrictionSlip = wis.FrictionSlip; wheel.RollInfluence = wis.RollInfluence; } BodyCustomData bd = (BodyCustomData)carChassis.UserObject; bd.Vehicle = vehicle; this.persistedList.Append(createBodyResult.Item1, createBodyResult.Item2); } } List <RigidBody> bodies = this.persistedList.Bodies; this.vehicleOutput.SliceCount = bodies.Count; this.chassisOutput.SliceCount = bodies.Count; for (int i = 0; i < bodies.Count; i++) { BodyCustomData bd = (BodyCustomData)bodies[i].UserObject; this.vehicleOutput[i] = bd.Vehicle; this.chassisOutput[i] = bodies[i]; } } } else { this.vehicleOutput.SliceCount = 0; this.chassisOutput.SliceCount = 0; } }
protected override void OnInitializePhysics() { SetupEmptyDynamicsWorld(); CollisionShape groundShape = new BoxShape(50, 1, 50); //CollisionShape groundShape = new StaticPlaneShape(Vector3.UnitY, 40); CollisionShapes.Add(groundShape); RigidBody body = LocalCreateRigidBody(0, Matrix.Translation(0, -16, 0), groundShape); body.UserObject = "Ground"; CollisionShape shape = new BoxShape(new Vector3(CubeHalfExtents)); CollisionShapes.Add(shape); const float THETA = (float)Math.PI / 4.0f; float L_1 = 2 - (float)Math.Tan(THETA); float L_2 = 1 / (float)Math.Cos(THETA); float RATIO = L_2 / L_1; RigidBody bodyA; RigidBody bodyB; CollisionShape cylA = new CylinderShape(0.2f, 0.25f, 0.2f); CollisionShape cylB = new CylinderShape(L_1, 0.025f, L_1); CompoundShape cyl0 = new CompoundShape(); cyl0.AddChildShape(Matrix.Identity, cylA); cyl0.AddChildShape(Matrix.Identity, cylB); float mass = 6.28f; Vector3 localInertia; cyl0.CalculateLocalInertia(mass, out localInertia); RigidBodyConstructionInfo ci = new RigidBodyConstructionInfo(mass, null, cyl0, localInertia); ci.StartWorldTransform = Matrix.Translation(-8, 1, -8); body = new RigidBody(ci); //1,0,cyl0,localInertia); World.AddRigidBody(body); body.LinearFactor = Vector3.Zero; body.AngularFactor = new Vector3(0, 1, 0); bodyA = body; cylA = new CylinderShape(0.2f, 0.26f, 0.2f); cylB = new CylinderShape(L_2, 0.025f, L_2); cyl0 = new CompoundShape(); cyl0.AddChildShape(Matrix.Identity, cylA); cyl0.AddChildShape(Matrix.Identity, cylB); mass = 6.28f; cyl0.CalculateLocalInertia(mass, out localInertia); ci = new RigidBodyConstructionInfo(mass, null, cyl0, localInertia); Quaternion orn = Quaternion.RotationAxis(new Vector3(0, 0, 1), -THETA); ci.StartWorldTransform = Matrix.RotationQuaternion(orn) * Matrix.Translation(-10, 2, -8); body = new RigidBody(ci);//1,0,cyl0,localInertia); body.LinearFactor = Vector3.Zero; HingeConstraint hinge = new HingeConstraint(body, Vector3.Zero, new Vector3(0, 1, 0), true); World.AddConstraint(hinge); bodyB = body; body.AngularVelocity = new Vector3(0, 3, 0); World.AddRigidBody(body); Vector3 axisA = new Vector3(0, 1, 0); Vector3 axisB = new Vector3(0, 1, 0); orn = Quaternion.RotationAxis(new Vector3(0, 0, 1), -THETA); Matrix mat = Matrix.RotationQuaternion(orn); axisB = new Vector3(mat.M21, mat.M22, mat.M23); GearConstraint gear = new GearConstraint(bodyA, bodyB, axisA, axisB, RATIO); World.AddConstraint(gear, true); mass = 1.0f; RigidBody body0 = LocalCreateRigidBody(mass, Matrix.Translation(0, 20, 0), shape); RigidBody body1 = null;//LocalCreateRigidBody(mass, Matrix.Translation(2*CUBE_HALF_EXTENTS,20,0), shape); //RigidBody body1 = LocalCreateRigidBody(0, Matrix.Translation(2*CUBE_HALF_EXTENTS,20,0), null); //body1.ActivationState = ActivationState.DisableDeactivation; //body1.SetDamping(0.3f, 0.3f); Vector3 pivotInA = new Vector3(CubeHalfExtents, -CubeHalfExtents, -CubeHalfExtents); Vector3 axisInA = new Vector3(0, 0, 1); Vector3 pivotInB; if (body1 != null) { Matrix transform = Matrix.Invert(body1.CenterOfMassTransform) * body0.CenterOfMassTransform; pivotInB = Vector3.TransformCoordinate(pivotInA, transform); } else { pivotInB = pivotInA; } Vector3 axisInB; if (body1 != null) { Matrix transform = Matrix.Invert(body1.CenterOfMassTransform) * body1.CenterOfMassTransform; axisInB = Vector3.TransformCoordinate(axisInA, transform); } else { axisInB = Vector3.TransformCoordinate(axisInA, body0.CenterOfMassTransform); } #if P2P { TypedConstraint p2p = new Point2PointConstraint(body0, pivotInA); //TypedConstraint p2p = new Point2PointConstraint(body0, body1, pivotInA, pivotInB); //TypedConstraint hinge = new HingeConstraint(body0, body1, pivotInA, pivotInB, axisInA, axisInB); World.AddConstraint(p2p); p2p.DebugDrawSize = 5; } #else { hinge = new HingeConstraint(body0, pivotInA, axisInA); //use zero targetVelocity and a small maxMotorImpulse to simulate joint friction //float targetVelocity = 0.f; //float maxMotorImpulse = 0.01; const float targetVelocity = 1.0f; const float maxMotorImpulse = 1.0f; hinge.EnableAngularMotor(true, targetVelocity, maxMotorImpulse); World.AddConstraint(hinge); hinge.DebugDrawSize = 5; } #endif RigidBody pRbA1 = LocalCreateRigidBody(mass, Matrix.Translation(-20, 0, 30), shape); //RigidBody pRbA1 = LocalCreateRigidBody(0.0f, Matrix.Translation(-20, 0, 30), shape); pRbA1.ActivationState = ActivationState.DisableDeactivation; // add dynamic rigid body B1 RigidBody pRbB1 = LocalCreateRigidBody(mass, Matrix.Translation(-20, 0, 30), shape); //RigidBody pRbB1 = LocalCreateRigidBody(0.0f, Matrix.Translation(-20, 0, 30), shape); pRbB1.ActivationState = ActivationState.DisableDeactivation; // create slider constraint between A1 and B1 and add it to world SliderConstraint spSlider1 = new SliderConstraint(pRbA1, pRbB1, Matrix.Identity, Matrix.Identity, true); //spSlider1 = new SliderConstraint(pRbA1, pRbB1, Matrix.Identity, Matrix.Identity, false); spSlider1.LowerLinearLimit = -15.0f; spSlider1.UpperLinearLimit = -5.0f; spSlider1.LowerLinearLimit = 5.0f; spSlider1.UpperLinearLimit = 15.0f; spSlider1.LowerLinearLimit = -10.0f; spSlider1.UpperLinearLimit = -10.0f; spSlider1.LowerAngularLimit = -(float)Math.PI / 3.0f; spSlider1.UpperAngularLimit = (float)Math.PI / 3.0f; World.AddConstraint(spSlider1, true); spSlider1.DebugDrawSize = 5.0f; //create a slider, using the generic D6 constraint Vector3 sliderWorldPos = new Vector3(0, 10, 0); Vector3 sliderAxis = Vector3.UnitX; const float angle = 0; //SIMD_RADS_PER_DEG * 10.f; Matrix trans = Matrix.RotationAxis(sliderAxis, angle) * Matrix.Translation(sliderWorldPos); d6body0 = LocalCreateRigidBody(mass, trans, shape); d6body0.ActivationState = ActivationState.DisableDeactivation; RigidBody fixedBody1 = LocalCreateRigidBody(0, trans, null); World.AddRigidBody(fixedBody1); Matrix frameInA = Matrix.Translation(0, 5, 0); Matrix frameInB = Matrix.Translation(0, 5, 0); //bool useLinearReferenceFrameA = false;//use fixed frame B for linear llimits const bool useLinearReferenceFrameA = true; //use fixed frame A for linear llimits spSlider6Dof = new Generic6DofConstraint(fixedBody1, d6body0, frameInA, frameInB, useLinearReferenceFrameA) { LinearLowerLimit = lowerSliderLimit, LinearUpperLimit = hiSliderLimit, //range should be small, otherwise singularities will 'explode' the constraint //AngularLowerLimit = new Vector3(-1.5f,0,0), //AngularUpperLimit = new Vector3(1.5f,0,0), //AngularLowerLimit = new Vector3(0,0,0), //AngularUpperLimit = new Vector3(0,0,0), AngularLowerLimit = new Vector3((float)-Math.PI, 0, 0), AngularUpperLimit = new Vector3(1.5f, 0, 0) }; //spSlider6Dof.TranslationalLimitMotor.EnableMotor[0] = true; spSlider6Dof.TranslationalLimitMotor.TargetVelocity = new Vector3(-5.0f, 0, 0); spSlider6Dof.TranslationalLimitMotor.MaxMotorForce = new Vector3(0.1f, 0, 0); World.AddConstraint(spSlider6Dof); spSlider6Dof.DebugDrawSize = 5; // create a door using hinge constraint attached to the world CollisionShape pDoorShape = new BoxShape(2.0f, 5.0f, 0.2f); CollisionShapes.Add(pDoorShape); RigidBody pDoorBody = LocalCreateRigidBody(1.0f, Matrix.Translation(-5.0f, -2.0f, 0.0f), pDoorShape); pDoorBody.ActivationState = ActivationState.DisableDeactivation; Vector3 btPivotA = new Vector3(10.0f + 2.1f, -2.0f, 0.0f); // right next to the door slightly outside Vector3 btAxisA = Vector3.UnitY; // pointing upwards, aka Y-axis spDoorHinge = new HingeConstraint(pDoorBody, btPivotA, btAxisA); //spDoorHinge.SetLimit(0.0f, (float)Math.PI / 2); // test problem values //spDoorHinge.SetLimit(-(float)Math.PI, (float)Math.PI * 0.8f); //spDoorHinge.SetLimit(1, -1); //spDoorHinge.SetLimit(-(float)Math.PI * 0.8f, (float)Math.PI); //spDoorHinge.SetLimit(-(float)Math.PI * 0.8f, (float)Math.PI, 0.9f, 0.3f, 0.0f); //spDoorHinge.SetLimit(-(float)Math.PI * 0.8f, (float)Math.PI, 0.9f, 0.01f, 0.0f); // "sticky limits" spDoorHinge.SetLimit(-(float)Math.PI * 0.25f, (float)Math.PI * 0.25f); //spDoorHinge.SetLimit(0, 0); World.AddConstraint(spDoorHinge); spDoorHinge.DebugDrawSize = 5; RigidBody pDropBody = LocalCreateRigidBody(10.0f, Matrix.Translation(-5.0f, 2.0f, 0.0f), shape); // create a generic 6DOF constraint //RigidBody pBodyA = LocalCreateRigidBody(mass, Matrix.Translation(10.0f, 6.0f, 0), shape); RigidBody pBodyA = LocalCreateRigidBody(0, Matrix.Translation(10, 6, 0), shape); //RigidBody pBodyA = LocalCreateRigidBody(0, Matrix.Translation(10, 6, 0), null); pBodyA.ActivationState = ActivationState.DisableDeactivation; RigidBody pBodyB = LocalCreateRigidBody(mass, Matrix.Translation(0, 6, 0), shape); //RigidBody pBodyB = LocalCreateRigidBody(0, Matrix.Translation(0, 6, 0), shape); pBodyB.ActivationState = ActivationState.DisableDeactivation; frameInA = Matrix.Translation(-5, 0, 0); frameInB = Matrix.Translation(5, 0, 0); Generic6DofConstraint pGen6DOF = new Generic6DofConstraint(pBodyA, pBodyB, frameInA, frameInB, true); //Generic6DofConstraint pGen6DOF = new Generic6DofConstraint(pBodyA, pBodyB, frameInA, frameInB, false); pGen6DOF.LinearLowerLimit = new Vector3(-10, -2, -1); pGen6DOF.LinearUpperLimit = new Vector3(10, 2, 1); //pGen6DOF.LinearLowerLimit = new Vector3(-10, 0, 0); //pGen6DOF.LinearUpperLimit = new Vector3(10, 0, 0); //pGen6DOF.LinearLowerLimit = new Vector3(0, 0, 0); //pGen6DOF.LinearUpperLimit = new Vector3(0, 0, 0); //pGen6DOF.TranslationalLimitMotor.EnableMotor[0] = true; //pGen6DOF.TranslationalLimitMotor.TargetVelocity = new Vector3(5, 0, 0); //pGen6DOF.TranslationalLimitMotor.MaxMotorForce = new Vector3(0.1f, 0, 0); //pGen6DOF.AngularLowerLimit = new Vector3(0, (float)Math.PI * 0.9f, 0); //pGen6DOF.AngularUpperLimit = new Vector3(0, -(float)Math.PI * 0.9f, 0); //pGen6DOF.AngularLowerLimit = new Vector3(0, 0, -(float)Math.PI); //pGen6DOF.AngularUpperLimit = new Vector3(0, 0, (float)Math.PI); pGen6DOF.AngularLowerLimit = new Vector3(-(float)Math.PI / 4, -0.75f, -(float)Math.PI * 0.4f); pGen6DOF.AngularUpperLimit = new Vector3((float)Math.PI / 4, 0.75f, (float)Math.PI * 0.4f); //pGen6DOF.AngularLowerLimit = new Vector3(0, -0.75f, (float)Math.PI * 0.8f); //pGen6DOF.AngularUpperLimit = new Vector3(0, 0.75f, -(float)Math.PI * 0.8f); //pGen6DOF.AngularLowerLimit = new Vector3(0, -(float)Math.PI * 0.8f, (float)Math.PI * 1.98f); //pGen6DOF.AngularUpperLimit = new Vector3(0, (float)Math.PI * 0.8f, -(float)Math.PI * 1.98f); //pGen6DOF.AngularLowerLimit = new Vector3(-0.75f, -0.5f, -0.5f); //pGen6DOF.AngularUpperLimit = new Vector3(0.75f, 0.5f, 0.5f); //pGen6DOF.AngularLowerLimit = new Vector3(-0.75f, 0, 0); //pGen6DOF.AngularUpperLimit = new Vector3(0.75f, 0, 0); //pGen6DOF.AngularLowerLimit = new Vector3(0, -0.7f, 0); //pGen6DOF.AngularUpperLimit = new Vector3(0, 0.7f, 0); //pGen6DOF.AngularLowerLimit = new Vector3(-1, 0, 0); //pGen6DOF.AngularUpperLimit = new Vector3(1, 0, 0); // create a ConeTwist constraint pBodyA = LocalCreateRigidBody(1.0f, Matrix.Translation(-10, 5, 0), shape); //pBodyA = LocalCreateRigidBody(0, Matrix.Translation(-10, 5, 0), shape); pBodyA.ActivationState = ActivationState.DisableDeactivation; pBodyB = LocalCreateRigidBody(0, Matrix.Translation(-10, -5, 0), shape); //pBodyB = LocalCreateRigidBody(1.0f, Matrix.Translation(-10, -5, 0), shape); frameInA = Matrix.RotationYawPitchRoll(0, 0, (float)Math.PI / 2); frameInA *= Matrix.Translation(0, -5, 0); frameInB = Matrix.RotationYawPitchRoll(0, 0, (float)Math.PI / 2); frameInB *= Matrix.Translation(0, 5, 0); coneTwist = new ConeTwistConstraint(pBodyA, pBodyB, frameInA, frameInB); //coneTwist.SetLimit((float)Math.PI / 4, (float)Math.PI / 4, (float)Math.PI * 0.8f); //coneTwist.SetLimit((((float)Math.PI / 4) * 0.6f), (float)Math.PI / 4, (float)Math.PI * 0.8f, 1.0f); // soft limit == hard limit coneTwist.SetLimit((((float)Math.PI / 4) * 0.6f), (float)Math.PI / 4, (float)Math.PI * 0.8f, 0.5f); World.AddConstraint(coneTwist, true); coneTwist.DebugDrawSize = 5; // Hinge connected to the world, with motor (to hinge motor with new and old constraint solver) RigidBody pBody = LocalCreateRigidBody(1.0f, Matrix.Identity, shape); pBody.ActivationState = ActivationState.DisableDeactivation; Vector3 pivotA = new Vector3(10.0f, 0.0f, 0.0f); btAxisA = new Vector3(0.0f, 0.0f, 1.0f); HingeConstraint pHinge = new HingeConstraint(pBody, pivotA, btAxisA); //pHinge.EnableAngularMotor(true, -1.0f, 0.165f); // use for the old solver pHinge.EnableAngularMotor(true, -1.0f, 1.65f); // use for the new SIMD solver World.AddConstraint(pHinge); pHinge.DebugDrawSize = 5; // create a universal joint using generic 6DOF constraint // create two rigid bodies // static bodyA (parent) on top: pBodyA = LocalCreateRigidBody(0, Matrix.Translation(20, 4, 0), shape); pBodyA.ActivationState = ActivationState.DisableDeactivation; // dynamic bodyB (child) below it : pBodyB = LocalCreateRigidBody(1.0f, Matrix.Translation(20, 0, 0), shape); pBodyB.ActivationState = ActivationState.DisableDeactivation; // add some (arbitrary) data to build constraint frames Vector3 parentAxis = new Vector3(1, 0, 0); Vector3 childAxis = new Vector3(0, 0, 1); Vector3 anchor = new Vector3(20, 2, 0); UniversalConstraint pUniv = new UniversalConstraint(pBodyA, pBodyB, anchor, parentAxis, childAxis); pUniv.SetLowerLimit(-(float)Math.PI / 4, -(float)Math.PI / 4); pUniv.SetUpperLimit((float)Math.PI / 4, (float)Math.PI / 4); // add constraint to world World.AddConstraint(pUniv, true); // draw constraint frames and limits for debugging pUniv.DebugDrawSize = 5; World.AddConstraint(pGen6DOF, true); pGen6DOF.DebugDrawSize = 5; // create a generic 6DOF constraint with springs pBodyA = LocalCreateRigidBody(0, Matrix.Translation(-20, 16, 0), shape); pBodyA.ActivationState = ActivationState.DisableDeactivation; pBodyB = LocalCreateRigidBody(1.0f, Matrix.Translation(-10, 16, 0), shape); pBodyB.ActivationState = ActivationState.DisableDeactivation; frameInA = Matrix.Translation(10, 0, 0); frameInB = Matrix.Identity; Generic6DofSpringConstraint pGen6DOFSpring = new Generic6DofSpringConstraint(pBodyA, pBodyB, frameInA, frameInB, true) { LinearUpperLimit = new Vector3(5, 0, 0), LinearLowerLimit = new Vector3(-5, 0, 0), AngularLowerLimit = new Vector3(0, 0, -1.5f), AngularUpperLimit = new Vector3(0, 0, 1.5f), DebugDrawSize = 5 }; World.AddConstraint(pGen6DOFSpring, true); pGen6DOFSpring.EnableSpring(0, true); pGen6DOFSpring.SetStiffness(0, 39.478f); pGen6DOFSpring.SetDamping(0, 0.5f); pGen6DOFSpring.EnableSpring(5, true); pGen6DOFSpring.SetStiffness(5, 39.478f); pGen6DOFSpring.SetDamping(0, 0.3f); pGen6DOFSpring.SetEquilibriumPoint(); // create a Hinge2 joint // create two rigid bodies // static bodyA (parent) on top: pBodyA = LocalCreateRigidBody(0, Matrix.Translation(-20, 4, 0), shape); pBodyA.ActivationState = ActivationState.DisableDeactivation; // dynamic bodyB (child) below it : pBodyB = LocalCreateRigidBody(1.0f, Matrix.Translation(-20, 0, 0), shape); pBodyB.ActivationState = ActivationState.DisableDeactivation; // add some data to build constraint frames parentAxis = new Vector3(0, 1, 0); childAxis = new Vector3(1, 0, 0); anchor = new Vector3(-20, 0, 0); Hinge2Constraint pHinge2 = new Hinge2Constraint(pBodyA, pBodyB, anchor, parentAxis, childAxis); pHinge2.SetLowerLimit(-(float)Math.PI / 4); pHinge2.SetUpperLimit((float)Math.PI / 4); // add constraint to world World.AddConstraint(pHinge2, true); // draw constraint frames and limits for debugging pHinge2.DebugDrawSize = 5; // create a Hinge joint between two dynamic bodies // create two rigid bodies // static bodyA (parent) on top: pBodyA = LocalCreateRigidBody(1.0f, Matrix.Translation(-20, -2, 0), shape); pBodyA.ActivationState = ActivationState.DisableDeactivation; // dynamic bodyB: pBodyB = LocalCreateRigidBody(10.0f, Matrix.Translation(-30, -2, 0), shape); pBodyB.ActivationState = ActivationState.DisableDeactivation; // add some data to build constraint frames axisA = new Vector3(0, 1, 0); axisB = new Vector3(0, 1, 0); Vector3 pivotA2 = new Vector3(-5, 0, 0); Vector3 pivotB = new Vector3(5, 0, 0); spHingeDynAB = new HingeConstraint(pBodyA, pBodyB, pivotA2, pivotB, axisA, axisB); spHingeDynAB.SetLimit(-(float)Math.PI / 4, (float)Math.PI / 4); // add constraint to world World.AddConstraint(spHingeDynAB, true); // draw constraint frames and limits for debugging spHingeDynAB.DebugDrawSize = 5; }
public CompoundShape GetFlatShape() { var result = new CompoundShape (); var pos = TileSizeYVector / 2f; result.AddTriangle (pos + TileSizeXVector / 2f, pos - TileSizeXVector / 2f, pos - TileSizeYVector / 2f); result.AddRectangle (pos - TileSizeXVector / 2f, pos + TileSizeXVector / 2f + TileSizeZVector); pos += TileSizeZVector; result.AddTriangle (pos - TileSizeXVector / 2f, pos + TileSizeXVector / 2f, pos + TileSizeYVector / 2f); return result; }