public void CalculateStartPosition(float elapsedTime, MatrixD worldMatrix, Vector3 userAxisScale, float userScale, out Vector3D startOffset, out Vector3D startPosition)
        {
            Vector3 currentOffsetUntransformed;

            Offset.GetInterpolatedValue <Vector3>(elapsedTime, out currentOffsetUntransformed);

            Vector3 currentRotation;

            Rotation.GetInterpolatedValue <Vector3>(elapsedTime, out currentRotation);

            float currentSize;

            Size.GetInterpolatedValue <float>(elapsedTime, out currentSize);
            currentSize *= MyUtils.GetRandomFloat(RadiusMin, RadiusMax) * userScale;

            Vector3 currentAxisScale = userAxisScale * AxisScale;

            Vector3  localPos = Vector3.Zero;
            Vector3D worldOffset;

            Vector3D.Transform(ref currentOffsetUntransformed, ref worldMatrix, out worldOffset);

            switch (Type)
            {
            case MyParticleEmitterType.Point:
                localPos = Vector3.Zero;
                break;

            case MyParticleEmitterType.Line:
                localPos = Vector3.Forward * MyUtils.GetRandomFloat(0.0f, currentSize) * currentAxisScale;
                break;

            case MyParticleEmitterType.Sphere:
                if (LimitAngle.GetKeysCount() > 0)
                {
                    float angle;
                    LimitAngle.GetInterpolatedValue <float>(elapsedTime, out angle);
                    angle    = MathHelper.ToRadians(angle);
                    localPos = MyUtils.GetRandomVector3MaxAngle(angle) * currentSize * currentAxisScale;
                }
                else
                {
                    localPos = MyUtils.GetRandomVector3Normalized() * currentSize * currentAxisScale;
                }
                break;

            case MyParticleEmitterType.Box:
                float currentSizeHalf = currentSize * 0.5f;
                localPos =
                    new Vector3(
                        MyUtils.GetRandomFloat(-currentSizeHalf, currentSizeHalf),
                        MyUtils.GetRandomFloat(-currentSizeHalf, currentSizeHalf),
                        MyUtils.GetRandomFloat(-currentSizeHalf, currentSizeHalf)
                        ) * currentAxisScale;
                break;

            case MyParticleEmitterType.Hemisphere:
                localPos = MyUtils.GetRandomVector3HemisphereNormalized(Vector3.Forward) * currentSize * currentAxisScale;
                break;

            case MyParticleEmitterType.Circle:
                localPos = MyUtils.GetRandomVector3CircleNormalized() * currentSize * currentAxisScale;
                break;

            default:
                System.Diagnostics.Debug.Assert(false);
                break;
            }

            //if ((LimitAngle < 90 && (Type == MyParticleEmitterType.Hemisphere)) ||
            //    (LimitAngle < 180 && ((Type == MyParticleEmitterType.Sphere) || (Type == MyParticleEmitterType.Box))))
            //{
            //    var angleScaleFactor = Type == MyParticleEmitterType.Hemisphere ? LimitAngle / 90.0f : LimitAngle / 180.0f;
            //    var normalizedPos = Vector3.Normalize(localPos);
            //    var dotProduct = Vector3.Dot(Vector3.Forward, normalizedPos);
            //    var currentAngle = (float)Math.Acos(dotProduct);
            //    var finalAngle = currentAngle * angleScaleFactor;
            //    var rotationAxis = Vector3.Cross(Vector3.Forward,localPos);
            //    var rotationMatrix = Matrix.CreateFromAxisAngle(rotationAxis, finalAngle - currentAngle);
            //    Vector3.TransformNormal(ref localPos, ref rotationMatrix, out localPos);
            //}

            if (currentRotation.LengthSquared() > 0)
            {
                Matrix rotationMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(currentRotation.X));
                rotationMatrix = rotationMatrix * Matrix.CreateRotationY(MathHelper.ToRadians(currentRotation.Y));
                rotationMatrix = rotationMatrix * Matrix.CreateRotationZ(MathHelper.ToRadians(currentRotation.Z));

                Vector3.TransformNormal(ref localPos, ref rotationMatrix, out localPos);
            }


            Vector3D worldPos;

            if (DirToCamera)
            {
                if (MyUtils.IsZero(MyTransparentGeometry.Camera.Forward))
                {
                    startPosition = Vector3.Zero;
                    startOffset   = Vector3.Zero;
                    return;
                }
                MatrixD WorldView = worldMatrix * MyTransparentGeometry.CameraView;
                WorldView.Translation += currentOffsetUntransformed;
                MatrixD newWorld = WorldView * MatrixD.Invert(MyTransparentGeometry.CameraView);

                Vector3D dir = MyTransparentGeometry.Camera.Translation - newWorld.Translation;
                dir.Normalize();

                MatrixD matrix = MatrixD.CreateFromDir(dir);
                matrix.Translation = newWorld.Translation;

                Vector3D.Transform(ref localPos, ref matrix, out worldPos);

                startOffset   = newWorld.Translation;
                startPosition = worldPos;
            }
            else
            {
                Vector3D.TransformNormal(ref localPos, ref worldMatrix, out worldPos);

                startOffset   = worldOffset;
                startPosition = worldOffset + worldPos;
            }
        }
        public static Vector3D Transform(this Vector3D vector, SerializableBlockOrientation orientation)
        {
            var matrix = MatrixD.CreateFromDir(Base6Directions.GetVector(orientation.Forward), Base6Directions.GetVector(orientation.Up));

            return(Vector3D.Transform(vector, matrix));
        }