void UpdateTaskControlKeys() { if (task_enabled) { Vec3 unit_pos = ControlledObject.Position; Vec3 unit_dir = ControlledObject.Rotation.GetForward(); Vec3 need_dir = task_position - unit_pos; Angles angle = new Angles(ControlledObject.Rotation.ToAngles().Roll, ControlledObject.Rotation.ToAngles().Pitch, Quat.FromDirectionZAxisUp(need_dir).ToAngles().Yaw); ControlledObject.Rotation = Quat.Slerp(ControlledObject.Rotation, angle.ToQuat(), 6.0f * TickDelta); ControlKeyPress(GameControlKeys.Forward, 1); if (ControlledObject.Rotation.GetUp().Z < .4f) { ControlKeyPress(GameControlKeys.Reload, 1); } else { ControlKeyRelease(GameControlKeys.Reload); } } else { ControlKeyRelease(GameControlKeys.Forward); } }
public void UpdatePhysXJoint() { bool needCreate = PushedToWorld && !Broken; bool created = nativeJoint != IntPtr.Zero; if (needCreate == created) { return; } if (needCreate) { if (Axis.LimitsEnabled && Axis.LimitLow > Axis.LimitHigh) { Log.Warning("HingeJoint: Invalid axis limits (low > high)."); return; } PhysXBody physXBody0 = (PhysXBody)Body1; PhysXBody physXBody1 = (PhysXBody)Body2; if ((!physXBody0.Static || !physXBody1.Static) && (physXBody0.nativeBody != IntPtr.Zero && physXBody1.nativeBody != IntPtr.Zero)) { Quat globalAxisRotation = Quat.FromDirectionZAxisUp(Axis.Direction); Vec3 localPosition0 = physXBody0.Rotation.GetInverse() * (Anchor - physXBody0.Position); Quat localRotation0 = (physXBody0.Rotation.GetInverse() * globalAxisRotation).GetNormalize(); Vec3 localPosition1 = physXBody1.Rotation.GetInverse() * (Anchor - physXBody1.Position); Quat localRotation1 = (physXBody1.Rotation.GetInverse() * globalAxisRotation).GetNormalize(); nativeJoint = PhysXNativeWrapper.PhysXNativeHingeJoint.Create( physXBody0.nativeBody, ref localPosition0, ref localRotation0, physXBody1.nativeBody, ref localPosition1, ref localRotation1); UpdateLimits(); if (ContactsEnabled) { PhysXNativeWrapper.PhysXJoint.SetCollisionEnable(nativeJoint, true); } UpdatePhysXBreakData(); if (Scene._EnableDebugVisualization) { SetVisualizationEnable(true); } //PhysXNativeWrapper.PhysXJoint.SetProjectionEnable( nativeJoint, true ); //desc->projectionMode = NxJointProjectionMode.NX_JPM_POINT_MINDIST; //desc->projectionDistance = 0.1f; //desc->projectionAngle = new Radian( new Degree( 3 ) ); initialRelativeRotationInverse = (physXBody1.Rotation * physXBody0.Rotation.GetInverse()).GetInverse(); } } else { DestroyPhysXJoint(); } }
public void SetForceFireRotationLookTo(Vec3 lookTo) { setForceFireRotation = true; Vec3 diff = lookTo - Position; //Vec3 diff = lookTo - GetFirePosition( false ); forceFireRotation = Quat.FromDirectionZAxisUp(diff); }
protected override Body[] OnVolumeCast(Capsule capsule, int contactGroup) { Vec3 origin = capsule.GetCenter(); Quat rotation = Quat.FromDirectionZAxisUp(capsule.GetDirection()); int shapeCount = PhysXNativeScene.OverlapCapsuleShapes(nativeScene, ref origin, ref rotation, capsule.Radius, capsule.GetLength() * .5f, GetContactGroupMask(contactGroup)); if (shapeCount == 0) { return(emptyVolumeCastResult); } return(GetBodiesFromVolumeCastResult(shapeCount)); }
static void AddCone(Camera camera, Vec3 from, Vec3 to, float radius) { Vec3 direction = to - from; float length = direction.Normalize(); Vec3[] positions; int[] indices; GeometryGenerator.GenerateCone(radius, length, 32, true, true, out positions, out indices); Quat rotation = Quat.FromDirectionZAxisUp(direction); Mat4 transform = new Mat4(rotation.ToMat3(), from); camera.DebugGeometry.AddVertexIndexBuffer(positions, indices, transform, false, true); }
public static ushort DirectionFromTarget(int selfX, int selfY, int x, int y) { Vec3 vec = new Vec3(x - selfX, y - selfY, 0); Quat rot = Quat.FromDirectionZAxisUp(vec); Angles ang = rot.ToAngles(); float deg = -ang.Yaw; if (deg < 0) { deg = 360 + deg; } return((ushort)deg); }
static void AddThicknessLine(Camera camera, Vec3 start, Vec3 end, float thickness) { Vec3 diff = end - start; Vec3 direction = diff.GetNormalize(); Quat rotation = Quat.FromDirectionZAxisUp(direction); float length = diff.Length(); float thickness2 = thickness; Mat4 t = new Mat4(rotation.ToMat3() * Mat3.FromScale(new Vec3(length, thickness2, thickness2)), (start + end) * .5f); if (addThicknessLinePositions == null) { GeometryGenerator.GenerateBox(new Vec3(1, 1, 1), out addThicknessLinePositions, out addThicknessLineIndices); } camera.DebugGeometry.AddVertexIndexBuffer(addThicknessLinePositions, addThicknessLineIndices, t, false, true); }
private void GetFireParameters(out Vec3 pos, out Quat rot, out float speed) { Camera camera = RendererWorld.Instance.DefaultCamera; pos = catapult.Position + new Vec3(0, 0, .7f); Radian verticalAngle = new Degree(30).InRadians(); rot = Quat.Identity; speed = 0; if (catapultFiring) { Ray startRay = camera.GetCameraToViewportRay(catapultFiringMouseStartPosition); Ray ray = camera.GetCameraToViewportRay(MousePosition); Plane plane = Plane.FromPointAndNormal(pos, Vec3.ZAxis); Vec3 startRayPos; if (!plane.RayIntersection(startRay, out startRayPos)) { //must never happen } Vec3 rayPos; if (!plane.RayIntersection(ray, out rayPos)) { //must never happen } Vec2 diff = rayPos.ToVec2() - startRayPos.ToVec2(); Radian horizonalAngle = MathFunctions.ATan(diff.Y, diff.X) + MathFunctions.PI; SphereDir dir = new SphereDir(horizonalAngle, verticalAngle); rot = Quat.FromDirectionZAxisUp(dir.GetVector()); float distance = diff.Length(); //3 meters clamp MathFunctions.Clamp(ref distance, .001f, 3); speed = distance * 10; } }
void UpdateThreads() { const float threadThickness = .07f; foreach (ThreadItem item in threads) { Vec3 start; Vec3 end; { Quat r; Vec3 s; item.startObject.GetGlobalInterpolatedTransform(out start, out r, out s); item.endObject.GetGlobalInterpolatedTransform(out end, out r, out s); } Vec3 dir = end - start; float length = dir.Normalize(); //update scene node transform item.sceneNode.Position = (start + end) * .5f; item.sceneNode.Rotation = Quat.FromDirectionZAxisUp(dir); item.sceneNode.Scale = new Vec3(length, threadThickness, threadThickness); } }
protected override Body[] OnVolumeCast(Capsule capsule, int contactGroup) { Vec3 center; capsule.GetCenter(out center); float length = capsule.GetLength(); Vec3 direction; capsule.GetDirection(out direction); dGeomID volumeCastGeomID = Ode.dCreateCapsule(rootSpaceID, capsule.Radius, length); Quat rotation = Quat.FromDirectionZAxisUp(direction); Mat3 rot; rotation.ToMat3(out rot); Mat3 rotationMat; Mat3.FromRotateByY(MathFunctions.PI / 2, out rotationMat); Mat3 mat3; Mat3.Multiply(ref rot, ref rotationMat, out mat3); Ode.dMatrix3 odeMat3; Convert.ToODE(ref mat3, out odeMat3); Ode.dGeomSetRotation(volumeCastGeomID, ref odeMat3); Ode.dGeomSetPosition(volumeCastGeomID, center.X, center.Y, center.Z); Body[] result = DoVolumeCastGeneral(volumeCastGeomID, contactGroup); Ode.dGeomDestroy(volumeCastGeomID); return(result); }
/// <summary>Overridden from <see cref="Engine.EntitySystem.Entity.OnTick()"/>.</summary> protected override void OnTick() { base.OnTick(); if (Type.Velocity != 0) { if (Type.Gravity != 0) { velocity.Z -= Type.Gravity * TickDelta; } Vec3 offset = velocity * TickDelta; float distance = offset.LengthFast(); bool deleteIfNoCollisions = false; if (Type.MaxDistance != 0) { if (flyDistance + distance >= Type.MaxDistance) { distance = Type.MaxDistance - flyDistance; if (distance <= 0) { distance = .001f; } offset = offset.GetNormalizeFast() * distance; deleteIfNoCollisions = true; } } Vec3 startPosition = Position; //back check (that did not fly by through moving towards objects) if (!firstTick) { startPosition -= offset * .1f; } Ray ray = new Ray(startPosition, offset); RayCastResult[] piercingResult = PhysicsWorld.Instance.RayCastPiercing( ray, (int)ContactGroup.CastOnlyContact); foreach (RayCastResult result in piercingResult) { MapObject obj = MapSystemWorld.GetMapObjectByBody(result.Shape.Body); if (obj != null) { Dynamic dynamic = obj as Dynamic; if (dynamic != null && sourceUnit != null && dynamic.GetParentUnitHavingIntellect() == sourceUnit) { continue; } } Position = result.Position; OnHit(result.Shape, result.Normal, obj); CreateWaterPlaneSplash(new Ray(startPosition, Position - startPosition)); goto end; } Position += offset; flyDistance += distance; //update rotation if (velocity != Vec3.Zero) { Rotation = Quat.FromDirectionZAxisUp(velocity.GetNormalizeFast()); } CreateWaterPlaneSplash(ray); if (deleteIfNoCollisions) { SetDeleted(); return; } } else { const float checkPieceSize = 40.0f; Bounds checkBounds = SceneManager.Instance.GetTotalObjectsBounds(); checkBounds.Expand(200); Vec3 dir = Rotation.GetForward(); Vec3 pos = Position; while (checkBounds.IsContainsPoint(pos)) { Vec3 offset = dir * checkPieceSize; float distance = offset.LengthFast(); bool deleteIfNoCollisions = false; if (Type.MaxDistance != 0) { if (flyDistance + distance >= Type.MaxDistance) { distance = Type.MaxDistance - flyDistance; if (distance <= 0) { distance = .001f; } offset = offset.GetNormalizeFast() * distance; deleteIfNoCollisions = true; } } Ray ray = new Ray(pos, offset); RayCastResult[] piercingResult = PhysicsWorld.Instance.RayCastPiercing( ray, (int)ContactGroup.CastOnlyContact); foreach (RayCastResult result in piercingResult) { MapObject obj = MapSystemWorld.GetMapObjectByBody(result.Shape.Body); if (obj != null) { Dynamic dynamic = obj as Dynamic; if (dynamic != null && sourceUnit != null && dynamic.GetParentUnitHavingIntellect() == sourceUnit) { continue; } } Position = result.Position; OnHit(result.Shape, result.Normal, obj); CreateWaterPlaneSplash(new Ray(ray.Origin, Position - ray.Origin)); goto end; } pos += offset; flyDistance += distance; CreateWaterPlaneSplash(ray); if (deleteIfNoCollisions) { SetDeleted(); return; } } SetDeleted(); } end :; firstTick = false; }
void UpdatePhysXJoint() { bool needCreate = PushedToWorld && !Broken; bool created = nativeJoint != IntPtr.Zero; if (needCreate == created) { return; } if (needCreate) { PhysXBody physXBody0 = (PhysXBody)Body1; PhysXBody physXBody1 = (PhysXBody)Body2; if ((!physXBody0.Static || !physXBody1.Static) && (physXBody0.nativeBody != IntPtr.Zero && physXBody1.nativeBody != IntPtr.Zero)) { Vec3 globalAnchor = (Body1.Position + Body2.Position) * .5f; //float diff = axis.LimitHigh - axis.LimitLow; //Vec3 low = globalAnchor + Axis.Direction * axis.LimitLow; //Vec3 high = globalAnchor + Axis.Direction * axis.LimitHigh; //if( axis.LimitsEnabled ) //{ // globalAnchor = ( low + high ) / 2; // //float d = axis.LimitHigh + axis.LimitLow; // //если low положительный? // //globalAnchor += ( d / 2 ) * Axis.Direction; //} Quat globalAxisRotation = Quat.FromDirectionZAxisUp(Axis.Direction); Vec3 localPosition0 = physXBody0.Rotation.GetInverse() * (globalAnchor - physXBody0.Position); Quat localRotation0 = (physXBody0.Rotation.GetInverse() * globalAxisRotation).GetNormalize(); Vec3 localPosition1 = physXBody1.Rotation.GetInverse() * (globalAnchor - physXBody1.Position); Quat localRotation1 = (physXBody1.Rotation.GetInverse() * globalAxisRotation).GetNormalize(); nativeJoint = PhysXNativeWrapper.PhysXNativeD6Joint.Create( physXBody0.nativeBody, ref localPosition0, ref localRotation0, physXBody1.nativeBody, ref localPosition1, ref localRotation1); PhysXNativeD6Joint.SetMotion(nativeJoint, PhysXD6Axis.X, PhysXD6Motion.Free); PhysXNativeD6Joint.SetMotion(nativeJoint, PhysXD6Axis.Y, PhysXD6Motion.Locked); PhysXNativeD6Joint.SetMotion(nativeJoint, PhysXD6Axis.Z, PhysXD6Motion.Locked); PhysXNativeD6Joint.SetMotion(nativeJoint, PhysXD6Axis.Twist, PhysXD6Motion.Locked); PhysXNativeD6Joint.SetMotion(nativeJoint, PhysXD6Axis.Swing1, PhysXD6Motion.Locked); PhysXNativeD6Joint.SetMotion(nativeJoint, PhysXD6Axis.Swing2, PhysXD6Motion.Locked); UpdateLimits(); //Vec3 globalAnchor = ( Body1.Position + Body2.Position ) * .5f; //Quat globalAxisRotation = Quat.FromDirectionZAxisUp( Axis.Direction ); //Vec3 localPosition0 = physXBody0.Rotation.GetInverse() * ( globalAnchor - physXBody0.Position ); //Quat localRotation0 = ( physXBody0.Rotation.GetInverse() * globalAxisRotation ).GetNormalize(); //Vec3 localPosition1 = physXBody1.Rotation.GetInverse() * ( globalAnchor - physXBody1.Position ); //Quat localRotation1 = ( physXBody1.Rotation.GetInverse() * globalAxisRotation ).GetNormalize(); //nativeJoint = PhysXNativeWrapper.PhysXNativeSliderJoint.Create( // physXBody0.nativeBody, ref localPosition0, ref localRotation0, // physXBody1.nativeBody, ref localPosition1, ref localRotation1 ); //if( axis.LimitsEnabled ) //{ // Log.Warning( "PhysXSliderJoint: Limits for Slider joint are not supported by the PhysX Physics System." ); // //PhysXNativeWrapper.PhysXNativeSliderJoint.SetLimit( nativeJoint, true, axis.LimitLow, axis.LimitHigh, // // PhysXGeneral.jointLimitContactDistance, axis.LimitsBounciness, axis.LimitsHardness ); //} if (ContactsEnabled) { PhysXNativeWrapper.PhysXJoint.SetCollisionEnable(nativeJoint, true); } UpdatePhysXBreakData(); if (Scene._EnableDebugVisualization) { SetVisualizationEnable(true); } } } else { DestroyPhysXJoint(); } }
private bool Process(float maxDistanceForBulletWithInfiniteSpeed) { Vec3 offset; float distance; if (Type.Velocity != 0) { offset = velocity * TickDelta; distance = offset.Length(); } else { offset = Rotation.GetForward() * maxDistanceForBulletWithInfiniteSpeed; distance = maxDistanceForBulletWithInfiniteSpeed; } bool deleteIfNoCollisions = false; if (Type.MaxDistance != 0 && flyDistance + distance >= Type.MaxDistance) { distance = Type.MaxDistance - flyDistance; if (distance <= 0) { distance = .001f; } offset = offset.GetNormalize() * distance; deleteIfNoCollisions = true; } Vec3 startPosition = Position; //back check (that did not fly by through moving towards objects) if (!firstTick) { startPosition -= offset * .1f; } Ray ray = new Ray(startPosition, offset); //find a hit Shape hitShape = null; Vec3 hitPosition = Vec3.Zero; Vec3 hitNormal = Vec3.Zero; MapObject hitMapObject = null;//can be null (as example in case when collided with a HeightmapTerrain shape) { RayCastResult[] piercingResult = PhysicsWorld.Instance.RayCastPiercing(ray, (int)ContactGroup.CastOnlyContact); foreach (RayCastResult result in piercingResult) { //get associated MapObject with the parent body of the shape MapObject obj = MapSystemWorld.GetMapObjectByBody(result.Shape.Body); //skip bullet creator Dynamic dynamic = obj as Dynamic; if (dynamic != null && sourceUnit != null && dynamic.GetParentUnitHavingIntellect() == sourceUnit) { continue; } //found! hitShape = result.Shape; hitPosition = result.Position; hitNormal = result.Normal; hitMapObject = obj; break; } } if (hitShape != null) { //process the hit Ray rayToHit = new Ray(ray.Origin, hitPosition - ray.Origin); //networking: call OnHit on clients if (EntitySystemWorld.Instance.IsServer() && Type.NetworkType == EntityNetworkTypes.Synchronized) { Body hitShapeBody = null; if (hitShape != null) { hitShapeBody = hitShape.Body; } Server_SendHitCallToAllClients(hitPosition, hitShapeBody != null ? hitShapeBody.Name : "", hitShape != null ? hitShape.Name : "", hitNormal, hitMapObject); } Position = hitPosition; OnHit(hitShape, hitNormal, hitMapObject); CreateWaterPlaneSplash(rayToHit); return(true); } else { //no hit. continue the flying or delete Position += offset; //update rotation if (velocity != Vec3.Zero) { Rotation = Quat.FromDirectionZAxisUp(velocity.GetNormalize()); } flyDistance += distance; CreateWaterPlaneSplash(ray); if (deleteIfNoCollisions) { SetForDeletion(false); } return(false); } }
private unsafe void UpdateGeometry() { DestroyGeometry(); Curve positionCurve = GetPositionCurve(); Curve radiusCurve = null; { bool existsSpecialRadius = false; foreach (MapCurvePoint point in Points) { RenderableCurvePoint point2 = point as RenderableCurvePoint; if (point2 != null && point2.OverrideRadius >= 0) { existsSpecialRadius = true; break; } } if (existsSpecialRadius) { switch (radiusCurveType) { case RadiusCurveTypes.UniformCubicSpline: radiusCurve = new UniformCubicSpline(); break; case RadiusCurveTypes.Bezier: radiusCurve = new BezierCurve(); break; case RadiusCurveTypes.Line: radiusCurve = new LineCurve(); break; } for (int n = 0; n < Points.Count; n++) { MapCurvePoint point = Points[n]; if (!point.Editor_IsExcludedFromWorld()) { float rad = radius; RenderableCurvePoint renderableCurvePoint = point as RenderableCurvePoint; if (renderableCurvePoint != null && renderableCurvePoint.OverrideRadius >= 0) { rad = renderableCurvePoint.OverrideRadius; } radiusCurve.AddValue(point.Time, new Vec3(rad, 0, 0)); } } } } //create mesh Vertex[] vertices = null; int[] indices = null; if (positionCurve != null && positionCurve.Values.Count > 1 && Points.Count >= 2) { Vec3 positionOffset = -Position; int steps = (Points.Count - 1) * pathSteps + 1; int vertexCount = steps * (shapeSegments + 1); int indexCount = (steps - 1) * shapeSegments * 2 * 3; vertices = new Vertex[vertexCount]; indices = new int[indexCount]; //fill data { int currentVertex = 0; int currentIndex = 0; float currentDistance = 0; Vec3 lastPosition = Vec3.Zero; Quat lastRot = Quat.Identity; for (int nStep = 0; nStep < steps; nStep++) { int startStepVertexIndex = currentVertex; float coefficient = (float)nStep / (float)(steps - 1); Vec3 pos = CalculateCurvePointByCoefficient(coefficient) + positionOffset; Quat rot; { Vec3 v = CalculateCurvePointByCoefficient(coefficient + .3f / (float)(steps - 1)) - CalculateCurvePointByCoefficient(coefficient); if (v != Vec3.Zero) { rot = Quat.FromDirectionZAxisUp(v.GetNormalize()); } else { rot = lastRot; } } if (nStep != 0) { currentDistance += (pos - lastPosition).Length(); } float rad; if (radiusCurve != null) { Range range = new Range(radiusCurve.Times[0], radiusCurve.Times[radiusCurve.Times.Count - 1]); float t = range.Minimum + (range.Maximum - range.Minimum) * coefficient; rad = radiusCurve.CalculateValueByTime(t).X; } else { rad = radius; } for (int nSegment = 0; nSegment < shapeSegments + 1; nSegment++) { float rotateCoefficient = ((float)nSegment / (float)(shapeSegments)); float angle = rotateCoefficient * MathFunctions.PI * 2; Vec3 p = pos + rot * new Vec3(0, MathFunctions.Cos(angle) * rad, MathFunctions.Sin(angle) * rad); Vertex vertex = new Vertex(); vertex.position = p; Vec3 pp = p - pos; if (pp != Vec3.Zero) { vertex.normal = pp.GetNormalize(); } else { vertex.normal = Vec3.XAxis; } //vertex.normal = ( p - pos ).GetNormalize(); vertex.texCoord = new Vec2(currentDistance * textureCoordinatesTilesPerMeter, rotateCoefficient + .25f); vertex.tangent = new Vec4(rot.GetForward(), 1); vertices[currentVertex++] = vertex; } if (nStep < steps - 1) { for (int nSegment = 0; nSegment < shapeSegments; nSegment++) { indices[currentIndex++] = startStepVertexIndex + nSegment; indices[currentIndex++] = startStepVertexIndex + nSegment + 1; indices[currentIndex++] = startStepVertexIndex + nSegment + 1 + shapeSegments + 1; indices[currentIndex++] = startStepVertexIndex + nSegment + 1 + shapeSegments + 1; indices[currentIndex++] = startStepVertexIndex + nSegment + shapeSegments + 1; indices[currentIndex++] = startStepVertexIndex + nSegment; } } lastPosition = pos; lastRot = rot; } if (currentVertex != vertexCount) { Log.Fatal("RenderableCurve: UpdateRenderingGeometry: currentVertex != vertexCount."); } if (currentIndex != indexCount) { Log.Fatal("RenderableCurve: UpdateRenderingGeometry: currentIndex != indexCount."); } } if (vertices.Length != 0 && indices.Length != 0) { //create mesh string meshName = MeshManager.Instance.GetUniqueName( string.Format("__RenderableCurve_{0}_{1}", Name, uniqueMeshIdentifier)); uniqueMeshIdentifier++; //string meshName = MeshManager.Instance.GetUniqueName( string.Format( "__RenderableCurve_{0}", Name ) ); mesh = MeshManager.Instance.CreateManual(meshName); SubMesh subMesh = mesh.CreateSubMesh(); subMesh.UseSharedVertices = false; //init vertexData VertexDeclaration declaration = subMesh.VertexData.VertexDeclaration; declaration.AddElement(0, 0, VertexElementType.Float3, VertexElementSemantic.Position); declaration.AddElement(0, 12, VertexElementType.Float3, VertexElementSemantic.Normal); declaration.AddElement(0, 24, VertexElementType.Float2, VertexElementSemantic.TextureCoordinates, 0); declaration.AddElement(0, 32, VertexElementType.Float4, VertexElementSemantic.Tangent, 0); fixed(Vertex *pVertices = vertices) { subMesh.VertexData = VertexData.CreateFromArray(declaration, (IntPtr)pVertices, vertices.Length * Marshal.SizeOf(typeof(Vertex))); } subMesh.IndexData = IndexData.CreateFromArray(indices, 0, indices.Length, false); //set material subMesh.MaterialName = materialName; //set mesh gabarites Bounds bounds = Bounds.Cleared; foreach (Vertex vertex in vertices) { bounds.Add(vertex.position); } mesh.SetBoundsAndRadius(bounds, bounds.GetRadius()); } } //create MeshObject, SceneNode if (mesh != null) { meshObject = SceneManager.Instance.CreateMeshObject(mesh.Name); if (meshObject != null) { meshObject.SetMaterialNameForAllSubObjects(materialName); meshObject.CastShadows = true; sceneNode = new SceneNode(); sceneNode.Attach(meshObject); //apply offset sceneNode.Position = Position; MapObject.AssociateSceneNodeWithMapObject(sceneNode, this); } } //create collision body if (mesh != null && collision) { Vec3[] positions = new Vec3[vertices.Length]; for (int n = 0; n < vertices.Length; n++) { positions[n] = vertices[n].position; } string meshPhysicsMeshName = PhysicsWorld.Instance.AddCustomMeshGeometry(positions, indices, null, MeshShape.MeshTypes.TriangleMesh, 0, 0); collisionBody = PhysicsWorld.Instance.CreateBody(); collisionBody.Static = true; collisionBody._InternalUserData = this; collisionBody.Position = Position; MeshShape shape = collisionBody.CreateMeshShape(); shape.MeshName = meshPhysicsMeshName; shape.MaterialName = CollisionMaterialName; shape.ContactGroup = (int)ContactGroup.Collision; //shape.VehicleDrivableSurface = collisionVehicleDrivableSurface; collisionBody.PushedToWorld = true; } needUpdate = false; }