void Start()
    {
        meshes = new MeshBase[5];

        meshes[0] = AddGear();
        meshes[1] = AddStar();
        meshes[2] = AddBox();
        meshes[3] = AddPointedCircle();
        meshes[4] = AddTriangleMesh();

        int verticesCount = 0;

        foreach (MeshBase mesh in meshes)
        {
            verticesCount += mesh.Vertices.Length;

            mesh.AddHingeJoint(C_JM2D);
            mesh.SetCollidersEnabled(false);
        }
        allVertices = new Vector3[verticesCount];

        convexMesh = ConvexMesh.AddConvexMesh(Vector3.zero, GetUpdatedVertices(), convexMaterial, false);
        //move body back a bit
        convexMesh.transform.Translate(Vector3.forward * 0.1f);
    }
        public static ConvexShapeDesc CreateConvexHull(this Physics physics, StaticMeshData meshData)
        {
            // create descriptor for convex hull
            ConvexShapeDesc convexMeshShapeDesc = null;
            ConvexMeshDesc  convexMeshDesc      = new ConvexMeshDesc();

            convexMeshDesc.PinPoints <float>(meshData.Points, 0, sizeof(float) * 3);
            convexMeshDesc.PinTriangles <uint>(meshData.Indices, 0, sizeof(uint) * 3);
            convexMeshDesc.VertexCount   = (uint)meshData.Vertices.Length;
            convexMeshDesc.TriangleCount = (uint)meshData.TriangleCount;
            convexMeshDesc.Flags         = ConvexFlags.ComputeConvex;

            MemoryStream stream = new MemoryStream(1024);

            CookingInterface.InitCooking();

            if (CookingInterface.CookConvexMesh(convexMeshDesc, stream))
            {
                stream.Seek(0, SeekOrigin.Begin);
                ConvexMesh convexMesh = physics.CreateConvexMesh(stream);
                convexMeshShapeDesc = new ConvexShapeDesc(convexMesh);
                CookingInterface.CloseCooking();
            }

            convexMeshDesc.UnpinAll();
            return(convexMeshShapeDesc);
        }
    private MeshBase GetChoosenMesh(MeshCreator meshCreator)
    {
        switch (meshCreator.meshType)
        {
        case MeshCreator.MeshType.Triangle:
            return(TriangleMesh.AddTriangle(meshCreator.transform.position, meshCreator.triangleVertex1,
                                            meshCreator.triangleVertex2, meshCreator.triangleVertex3, Space.World, meshCreator.material,
                                            meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Rectangle:
            return(RectangleMesh.AddRectangle(meshCreator.transform.position, meshCreator.boxSize,
                                              meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Circle:
            return(CircleMesh.AddCircle(meshCreator.transform.position, meshCreator.circleRadius,
                                        meshCreator.circleSides, meshCreator.circleUseCircleCollider, meshCreator.material,
                                        meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Quadrangle:
            Vector2[] verts = new Vector2[4] {
                meshCreator.quadrangleVertex1, meshCreator.quadrangleVertex2,
                meshCreator.quadrangleVertex3, meshCreator.quadrangleVertex4
            };
            return(QuadrangleMesh.AddQuadrangle(meshCreator.transform.position, verts, Space.World,
                                                meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Ellipse:
            return(EllipseMesh.AddEllipse(meshCreator.transform.position, meshCreator.ellipseHorizontalRadius,
                                          meshCreator.ellipseVerticalRadius, meshCreator.ellipseSides, meshCreator.material,
                                          meshCreator.attachRigidbody));

        case MeshCreator.MeshType.PointedCircle:
            return(PointedCircleMesh.AddPointedCircle(meshCreator.transform.position, meshCreator.pointedCircleRadius,
                                                      meshCreator.pointedCircleSides, meshCreator.pointedCircleShift, meshCreator.material,
                                                      meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Cake:
            return(CakeMesh.AddCakeMesh(meshCreator.transform.position, meshCreator.cakeRadius, meshCreator.cakeSides,
                                        meshCreator.cakeSidesToFill, meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Convex:
            return(ConvexMesh.AddConvexMesh(meshCreator.transform.position,
                                            MeshHelper.ConvertVec2ToVec3(meshCreator.convexPoints), Space.World,
                                            meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Star:
            return(StarMesh.AddStar(meshCreator.transform.position, meshCreator.starRadiusA, meshCreator.starRadiusB,
                                    meshCreator.starSides, meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Gear:
            return(GearMesh.AddGear(meshCreator.transform.position, meshCreator.gearInnerRadius, meshCreator.gearRootRadius,
                                    meshCreator.gearOuterRadius, meshCreator.gearSides, meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Line:
            return(LineMesh.AddLine(meshCreator.transform.position, meshCreator.linePoints.ToArray(), meshCreator.lineWidth,
                                    meshCreator.lineUseDoubleCollider, Space.World, meshCreator.material, meshCreator.attachRigidbody));
        }
        return(null);
    }
    private void AddConvex(Vector3 pos)
    {
        Vector3[] verts = new Vector3[20];
        for (int i = 0; i < verts.Length; i++)
        {
            float x = Random.Range(-1f, 1f);
            float y = Random.Range(-1f, 1f);
            verts[i] = new Vector3(x, y);
        }

        ConvexMesh convex = ConvexMesh.AddConvexMesh(pos, verts, Space.Self, material);

        convex.SetTexture(uvGridTexture);
    }
        public PxGhRigidStaticCMesh(Plane plane, List <Mesh> meshes, Material material)
        {
            ghMeshes = new List <GH_Mesh>();
            List <Mesh> initialMeshes = new List <Mesh>(meshes);

            actor = PhysXManager.Physics.CreateRigidStatic();

            foreach (Mesh initialMesh in initialMeshes)
            {
                Mesh meshLocal = initialMesh.DuplicateMesh();
                meshLocal.Transform(Transform.PlaneToPlane(plane, Plane.WorldXY));

                List <Vector3> points = new List <Vector3>();
                foreach (Point3d v in meshLocal.Vertices)
                {
                    points.Add(new Vector3((float)v.X, (float)v.Y, (float)v.Z));
                }

                List <int> faceVertexIndices = new List <int>();
                foreach (MeshFace face in meshLocal.Faces)
                {
                    faceVertexIndices.Add(face.A);
                    faceVertexIndices.Add(face.B);
                    faceVertexIndices.Add(face.C);
                }

                ConvexMeshDesc convexMeshDescription = new ConvexMeshDesc();
                convexMeshDescription.Flags = ConvexFlag.ComputeConvex;
                convexMeshDescription.SetPositions(points.ToArray());
                convexMeshDescription.SetTriangles(faceVertexIndices.ToArray());

                MemoryStream memoryStream = new MemoryStream();
                PhysXManager.Physics.CreateCooking().CookConvexMesh(convexMeshDescription, memoryStream);
                memoryStream.Position = 0;

                ConvexMesh         convexMesh         = PhysXManager.Physics.CreateConvexMesh(memoryStream);
                ConvexMeshGeometry convexMeshGeometry = new ConvexMeshGeometry(convexMesh);

                actor.CreateShape(convexMeshGeometry, material);

                ghMeshes.Add(new GH_Mesh(meshLocal));
            }

            actor.GlobalPose = plane.ToMatrix();
        }
Example #6
0
        public PxGhRigidDynamiCompoundConvexMesh(List <Mesh> meshes, Plane frame, Material material, float mass, Vector3d initialLinearVelocity, Vector3d initialAngularVelocity)
            : base(frame, initialLinearVelocity, initialAngularVelocity)
        {
            DisplayMeshes = new List <Mesh>(meshes);

            foreach (Mesh mesh in DisplayMeshes)
            {
                mesh.Transform(Transform.PlaneToPlane(frame, Plane.WorldXY));

                Vector3[] vertices = new Vector3[mesh.Vertices.Count];
                for (int i = 0; i < vertices.Length; i++)
                {
                    vertices[i] = mesh.Vertices[i].ToSystemVector();
                }

                int[] faceVertexIndices = new int[mesh.Faces.Count * 3];
                for (int i = 0; i < mesh.Faces.Count; i++)
                {
                    MeshFace face = mesh.Faces[i];
                    faceVertexIndices[3 * i + 0] = face.A;
                    faceVertexIndices[3 * i + 1] = face.B;
                    faceVertexIndices[3 * i + 2] = face.C;
                }

                ConvexMeshDesc convexMeshDescription = new ConvexMeshDesc();
                convexMeshDescription.Flags = ConvexFlag.ComputeConvex;
                convexMeshDescription.SetPositions(vertices);
                convexMeshDescription.SetTriangles(faceVertexIndices);

                MemoryStream memoryStream = new MemoryStream();
                PxGhManager.Physics.CreateCooking().CookConvexMesh(convexMeshDescription, memoryStream);
                memoryStream.Position = 0;

                ConvexMesh         convexMesh         = PxGhManager.Physics.CreateConvexMesh(memoryStream);
                ConvexMeshGeometry convexMeshGeometry = new ConvexMeshGeometry(convexMesh);

                Actor.CreateShape(convexMeshGeometry, material);
            }

            Actor.SetMassAndUpdateInertia(mass);
        }
Example #7
0
    void Start()
    {
        meshes = new MeshBase[5];

        meshes[0] = AddGear();
        meshes[1] = AddStar();
        meshes[2] = AddBox();
        meshes[3] = AddPointedCircle();
        meshes[4] = AddTriangleMesh();

        int v = 0;

        for (int i = 0; i < meshes.Length; i++)
        {
            v += meshes[i].Vertices.Length;

            meshes[i].AddHingeJoint(C_JM2D);
            meshes[i].SetCollidersEnabled(false);
        }
        allVertices = new Vector3[v];

        convexMesh = ConvexMesh.AddConvexMesh(Vector3.zero, UpdateVertices(), Space.World, convexMaterial, false);
        convexMesh.C_MR.sortingOrder = -1;
    }
Example #8
0
		private void CreateVehicle4WSimulationData(
			float chassisMass,
			ConvexMesh chassisConvexMesh,
			float wheelMass, 
			ConvexMesh[] wheelConvexMeshes, 
			Vector3[] wheelCentreOffsets,
			VehicleWheelsSimData wheelsData, 
			VehicleDriveSimData4W driveData, 
			VehicleChassisData chassisData)
		{
			const int TIRE_TYPE_SLICKS = 0;

			//Extract the chassis AABB dimensions from the chassis convex mesh.
			//Vector3 chassisDims = computeChassisAABBDimensions(chassisConvexMesh);
			Vector3 chassisDims = new Vector3(10, 10, 10);

			//The origin is at the center of the chassis mesh.
			//Set the center of mass to be below this point and a little towards the front.
			Vector3 chassisCMOffset = new Vector3(0.0f, -chassisDims.Y * 0.5f + 0.65f, 0.25f);

			//Now compute the chassis mass and moment of inertia.
			//Use the moment of inertia of a cuboid as an approximate value for the chassis moi.
			Vector3 chassisMOI = new Vector3
			(
				(chassisDims.Y * chassisDims.Y + chassisDims.Z * chassisDims.Z) * chassisMass / 12.0f,
				(chassisDims.X * chassisDims.X + chassisDims.Z * chassisDims.Z) * chassisMass / 12.0f,
				(chassisDims.X * chassisDims.X + chassisDims.Y * chassisDims.Y) * chassisMass / 12.0f
			);

			//A bit of tweaking here.  The car will have more responsive turning if we reduce the
			//y-component of the chassis moment of inertia.
			chassisMOI.Y *= 0.8f;

			//Let's set up the chassis data structure now.
			chassisData.Mass = chassisMass;
			chassisData.MomentOfInertia = chassisMOI;
			chassisData.CenterOfMassOffset = chassisCMOffset;

			//Work out the front/rear mass split from the cm offset.
			//This is a very approximate calculation with lots of assumptions.
			//massRear*zRear + massFront*zFront = mass*cm           (1)
			//massRear       + massFront        = mass                      (2)
			//Rearrange (2)
			//massFront = mass - massRear                                           (3)
			//Substitute (3) into (1)
			//massRear(zRear - zFront) + mass*zFront = mass*cm      (4)
			//Solve (4) for massRear
			//massRear = mass(cm - zFront)/(zRear-zFront)           (5)
			//Now we also have
			//zFront = (z-cm)/2                                                                     (6a)
			//zRear = (-z-cm)/2                                                                     (6b)
			//Substituting (6a-b) into (5) gives
			//massRear = 0.5*mass*(z-3cm)/z                                         (7)
			float massRear = 0.5f * chassisMass * (chassisDims.Z - 3 * chassisCMOffset.Z) / chassisDims.Z;
			float massFront = chassisMass - massRear;

			//Extract the wheel radius and width from the wheel convex meshes.
			float[] wheelWidths = new float[4];
			float[] wheelRadii = new float[4];
			//ComputeWheelWidthsAndRadii(wheelConvexMeshes, wheelWidths, wheelRadii);
			wheelWidths = new[] { 3f, 3, 3, 3 };
			wheelRadii = new[] { 1f, 1, 1, 1 };

			//Now compute the wheel masses and inertias components around the axle's axis.
			//http://en.wikipedia.org/wiki/List_of_moments_of_inertia
			float[] wheelMOIs = new float[4];
			for (int i = 0; i < 4; i++)
			{
				wheelMOIs[i] = 0.5f * wheelMass * wheelRadii[i] * wheelRadii[i];
			}
			//Let's set up the wheel data structures now with radius, mass, and moi.
			VehicleWheelData[] wheels = new VehicleWheelData[4]
			{
				new VehicleWheelData(),
				new VehicleWheelData(),
				new VehicleWheelData(),
				new VehicleWheelData()
			};
			for (int i = 0; i < 4; i++)
			{
				wheels[i].Radius = wheelRadii[i];
				wheels[i].Mass = wheelMass;
				wheels[i].MomentOfInertia = wheelMOIs[i];
				wheels[i].Width = wheelWidths[i];
			}
			//Disable the handbrake from the front wheels and enable for the rear wheels
			wheels[(int)VehicleWheelOrdering.FrontLeft].MaxHandBrakeTorque = 0.0f;
			wheels[(int)VehicleWheelOrdering.FrontRight].MaxHandBrakeTorque = 0.0f;
			wheels[(int)VehicleWheelOrdering.RearLeft].MaxHandBrakeTorque = 4000.0f;
			wheels[(int)VehicleWheelOrdering.RearRight].MaxHandBrakeTorque = 4000.0f;
			//Enable steering for the front wheels and disable for the front wheels.
			wheels[(int)VehicleWheelOrdering.FrontLeft].MaxSteer = (float)System.Math.PI * 0.3333f;
			wheels[(int)VehicleWheelOrdering.FrontRight].MaxSteer = (float)System.Math.PI * 0.3333f;
			wheels[(int)VehicleWheelOrdering.RearLeft].MaxSteer = 0.0f;
			wheels[(int)VehicleWheelOrdering.RearRight].MaxSteer = 0.0f;

			//Let's set up the tire data structures now.
			//Put slicks on the front tires and wets on the rear tires.
			VehicleTireData[] tires = new VehicleTireData[4]
			{
				new VehicleTireData(),
				new VehicleTireData(),
				new VehicleTireData(),
				new VehicleTireData()
			};
			tires[(int)VehicleWheelOrdering.FrontLeft].Type = TIRE_TYPE_SLICKS;
			tires[(int)VehicleWheelOrdering.FrontRight].Type = TIRE_TYPE_SLICKS;
			tires[(int)VehicleWheelOrdering.RearLeft].Type = TIRE_TYPE_SLICKS;
			tires[(int)VehicleWheelOrdering.RearRight].Type = TIRE_TYPE_SLICKS;

			//Let's set up the suspension data structures now.
			VehicleSuspensionData[] susps = new VehicleSuspensionData[4]
			{
				new VehicleSuspensionData(),
				new VehicleSuspensionData(),
				new VehicleSuspensionData(),
				new VehicleSuspensionData()
			};
			for (int i = 0; i < 4; i++)
			{
				susps[i].MaxCompression = 0.3f;
				susps[i].MaxDroop = 0.1f;
				susps[i].SpringStrength = 35000.0f;
				susps[i].SpringDamperRate = 4500.0f;
			}
			susps[(int)VehicleWheelOrdering.FrontLeft].SprungMass = massFront * 0.5f;
			susps[(int)VehicleWheelOrdering.FrontRight].SprungMass = massFront * 0.5f;
			susps[(int)VehicleWheelOrdering.RearLeft].SprungMass = massRear * 0.5f;
			susps[(int)VehicleWheelOrdering.RearRight].SprungMass = massRear * 0.5f;

			//We need to set up geometry data for the suspension, wheels, and tires.
			//We already know the wheel centers described as offsets from the rigid body centre of mass.
			//From here we can approximate application points for the tire and suspension forces.
			//Lets assume that the suspension travel directions are absolutely vertical.
			//Also assume that we apply the tire and suspension forces 30cm below the centre of mass.
			Vector3[] suspTravelDirections = new Vector3[] { new Vector3(0, -1, 0), new Vector3(0, -1, 0), new Vector3(0, -1, 0), new Vector3(0, -1, 0) };
			Vector3[] wheelCentreCMOffsets = new Vector3[4];
			Vector3[] suspForceAppCMOffsets = new Vector3[4];
			Vector3[] tireForceAppCMOffsets = new Vector3[4];
			for (int i = 0; i < 4; i++)
			{
				wheelCentreCMOffsets[i] = wheelCentreOffsets[i] - chassisCMOffset;
				suspForceAppCMOffsets[i] = new Vector3(wheelCentreCMOffsets[i].X, -0.3f, wheelCentreCMOffsets[i].Z);
				tireForceAppCMOffsets[i] = new Vector3(wheelCentreCMOffsets[i].X, -0.3f, wheelCentreCMOffsets[i].Z);
			}

			//Now add the wheel, tire and suspension data.
			for (int i = 0; i < 4; i++)
			{
				wheelsData.SetWheelData(i, wheels[i]);
				wheelsData.SetTireData(i, tires[i]);
				wheelsData.SetSuspensionData(i, susps[i]);
				wheelsData.SetSuspensionTravelDirection(i, suspTravelDirections[i]);
				wheelsData.SetWheelCentreOffset(i, wheelCentreCMOffsets[i]);
				wheelsData.SetSuspensionForceApplicationPointOffset(i, suspForceAppCMOffsets[i]);
				wheelsData.SetTireForceApplicationPointOffset(i, tireForceAppCMOffsets[i]);
			}

			//Now set up the differential, engine, gears, clutch, and ackermann steering.

			//Diff
			VehicleDifferential4WData diff = new VehicleDifferential4WData();
			diff.Type = VehicleDifferentialType.LimitedSlip4WheelDrive;
			driveData.SetDifferentialData(diff);

			//Engine
			VehicleEngineData engine = new VehicleEngineData()
			{
				PeakTorque = 500.0f,
				MaxOmega = 600.0f//approx 6000 rpm
			};
			driveData.SetEngineData(engine);

			//Gears
			VehicleGearsData gears = new VehicleGearsData()
			{
				SwitchTime = 0.5f
			};
			driveData.SetGearsData(gears);

			//Clutch
			VehicleClutchData clutch = new VehicleClutchData()
			{
				Strength = 10.0f
			};
			driveData.SetClutchData(clutch);

			//Ackermann steer accuracy
			var ackermann = new VehicleAckermannGeometryData()
			{
				Accuracy = 1.0f,
				AxleSeparation = wheelCentreOffsets[(int)VehicleWheelOrdering.FrontLeft].Z - wheelCentreOffsets[(int)VehicleWheelOrdering.RearLeft].Z,
				FrontWidth = wheelCentreOffsets[(int)VehicleWheelOrdering.FrontRight].X - wheelCentreOffsets[(int)VehicleWheelOrdering.FrontLeft].X,
				RearWidth = wheelCentreOffsets[(int)VehicleWheelOrdering.RearRight].X - wheelCentreOffsets[(int)VehicleWheelOrdering.RearLeft].X
			};
			driveData.SetAckermannGeometryData(ackermann);
		}
Example #9
0
 public Geometry(string id, string name, ConvexMesh convexMesh)
     : this(id, name)
 {
     this.convexMesh = convexMesh;
 }
    private MeshBase GetChoosenMesh(MeshCreator meshCreator)
    {
        float?minArea = meshCreator.splineSimplification != SplineSimplification.Type.None
            ? meshCreator.minAbsoluteSplineArea
            : (float?)null;

        switch (meshCreator.meshType)
        {
        case MeshCreator.MeshType.Triangle:
            return(TriangleMesh.AddTriangle(meshCreator.transform.position, meshCreator.triangleVertex1,
                                            meshCreator.triangleVertex2, meshCreator.triangleVertex3, Space.World, meshCreator.material,
                                            meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Rectangle:
            return(RectangleMesh.AddRectangle(meshCreator.transform.position, meshCreator.boxSize,
                                              meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Circle:
            return(CircleMesh.AddCircle(meshCreator.transform.position, meshCreator.circleRadius,
                                        meshCreator.circleSides, meshCreator.circleUseCircleCollider, meshCreator.material,
                                        meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Quadrangle:
            Vector2[] verts = new Vector2[4] {
                meshCreator.quadrangleVertex1, meshCreator.quadrangleVertex2,
                meshCreator.quadrangleVertex3, meshCreator.quadrangleVertex4
            };
            return(QuadrangleMesh.AddQuadrangle(meshCreator.transform.position, verts, Space.World,
                                                meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Ellipse:
            return(EllipseMesh.AddEllipse(meshCreator.transform.position, meshCreator.ellipseHorizontalRadius,
                                          meshCreator.ellipseVerticalRadius, meshCreator.ellipseSides, meshCreator.material,
                                          meshCreator.attachRigidbody));

        case MeshCreator.MeshType.PointedCircle:
            return(PointedCircleMesh.AddPointedCircle(meshCreator.transform.position, meshCreator.pointedCircleRadius,
                                                      meshCreator.pointedCircleSides, meshCreator.pointedCircleShift, meshCreator.material,
                                                      meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Cake:
            return(CakeMesh.AddCakeMesh(meshCreator.transform.position, meshCreator.cakeRadius, meshCreator.cakeSides,
                                        meshCreator.cakeSidesToFill, meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Convex:
            return(ConvexMesh.AddConvexMesh(meshCreator.transform.position,
                                            MeshHelper.ConvertVec2ToVec3(meshCreator.convexPoints),
                                            meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Star:
            return(StarMesh.AddStar(meshCreator.transform.position, meshCreator.starRadiusA, meshCreator.starRadiusB,
                                    meshCreator.starSides, meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Gear:
            return(GearMesh.AddGear(meshCreator.transform.position, meshCreator.gearInnerRadius, meshCreator.gearRootRadius,
                                    meshCreator.gearOuterRadius, meshCreator.gearSides, meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.Line:
            return(LineMesh.AddLine(meshCreator.transform.position, meshCreator.linePoints.ToArray(), meshCreator.lineWidth,
                                    meshCreator.lineUseDoubleCollider, Space.World, meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.TriangulatedMesh:
            return(TriangulatedMesh.Add(meshCreator.transform.position, meshCreator.triangulatedPoints.ToArray(),
                                        meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.SplineShape:
            return(SplineShapeMesh.AddSplineShape(meshCreator.transform.position, meshCreator.splinePoints.ToArray(), meshCreator.splineResolution,
                                                  minArea, Space.World, meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.SplineCurve:
            return(SplineCurveMesh.AddSplineCurve(meshCreator.transform.position, meshCreator.splineCurvePoints.ToArray(),
                                                  meshCreator.splineResolution, meshCreator.splineCurveWidth, meshCreator.splineCurveUseDoubleCollider, minArea,
                                                  Space.World, meshCreator.material, meshCreator.attachRigidbody));

        case MeshCreator.MeshType.SplineConvexShape:
            return(ConvexSplineMesh.AddConvexSpline(meshCreator.transform.position, meshCreator.convexSplinePoints.ToArray(),
                                                    meshCreator.splineResolution, minArea, Space.World, meshCreator.material, meshCreator.attachRigidbody));

        default:
            throw new System.ArgumentOutOfRangeException();
        }
    }
        /// <summary>Simple examples of all the PhysX bits running together</summary>
        private void LoadPhysics()
        {
            // The ground plane (if created) sould be the first actor
            _groundActor      = _scene.Actors.First();
            _groundActor.Name = "Default Ground Plane";

            //

            #region Some Boxes
            for (int x = 0; x < 5; x++)
            {
                BoxShapeDescription boxShapeDesc = new BoxShapeDescription(2, 3, 8);

                ActorDescription actorDesc = new ActorDescription()
                {
                    Name            = String.Format("Box {0}", x),
                    BodyDescription = new BodyDescription(10.0f),
                    GlobalPose      = Matrix.CreateTranslation(100, 15 + 3 * x, 20),
                    Shapes          = { boxShapeDesc }
                };

                Actor actor = _scene.CreateActor(actorDesc);
            }
            #endregion

            #region Cloth (Flag)
            {
                // Create a Grid of Points
                VertexGrid grid = VertexGrid.CreateGrid(10, 10);

                ClothMeshDescription clothMeshDesc = new ClothMeshDescription();
                clothMeshDesc.AllocateVertices <Vector3>(grid.Points.Length);
                clothMeshDesc.AllocateTriangles <int>(grid.Indices.Length / 3);

                clothMeshDesc.VertexCount   = grid.Points.Length;
                clothMeshDesc.TriangleCount = grid.Indices.Length / 3;

                clothMeshDesc.VerticesStream.SetData(grid.Points);
                clothMeshDesc.TriangleStream.SetData(grid.Indices);

                // We are using 32 bit integers, so make sure the 16 bit flag is removed.
                // 32 bits are the default, so this isn't technically needed
                clothMeshDesc.Flags &= ~MeshFlag.Indices16Bit;

                // Write the cooked data to memory
                MemoryStream memoryStream = new MemoryStream();

                Cooking.InitializeCooking();
                Cooking.CookClothMesh(clothMeshDesc, memoryStream);
                Cooking.CloseCooking();

                // Need to reset the position of the stream to the beginning
                memoryStream.Position = 0;

                ClothMesh clothMesh = _core.CreateClothMesh(memoryStream);

                //

                ClothDescription clothDesc = new ClothDescription()
                {
                    ClothMesh  = clothMesh,
                    Flags      = ClothFlag.Gravity | ClothFlag.Bending | ClothFlag.CollisionTwoway | ClothFlag.Visualization,
                    GlobalPose =
                        Matrix.CreateFromYawPitchRoll(0, (float)Math.PI / 2.0f, (float)Math.PI / 2.0f) *
                        Matrix.CreateTranslation(0, 20, 0)
                };
                clothDesc.MeshData.AllocatePositions <Vector3>(grid.Points.Length);
                clothDesc.MeshData.AllocateIndices <int>(grid.Indices.Length);

                clothDesc.MeshData.MaximumVertices = grid.Points.Length;
                clothDesc.MeshData.MaximumIndices  = grid.Indices.Length;

                clothDesc.MeshData.NumberOfVertices = grid.Points.Length;
                clothDesc.MeshData.NumberOfIndices  = grid.Indices.Length;

                _flag = _scene.CreateCloth(clothDesc);

                // Flag Pole
                ActorDescription flagPoleActorDesc = new ActorDescription()
                {
                    GlobalPose = Matrix.CreateTranslation(0, 10, 0),
                    Shapes     = { new BoxShapeDescription(1.0f, 20.0f, 1.0f) }
                };

                Actor flagPoleActor = _scene.CreateActor(flagPoleActorDesc);

                _flag.AttachToShape(flagPoleActor.Shapes[0], 0);
                _flag.WindAcceleration = new Vector3(10, 10, 10);
                _flag.BendingStiffness = 0.1f;
            }
            #endregion

            #region Revolute Joint
            {
                BoxShapeDescription boxShapeDescA = new BoxShapeDescription(3, 3, 3);
                BoxShapeDescription boxShapeDescB = new BoxShapeDescription(3, 3, 3);

                ActorDescription actorDescA = new ActorDescription()
                {
                    BodyDescription = new BodyDescription(10.0f),
                    GlobalPose      = Matrix.CreateTranslation(75, 1.5f, 55),
                    Shapes          = { boxShapeDescA }
                };
                Actor actorA = _scene.CreateActor(actorDescA);

                ActorDescription actorDescB = new ActorDescription()
                {
                    BodyDescription = new BodyDescription(10.0f),
                    GlobalPose      = Matrix.CreateTranslation(70, 1.5f, 55),
                    Shapes          = { boxShapeDescB }
                };
                Actor actorB = _scene.CreateActor(actorDescB);

                //

                RevoluteJointDescription revoluteJointDesc = new RevoluteJointDescription()
                {
                    Actor1 = actorA,
                    Actor2 = actorB,
                    Motor  = new MotorDescription(20, 20.1f, true)
                };
                revoluteJointDesc.Flags |= RevoluteJointFlag.MotorEnabled;
                revoluteJointDesc.SetGlobalAnchor(new Vector3(73.5f, 1.5f, 55));
                revoluteJointDesc.SetGlobalAxis(new Vector3(1, 0, 0));

                RevoluteJoint revoluteJoint = _scene.CreateJoint(revoluteJointDesc) as RevoluteJoint;
            }
            #endregion

            #region Prismatic Joint with Limit
            {
                Actor actorA, actorB;
                {
                    BoxShapeDescription boxShapeDesc = new BoxShapeDescription(3, 3, 3);

                    BodyDescription bodyDesc = new BodyDescription(10.0f);
                    bodyDesc.BodyFlags |= BodyFlag.Kinematic;

                    ActorDescription actorDesc = new ActorDescription()
                    {
                        BodyDescription = bodyDesc,
                        GlobalPose      = Matrix.CreateTranslation(70, 25, 65),
                        Shapes          = { boxShapeDesc }
                    };
                    actorA = _scene.CreateActor(actorDesc);
                }
                {
                    BoxShapeDescription boxShapeDesc = new BoxShapeDescription(3, 3, 3);

                    ActorDescription actorDesc = new ActorDescription()
                    {
                        BodyDescription = new BodyDescription(10.0f),
                        GlobalPose      = Matrix.CreateTranslation(70, 15, 65),
                        Shapes          = { boxShapeDesc }
                    };
                    actorB = _scene.CreateActor(actorDesc);
                }

                PrismaticJointDescription prismaticJointDesc = new PrismaticJointDescription()
                {
                    Actor1 = actorA,
                    Actor2 = actorB,
                };
                prismaticJointDesc.SetGlobalAnchor(new Vector3(70, 20, 65));
                prismaticJointDesc.SetGlobalAxis(new Vector3(0, 1, 0));

                PrismaticJoint prismaticJoint = _scene.CreateJoint(prismaticJointDesc) as PrismaticJoint;

                LimitPlane limitPlane = new LimitPlane(new Vector3(0, 1, 0), new Vector3(-30, 8, -30), 0);
                prismaticJoint.AddLimitPlane(limitPlane);
            }
            #endregion

            #region Fluid
            {
                const int maximumParticles = 1000;

                FluidEmitterDescription fluidEmitterDesc = new FluidEmitterDescription()
                {
                    DimensionX   = 0.5f,
                    DimensionY   = 0.5f,
                    Rate         = 15,
                    RelativePose = Matrix.CreateTranslation(-40, 10, 50),
                    Shape        = EmitterShape.Rectangular,
                    Type         = EmitterType.ConstantFlowRate,
                    RandomAngle  = 0.5f
                };
                fluidEmitterDesc.Flags |= (FluidEmitterFlag.Enabled | FluidEmitterFlag.Visualization);

                FluidDescription fluidDesc = new FluidDescription()
                {
                    Emitters         = { fluidEmitterDesc },
                    Flags            = FluidFlag.Enabled | FluidFlag.Visualization,
                    MaximumParticles = maximumParticles
                };
                fluidDesc.ParticleWriteData.AllocatePositionBuffer <Vector3>(maximumParticles);
                fluidDesc.ParticleWriteData.NumberOfParticles = maximumParticles;

                Fluid fluid = _scene.CreateFluid(fluidDesc);

                // Ledge
                {
                    BoxShapeDescription boxShapeDesc = new BoxShapeDescription(5, 0.1f, 5);

                    ActorDescription drainActorDesc = new ActorDescription()
                    {
                        GlobalPose = Matrix.CreateRotationX(0.5f) * Matrix.CreateTranslation(-40, 5, 52),
                        Shapes     = { boxShapeDesc }
                    };

                    Actor drianActor = _scene.CreateActor(drainActorDesc);
                }

                // Drain
                {
                    BoxShapeDescription boxShapeDesc = new BoxShapeDescription(5, 0.1f, 5);
                    boxShapeDesc.Flags |= ShapeFlag.FluidDrain;

                    ActorDescription drainActorDesc = new ActorDescription()
                    {
                        GlobalPose = Matrix.CreateTranslation(-40, 0, 55),
                        Shapes     = { boxShapeDesc }
                    };

                    Actor drianActor = _scene.CreateActor(drainActorDesc);
                }
            }
            #endregion

            #region Force Field
            {
                BoxForceFieldShapeDescription boxForceFieldShapeDesc = new BoxForceFieldShapeDescription()
                {
                    Size = new Vector3(10, 10, 10)
                };

                ForceFieldLinearKernelDescription kernelDesc = new ForceFieldLinearKernelDescription()
                {
                    Constant = new Vector3(0, 100.0f, 0)
                };

                ForceFieldLinearKernel kernel = _scene.CreateForceFieldLinearKernel(kernelDesc);

                ForceFieldShapeGroupDescription shapeGroupDesc = new ForceFieldShapeGroupDescription()
                {
                    Shapes = { boxForceFieldShapeDesc }
                };

                ForceFieldShapeGroup shapeGroup = _scene.CreateForceFieldShapeGroup(shapeGroupDesc);

                BoxForceFieldShape boxForceFieldShape = shapeGroup.CreateShape(boxForceFieldShapeDesc) as BoxForceFieldShape;
                boxForceFieldShape.Pose = Matrix.CreateTranslation(30, 5, 0);

                ForceFieldDescription forceFieldDesc = new ForceFieldDescription()
                {
                    Kernel      = kernel,
                    ShapeGroups = { shapeGroup }
                };
                ForceField forceField = _scene.CreateForceField(forceFieldDesc);
            }
            #endregion

            #region Heightfield
            {
                int rows    = 25;
                int columns = 25;

                HeightFieldSample[] samples = new HeightFieldSample[rows * columns];
                for (int r = 0; r < rows; r++)
                {
                    for (int c = 0; c < columns; c++)
                    {
                        // Put a z and x curve together
                        double h = Math.Sin(c) * Math.Cos(r) * short.MaxValue;

                        HeightFieldSample sample = new HeightFieldSample();
                        sample.Height           = (short)h;
                        sample.MaterialIndex0   = 0;
                        sample.MaterialIndex1   = 1;
                        sample.TessellationFlag = 0;

                        samples[r * columns + c] = sample;
                    }
                }

                HeightFieldDescription heightFieldDesc = new HeightFieldDescription()
                {
                    NumberOfRows    = rows,
                    NumberOfColumns = columns,
                    Samples         = samples
                };

                HeightField heightField = _core.CreateHeightField(heightFieldDesc);

                //

                HeightFieldShapeDescription heightFieldShapeDesc = new HeightFieldShapeDescription()
                {
                    HeightField  = heightField,
                    HoleMaterial = 2,
                    // The max height of our samples is short.MaxValue and we want it to be 1
                    HeightScale = 1.0f / (float)short.MaxValue,
                    RowScale    = 3,
                    ColumnScale = 3
                };
                heightFieldShapeDesc.LocalPosition = new Vector3(-0.5f * rows * 1 * heightFieldShapeDesc.RowScale, 0, -0.5f * columns * 1 * heightFieldShapeDesc.ColumnScale);

                ActorDescription actorDesc = new ActorDescription()
                {
                    GlobalPose = Matrix.CreateTranslation(100, 0, 0),
                    Shapes     = { heightFieldShapeDesc }
                };
                Actor actor = _scene.CreateActor(actorDesc);
            }
            #endregion

            #region Convex Mesh
            {
                ModelMesh mesh = _torusModel.Meshes.First();

                Matrix[] transforms = new Matrix[_torusModel.Bones.Count];
                _torusModel.CopyAbsoluteBoneTransformsTo(transforms);

                // Gets the vertices from the mesh
                VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[mesh.MeshParts[0].NumVertices];
                mesh.VertexBuffer.GetData <VertexPositionNormalTexture>(vertices);

                //

                // Allocate memory for the points and triangles
                var convexMeshDesc = new ConvexMeshDescription()
                {
                    PointCount = vertices.Length
                };
                convexMeshDesc.Flags |= ConvexFlag.ComputeConvex;
                convexMeshDesc.AllocatePoints <Vector3>(vertices.Length);

                // Write in the points and triangles
                // We only want the Position component of the vertex. Also scale down the mesh
                foreach (VertexPositionNormalTexture vertex in vertices)
                {
                    Vector3 position = Vector3.Transform(vertex.Position, Matrix.CreateScale(0.1f, 0.1f, 0.1f) * transforms[0]);

                    convexMeshDesc.PointsStream.Write(position);
                }

                //

                // Cook to memory or to a file
                MemoryStream stream = new MemoryStream();
                //FileStream stream = new FileStream( @"Convex Mesh.cooked", FileMode.CreateNew );

                Cooking.InitializeCooking(new ConsoleOutputStream());
                Cooking.CookConvexMesh(convexMeshDesc, stream);
                Cooking.CloseCooking();

                stream.Position = 0;

                ConvexMesh convexMesh = _core.CreateConvexMesh(stream);

                ConvexShapeDescription convexShapeDesc = new ConvexShapeDescription(convexMesh);

                ActorDescription actorDesc = new ActorDescription()
                {
                    BodyDescription = new BodyDescription(10.0f),
                    GlobalPose      = Matrix.CreateTranslation(30, 30, 0)
                };
                actorDesc.Shapes.Add(convexShapeDesc);

                _torusActor = _scene.CreateActor(actorDesc);
            }
            #endregion

            #region SoftBody
            if (false)              // Enable to view soft bodies, they run slowly
            {
                XmlDocument doc = new XmlDocument();
                doc.Load("Teapot.xml");

                // Not how NxuStream are meant to used but what ever :S
                Vector3[] vertices          = ReadVertices(doc.SelectSingleNode("/NXUSTREAM2/NxuPhysicsCollection/NxSoftBodyMeshDesc/vertices"));
                int[]     tetrahedraSingles = ReadTetrahedra(doc.SelectSingleNode("/NXUSTREAM2/NxuPhysicsCollection/NxSoftBodyMeshDesc/tetrahedra"));

                var softBodyMeshDesc = new SoftBodyMeshDescription()
                {
                    VertexCount     = vertices.Length,
                    TetrahedraCount = tetrahedraSingles.Length / 4                     // Tetrahedras come in quadruples of ints
                };

                softBodyMeshDesc.AllocateVertices <Vector3>(softBodyMeshDesc.VertexCount);
                softBodyMeshDesc.AllocateTetrahedra <int>(softBodyMeshDesc.TetrahedraCount);                  // Note: T is an int. T is the type of each point

                softBodyMeshDesc.VertexStream.SetData(vertices);
                softBodyMeshDesc.TetrahedraStream.SetData(tetrahedraSingles);

                MemoryStream memoryStream = new MemoryStream();

                Cooking.InitializeCooking();
                Cooking.CookSoftBodyMesh(softBodyMeshDesc, memoryStream);
                Cooking.CloseCooking();

                memoryStream.Position = 0;

                SoftBodyMesh softBodyMesh = _core.CreateSoftBodyMesh(memoryStream);

                SoftBodyDescription desc = new SoftBodyDescription()
                {
                    GlobalPose   = Matrix.CreateTranslation(-30, 20, -30),
                    SoftBodyMesh = softBodyMesh
                };
                desc.Flags |= SoftBodyFlag.Visualization;

                desc.MeshData.AllocatePositions <Vector3>(vertices.Length);
                desc.MeshData.AllocateIndices <int>(tetrahedraSingles.Length);

                SoftBody softBody = _scene.CreateSoftBody(desc);
            }
            #endregion

            #region Reports
            // Contact report
            // When the capsule actor hits the ground make it bounce by using the conact report
            {
                CapsuleShapeDescription capsuleShapeDesc = new CapsuleShapeDescription(1, 5);

                ActorDescription actorDesc = new ActorDescription()
                {
                    GlobalPose      = Matrix.CreateTranslation(-30, 20, 0),
                    BodyDescription = new BodyDescription(10.0f),
                    Name            = "Report Capsule",
                    Shapes          = { capsuleShapeDesc }
                };

                _contactReportActor = _scene.CreateActor(actorDesc);

                _scene.SetActorPairFlags(_contactReportActor, _groundActor, ContactPairFlag.All);

                _scene.UserContactReport = new ContactReport(this);
            }

            // Trigger Reports
            {
                BoxShapeDescription boxShapeDesc = new BoxShapeDescription(15, 8, 15);
                boxShapeDesc.Flags |= (ShapeFlag.TriggerOnEnter | ShapeFlag.TriggerOnLeave);

                ActorDescription actorDesc = new ActorDescription()
                {
                    GlobalPose = Matrix.CreateTranslation(-30, 4, 0),
                    Shapes     = { boxShapeDesc }
                };
                _scene.CreateActor(actorDesc);

                _scene.UserTriggerReport = new TriggerReport(this);
            }

            _scene.UserNotify = new Notify(this);
            #endregion

            #region Wheel
            {
                _basicVehicle = new Vehicle(this);
            }
            #endregion

            #region Controller
            {
                ControllerManager manager = _scene.CreateControllerManager();

                CapsuleControllerDescription capsuleControllerDesc = new CapsuleControllerDescription(4, 3)
                {
                    Callback = new ControllerHitReport()
                };

                CapsuleController capsuleController = manager.CreateController <CapsuleController>(capsuleControllerDesc);
                capsuleController.Position   = new Vector3(0, 1.5f + 2, -15);
                capsuleController.Actor.Name = "BoxController";
                capsuleController.SetCollisionEnabled(true);
            }
            #endregion
        }
Example #12
0
 private List <Vector3> GetConvexPoints()
 {
     return(ConvexMesh.QuickHull(new List <Vector3>(MeshHelper.ConvertVec2ToVec3(convexPoints))));
 }
Example #13
0
        private void CreateVehicle4WSimulationData(
            float chassisMass,
            ConvexMesh chassisConvexMesh,
            float wheelMass,
            ConvexMesh[] wheelConvexMeshes,
            Vector3[] wheelCentreOffsets,
            VehicleWheelsSimData wheelsData,
            VehicleDriveSimData4W driveData,
            VehicleChassisData chassisData)
        {
            const int TIRE_TYPE_SLICKS = 0;

            //Extract the chassis AABB dimensions from the chassis convex mesh.
            //Vector3 chassisDims = computeChassisAABBDimensions(chassisConvexMesh);
            Vector3 chassisDims = new Vector3(10, 10, 10);

            //The origin is at the center of the chassis mesh.
            //Set the center of mass to be below this point and a little towards the front.
            Vector3 chassisCMOffset = new Vector3(0.0f, -chassisDims.Y * 0.5f + 0.65f, 0.25f);

            //Now compute the chassis mass and moment of inertia.
            //Use the moment of inertia of a cuboid as an approximate value for the chassis moi.
            Vector3 chassisMOI = new Vector3
                                 (
                (chassisDims.Y * chassisDims.Y + chassisDims.Z * chassisDims.Z) * chassisMass / 12.0f,
                (chassisDims.X * chassisDims.X + chassisDims.Z * chassisDims.Z) * chassisMass / 12.0f,
                (chassisDims.X * chassisDims.X + chassisDims.Y * chassisDims.Y) * chassisMass / 12.0f
                                 );

            //A bit of tweaking here.  The car will have more responsive turning if we reduce the
            //y-component of the chassis moment of inertia.
            chassisMOI.Y *= 0.8f;

            //Let's set up the chassis data structure now.
            chassisData.Mass               = chassisMass;
            chassisData.MomentOfInertia    = chassisMOI;
            chassisData.CenterOfMassOffset = chassisCMOffset;

            //Work out the front/rear mass split from the cm offset.
            //This is a very approximate calculation with lots of assumptions.
            //massRear*zRear + massFront*zFront = mass*cm           (1)
            //massRear       + massFront        = mass                      (2)
            //Rearrange (2)
            //massFront = mass - massRear                                           (3)
            //Substitute (3) into (1)
            //massRear(zRear - zFront) + mass*zFront = mass*cm      (4)
            //Solve (4) for massRear
            //massRear = mass(cm - zFront)/(zRear-zFront)           (5)
            //Now we also have
            //zFront = (z-cm)/2                                                                     (6a)
            //zRear = (-z-cm)/2                                                                     (6b)
            //Substituting (6a-b) into (5) gives
            //massRear = 0.5*mass*(z-3cm)/z                                         (7)
            float massRear  = 0.5f * chassisMass * (chassisDims.Z - 3 * chassisCMOffset.Z) / chassisDims.Z;
            float massFront = chassisMass - massRear;

            //Extract the wheel radius and width from the wheel convex meshes.
            float[] wheelWidths = new float[4];
            float[] wheelRadii  = new float[4];
            //ComputeWheelWidthsAndRadii(wheelConvexMeshes, wheelWidths, wheelRadii);
            wheelWidths = new[] { 3f, 3, 3, 3 };
            wheelRadii  = new[] { 1f, 1, 1, 1 };

            //Now compute the wheel masses and inertias components around the axle's axis.
            //http://en.wikipedia.org/wiki/List_of_moments_of_inertia
            float[] wheelMOIs = new float[4];
            for (int i = 0; i < 4; i++)
            {
                wheelMOIs[i] = 0.5f * wheelMass * wheelRadii[i] * wheelRadii[i];
            }
            //Let's set up the wheel data structures now with radius, mass, and moi.
            VehicleWheelData[] wheels = new VehicleWheelData[4]
            {
                new VehicleWheelData(),
                new VehicleWheelData(),
                new VehicleWheelData(),
                new VehicleWheelData()
            };
            for (int i = 0; i < 4; i++)
            {
                wheels[i].Radius          = wheelRadii[i];
                wheels[i].Mass            = wheelMass;
                wheels[i].MomentOfInertia = wheelMOIs[i];
                wheels[i].Width           = wheelWidths[i];
            }
            //Disable the handbrake from the front wheels and enable for the rear wheels
            wheels[(int)VehicleWheelOrdering.FrontLeftWheel].MaxHandBrakeTorque  = 0.0f;
            wheels[(int)VehicleWheelOrdering.FrontRightWheel].MaxHandBrakeTorque = 0.0f;
            wheels[(int)VehicleWheelOrdering.RearLeftWheel].MaxHandBrakeTorque   = 4000.0f;
            wheels[(int)VehicleWheelOrdering.RearRightWheel].MaxHandBrakeTorque  = 4000.0f;
            //Enable steering for the front wheels and disable for the front wheels.
            wheels[(int)VehicleWheelOrdering.FrontLeftWheel].MaxSteer  = (float)System.Math.PI * 0.3333f;
            wheels[(int)VehicleWheelOrdering.FrontRightWheel].MaxSteer = (float)System.Math.PI * 0.3333f;
            wheels[(int)VehicleWheelOrdering.RearLeftWheel].MaxSteer   = 0.0f;
            wheels[(int)VehicleWheelOrdering.RearRightWheel].MaxSteer  = 0.0f;

            //Let's set up the tire data structures now.
            //Put slicks on the front tires and wets on the rear tires.
            VehicleTireData[] tires = new VehicleTireData[4]
            {
                new VehicleTireData(),
                new VehicleTireData(),
                new VehicleTireData(),
                new VehicleTireData()
            };
            tires[(int)VehicleWheelOrdering.FrontLeftWheel].Type  = TIRE_TYPE_SLICKS;
            tires[(int)VehicleWheelOrdering.FrontRightWheel].Type = TIRE_TYPE_SLICKS;
            tires[(int)VehicleWheelOrdering.RearLeftWheel].Type   = TIRE_TYPE_SLICKS;
            tires[(int)VehicleWheelOrdering.RearRightWheel].Type  = TIRE_TYPE_SLICKS;

            //Let's set up the suspension data structures now.
            VehicleSuspensionData[] susps = new VehicleSuspensionData[4]
            {
                new VehicleSuspensionData(),
                new VehicleSuspensionData(),
                new VehicleSuspensionData(),
                new VehicleSuspensionData()
            };
            for (int i = 0; i < 4; i++)
            {
                susps[i].MaxCompression   = 0.3f;
                susps[i].MaxDroop         = 0.1f;
                susps[i].SpringStrength   = 35000.0f;
                susps[i].SpringDamperRate = 4500.0f;
            }
            susps[(int)VehicleWheelOrdering.FrontLeftWheel].SprungMass  = massFront * 0.5f;
            susps[(int)VehicleWheelOrdering.FrontRightWheel].SprungMass = massFront * 0.5f;
            susps[(int)VehicleWheelOrdering.RearLeftWheel].SprungMass   = massRear * 0.5f;
            susps[(int)VehicleWheelOrdering.RearRightWheel].SprungMass  = massRear * 0.5f;

            //We need to set up geometry data for the suspension, wheels, and tires.
            //We already know the wheel centers described as offsets from the rigid body centre of mass.
            //From here we can approximate application points for the tire and suspension forces.
            //Lets assume that the suspension travel directions are absolutely vertical.
            //Also assume that we apply the tire and suspension forces 30cm below the centre of mass.
            Vector3[] suspTravelDirections  = new Vector3[] { new Vector3(0, -1, 0), new Vector3(0, -1, 0), new Vector3(0, -1, 0), new Vector3(0, -1, 0) };
            Vector3[] wheelCentreCMOffsets  = new Vector3[4];
            Vector3[] suspForceAppCMOffsets = new Vector3[4];
            Vector3[] tireForceAppCMOffsets = new Vector3[4];
            for (int i = 0; i < 4; i++)
            {
                wheelCentreCMOffsets[i]  = wheelCentreOffsets[i] - chassisCMOffset;
                suspForceAppCMOffsets[i] = new Vector3(wheelCentreCMOffsets[i].X, -0.3f, wheelCentreCMOffsets[i].Z);
                tireForceAppCMOffsets[i] = new Vector3(wheelCentreCMOffsets[i].X, -0.3f, wheelCentreCMOffsets[i].Z);
            }

            //Now add the wheel, tire and suspension data.
            for (int i = 0; i < 4; i++)
            {
                wheelsData.SetWheelData(i, wheels[i]);
                wheelsData.SetTireData(i, tires[i]);
                wheelsData.SetSuspensionData(i, susps[i]);
                wheelsData.SetSuspensionTravelDirection(i, suspTravelDirections[i]);
                wheelsData.SetWheelCentreOffset(i, wheelCentreCMOffsets[i]);
                wheelsData.SetSuspensionForceApplicationPointOffset(i, suspForceAppCMOffsets[i]);
                wheelsData.SetTireForceApplicationPointOffset(i, tireForceAppCMOffsets[i]);
            }

            //Now set up the differential, engine, gears, clutch, and ackermann steering.

            //Diff
            VehicleDifferential4WData diff = new VehicleDifferential4WData();

            diff.Type = VehicleDifferentialType.LimitedSlip4WheelDrive;
            driveData.SetDifferentialData(diff);

            //Engine
            VehicleEngineData engine = new VehicleEngineData()
            {
                PeakTorque = 500.0f,
                MaxOmega   = 600.0f              //approx 6000 rpm
            };

            driveData.SetEngineData(engine);

            //Gears
            VehicleGearsData gears = new VehicleGearsData()
            {
                SwitchTime = 0.5f
            };

            driveData.SetGearsData(gears);

            //Clutch
            VehicleClutchData clutch = new VehicleClutchData()
            {
                Strength = 10.0f
            };

            driveData.SetClutchData(clutch);

            //Ackermann steer accuracy
            VehicleAckermannGeometryData ackermann = new VehicleAckermannGeometryData()
            {
                Accuracy       = 1.0f,
                AxleSeparation = wheelCentreOffsets[(int)VehicleWheelOrdering.FrontLeftWheel].Z - wheelCentreOffsets[(int)VehicleWheelOrdering.RearLeftWheel].Z,
                FrontWidth     = wheelCentreOffsets[(int)VehicleWheelOrdering.FrontRightWheel].X - wheelCentreOffsets[(int)VehicleWheelOrdering.FrontLeftWheel].X,
                RearWidth      = wheelCentreOffsets[(int)VehicleWheelOrdering.RearRightWheel].X - wheelCentreOffsets[(int)VehicleWheelOrdering.RearLeftWheel].X
            };

            driveData.SetAckermannGeometryData(ackermann);
        }
 public override void addConvexMesh(string name, ConvexMesh mesh)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Add a convex mesh that will be managed by this reposotory.  This will
 /// be released when this object is disposed.
 /// </summary>
 /// <param name="mesh">The mesh to add.</param>
 public abstract void addConvexMesh(String name, ConvexMesh mesh);