Esempio n. 1
0
        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);
            }
        }
Esempio n. 2
0
        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();
            }
        }
Esempio n. 3
0
        public void SetForceFireRotationLookTo(Vec3 lookTo)
        {
            setForceFireRotation = true;

            Vec3 diff = lookTo - Position;

            //Vec3 diff = lookTo - GetFirePosition( false );

            forceFireRotation = Quat.FromDirectionZAxisUp(diff);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 6
0
        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;
            }
        }
Esempio n. 9
0
        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);
            }
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
        /// <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;
        }
Esempio n. 12
0
        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();
            }
        }
Esempio n. 13
0
        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;
        }