Ejemplo n.º 1
0
        internal static void AddBillboardOriented(string material,
                                                  Color color, Vector3D origin, Vector3 leftVector, Vector3 upVector, float radius, int priority = 0, float softParticleDistanceScale = 1.0f,
                                                  int customViewProjection = -1)
        {
            if (!MyRender11.DebugOverrides.BillboardsDynamic)
            {
                return;
            }

            Debug.Assert(material != null);

            origin.AssertIsValid();
            leftVector.AssertIsValid();
            upVector.AssertIsValid();
            radius.AssertIsValid();
            MyDebug.AssertDebug(radius > 0);

            MyBillboard billboard = MyBillboardRenderer.AddBillboardOnce();

            if (billboard == null)
            {
                return;
            }

            billboard.Priority             = priority;
            billboard.CustomViewProjection = customViewProjection;

            MyQuadD quad;

            MyUtils.GetBillboardQuadOriented(out quad, ref origin, radius, ref leftVector, ref upVector);

            CreateBillboard(billboard, ref quad, material, ref color, ref origin, softParticleDistanceScale);
        }
Ejemplo n.º 2
0
        internal static void AddPointBillboard(string material,
                                               Color color, Vector3D origin, float radius, float angle, int priority = 0, int customViewProjection = -1)
        {
            if (!MyRender11.DebugOverrides.BillboardsDynamic)
            {
                return;
            }
            Debug.Assert(material != null);

            origin.AssertIsValid();
            angle.AssertIsValid();

            MyQuadD quad;

            if (MyUtils.GetBillboardQuadAdvancedRotated(out quad, origin, radius, angle, MyRender11.Environment.Matrices.CameraPosition) != false)
            {
                MyBillboard billboard = MyBillboardRenderer.AddBillboardOnce();
                if (billboard == null)
                {
                    return;
                }

                billboard.Priority             = priority;
                billboard.CustomViewProjection = customViewProjection;
                CreateBillboard(billboard, ref quad, material, ref color, ref origin);
            }
        }
        internal static void AddBillboardOriented(string material,
                                                  Color color, Vector3D origin, Vector3 leftVector, Vector3 upVector, float radius, int priority = 0, int customViewProjection = -1)
        {
            Debug.Assert(material != null);

            origin.AssertIsValid();
            leftVector.AssertIsValid();
            upVector.AssertIsValid();
            radius.AssertIsValid();
            MyDebug.AssertDebug(radius > 0);

            MyBillboard billboard = SpawnBillboard();

            if (billboard == null)
            {
                return;
            }

            billboard.Priority             = priority;
            billboard.CustomViewProjection = customViewProjection;

            MyQuadD quad;

            MyUtils.GetBillboardQuadOriented(out quad, ref origin, radius, ref leftVector, ref upVector);

            CreateBillboard(billboard, ref quad, material, ref color, ref origin);
        }
Ejemplo n.º 4
0
        private void CalculateRotationHint(ref MatrixD parentMatrix, ref Vector3 desiredForward)
        {
            Vector3D gravityUp = m_parent.UpVector;

            if (desiredForward.LengthSquared() == 0)
            {
                m_rotationHint.X = m_rotationHint.Y = 0;
                return;
            }

            // CH: Note: The XZ and YZ in the vector names does not mean that other components are zero!
            // They would be zero in local coords, but these vectors are global!
            Vector3D desiredForwardXZ = Vector3D.Reject(desiredForward, parentMatrix.Up);
            Vector3D desiredForwardYZ = Vector3D.Reject(desiredForward, parentMatrix.Right);

            desiredForwardXZ.Normalize();
            desiredForwardYZ.Normalize();

            desiredForwardXZ.AssertIsValid();
            desiredForwardYZ.AssertIsValid();

            m_dbgDesiredForward = desiredForward;

            /*Vector3D parentForward = parentMatrix.Forward;
             * parentForward.Normalize();
             * parentForward.AssertIsValid();
             *
             * // Flip Z component of the parent forward, when the desiredForwardYZ Z component is oposite sign ???
             * // And it's not used...
             * if (desiredForwardYZ.Z * parentForward.Z < 0)
             *  parentForward.Z = -parentForward.Z;*/

            double angleY = 0;
            double angleX = 0;

            double parentHeight  = Vector3D.Dot(parentMatrix.Forward, gravityUp);
            double desiredHeight = Vector3D.Dot(desiredForward, gravityUp);

            angleX = Vector3D.Dot(parentMatrix.Forward, desiredForwardYZ);
            angleX = MathHelper.Clamp(angleX, -1, 1);
            angleX = Math.Acos(angleX);
            if (desiredHeight > parentHeight) // rotate in correct direction
            {
                angleX = -angleX;
            }

            angleY = Vector3D.Dot(parentMatrix.Forward, desiredForwardXZ);
            angleY = MathHelper.Clamp(angleY, -1, 1);
            angleY = Math.Acos(angleY);
            double det = Vector3D.Dot(parentMatrix.Right, desiredForwardXZ);

            if (det < 0) // rotate in correct direction
            {
                angleY = -angleY;
            }

            m_rotationHint.X = MathHelper.Clamp((float)angleY, -3.0f, 3.0f);
            m_rotationHint.Y = MathHelper.Clamp((float)angleX, -3.0f, 3.0f);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Sets the position.
        /// </summary>
        /// <param name="pos">The pos.</param>
        public void SetPosition(Vector3D pos)
        {
            pos.AssertIsValid();

            if (!MyUtils.IsZero(m_worldMatrix.Translation - pos))
            {
                m_worldMatrix.Translation = pos;
                UpdateWorldMatrix();
            }
        }
Ejemplo n.º 6
0
 public void SetPosition(Vector3D position)
 {
     if (Vector3D.DistanceSquared(Position, position) > 0.0001)
     {
         position.AssertIsValid();
         Position          = position;
         m_spotParamsDirty = true;
         UpdatePositionWithOffset();
         m_pointBoundingSphere.Center = PositionWithOffset;
     }
 }
Ejemplo n.º 7
0
        private void SetPositionAndLookAt(Vector3D lookAt)
        {
            m_lookAt = lookAt;

            m_transformedLookAt = Vector3D.Transform(lookAt, m_targetOrientation);
            m_positionSafe      = m_target + m_transformedLookAt;
            m_desiredPosition   = m_positionSafe;
            m_position          = m_positionSafe;
            m_velocity          = Vector3.Zero;

            m_positionSafe.AssertIsValid();
        }
Ejemplo n.º 8
0
        private void CalculateRotationHint(ref MatrixD parentMatrix, ref Vector3 desiredForward)
        {
            if (desiredForward.LengthSquared() == 0)
            {
                m_rotationHint.X = m_rotationHint.Y = 0;
                return;
            }

            Vector3D desiredForwardXZ = Vector3D.Reject(desiredForward, parentMatrix.Up);

            desiredForwardXZ.Normalize();
            desiredForwardXZ.AssertIsValid();

            Vector3D desiredForwardYZ = Vector3D.Reject(desiredForward, parentMatrix.Right);

            desiredForwardYZ.Normalize();
            desiredForwardYZ.AssertIsValid();

            /*Vector3D parentForward = parentMatrix.Forward;
             * parentForward.Normalize();
             * parentForward.AssertIsValid();
             *
             * // Flip Z component of the parent forward, when the desiredForwardYZ Z component is oposite sign ???
             * // And it's not used...
             * if (desiredForwardYZ.Z * parentForward.Z < 0)
             *  parentForward.Z = -parentForward.Z;*/

            double angleY = 0;
            double angleX = 0;

            angleX = Vector3D.Dot(parentMatrix.Forward, desiredForwardYZ);
            angleX = MathHelper.Clamp(angleX, -1, 1);
            angleX = Math.Acos(angleX);
            if (desiredForwardYZ.Y > parentMatrix.Forward.Y) // rotate in correct direction
            {
                angleX = -angleX;
            }

            angleY = Vector3D.Dot(parentMatrix.Forward, desiredForwardXZ);
            angleY = MathHelper.Clamp(angleY, -1, 1);
            angleY = Math.Acos(angleY);
            var det = desiredForwardXZ.X * parentMatrix.Forward.Z - desiredForwardXZ.Z * parentMatrix.Forward.X;

            if (det > 0) // rotate in correct direction
            {
                angleY = -angleY;
            }

            m_rotationHint.X = MathHelper.Clamp((float)angleY, -3.0f, 3.0f);
            m_rotationHint.Y = MathHelper.Clamp((float)angleX, -3.0f, 3.0f);
            Vector3D localDesiredForward = VRageMath.Vector3D.TransformNormal(desiredForward, VRageMath.MatrixD.Invert(parentMatrix));
        }
        private void SetPositionAndLookAt(Vector3D lookAt)
        {
            double dist = lookAt.Length();

            m_lookAt = (MySession.Static == null || !(MySession.Static.CameraController is MyCharacter) ? m_lookAtDirection : m_lookAtDirectionCharacter) * dist;

            m_transformedLookAt = Vector3D.Transform(lookAt, m_targetOrientation);
            m_positionSafe      = m_target + m_transformedLookAt;
            m_desiredPosition   = m_positionSafe;
            m_position          = m_positionSafe;
            m_velocity          = Vector3.Zero;

            m_positionSafe.AssertIsValid();
        }
        private void ProcessSpringCalculation()
        {
            Vector3D stretch = m_position - m_desiredPosition;
            Vector3D force   = -m_currentSpring.Stiffness * stretch - m_currentSpring.Dampening * m_velocity;

            force.AssertIsValid();
            // Apply acceleration
            Vector3 acceleration = (Vector3)force / m_currentSpring.Mass;

            m_velocity += acceleration * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
            m_velocity.AssertIsValid();
            // Apply velocity
            m_position += m_velocity * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
            m_position.AssertIsValid();
        }
Ejemplo n.º 11
0
        private void CalculateRotationHint(ref MatrixD parentMatrix, ref Vector3 desiredForward)
        {
            if (desiredForward.LengthSquared() == 0)
            {
                m_rotationHint.X = m_rotationHint.Y = 0;
                return;
            }

            Vector3D desiredForwardXZ = Vector3D.Reject(desiredForward, parentMatrix.Up);
            Vector3D parentForward    = parentMatrix.Forward;
            Vector3D desiredForwardYZ = Vector3D.Reject(desiredForward, parentMatrix.Right);

            desiredForwardXZ.Normalize();
            parentForward.Normalize();
            desiredForwardYZ.Normalize();
            parentForward.AssertIsValid();
            desiredForwardYZ.AssertIsValid();
            desiredForwardXZ.AssertIsValid();

            if (desiredForwardYZ.Z * parentForward.Z < 0)
            {
                parentForward.Z = -parentForward.Z;
            }

            double angleY = 0;
            double angleX = 0;

            angleX = Vector3D.Dot(parentMatrix.Forward, desiredForwardYZ);
            angleX = MathHelper.Clamp(angleX, -1, 1);
            angleX = Math.Acos(angleX);
            if (desiredForwardYZ.Y > parentMatrix.Forward.Y) // rotate in correct direction
            {
                angleX = -angleX;
            }

            angleY = Vector3D.Dot(parentMatrix.Forward, desiredForwardXZ);
            angleY = MathHelper.Clamp(angleY, -1, 1);
            angleY = Math.Acos(angleY);
            var det = desiredForwardXZ.X * parentMatrix.Forward.Z - desiredForwardXZ.Z * parentMatrix.Forward.X;

            if (det > 0) // rotate in correct direction
            {
                angleY = -angleY;
            }

            m_rotationHint.X = (float)angleY;
            m_rotationHint.Y = (float)angleX;
        }
Ejemplo n.º 12
0
        public void ResetPosition(double distance, Vector2?headAngle)
        {
            if (headAngle.HasValue)
            {
                Sandbox.Game.Entities.IMyControllableEntity controlledEntity = MySession.Static.ControlledEntity as Sandbox.Game.Entities.IMyControllableEntity;
                if (controlledEntity == null)
                {
                    return;
                }

                controlledEntity.HeadLocalXAngle = headAngle.Value.X;
                controlledEntity.HeadLocalYAngle = headAngle.Value.Y;

                ResetDistance(distance);

                m_positionSafe.AssertIsValid();
            }
        }
Ejemplo n.º 13
0
        internal static void AddPointBillboard(string material,
           Color color, Vector3D origin, float radius, float angle, int priority = 0, int customViewProjection = -1)
        {
            Debug.Assert(material != null);

            origin.AssertIsValid();
            angle.AssertIsValid();

            MyQuadD quad;
            if (MyUtils.GetBillboardQuadAdvancedRotated(out quad, origin, radius, angle, MyEnvironment.CameraPosition) != false)
            {
                MyBillboard billboard = SpawnBillboard();
                if (billboard == null)
                    return;

                billboard.Priority = priority;
                billboard.CustomViewProjection = customViewProjection;
                CreateBillboard(billboard, ref quad, material, ref color, ref origin);
            }
        }
Ejemplo n.º 14
0
        public MatrixD GetViewMatrix(float fov, float zoomLevel, bool shakeActive, Vector3D headPosition, Vector3 headDirection)
        {
            System.Diagnostics.Debug.Assert(m_lookAt.LengthSquared() > 0);

            Vector3D position    = m_positionSafe;
            Matrix   orientation = m_orientationMatrix;

            var distance = (m_target - position).Length();

            position.AssertIsValid();
            distance.AssertIsValid();

            // Push ship down (crosshair approx in middle of screen)
            var      shipVerticalShift = Math.Tan(fov / 2) * 0.1 * distance;
            Vector3D lookVector        = m_target + (Vector3D)orientation.Up * shipVerticalShift - position;

            float zoomPhase = MathHelper.Clamp((1.0f - zoomLevel) * 4, 0, 1);

            if (zoomLevel != 1)
            {
                // Normalize directions for more linear interpolation
                Vector3 lookDirection      = (Vector3)Vector3D.Normalize(lookVector);
                Vector3 crosshairDirection = (Vector3)Vector3D.Normalize(GetCrosshair() - position);
                lookVector = (Vector3D)Vector3.Lerp(lookDirection, crosshairDirection, zoomPhase);
            }

            // Apply headshake
            if (shakeActive)
            {
                position += (Vector3D)Vector3D.Transform(headPosition, orientation) * distance * HEADSHAKE_POWER;
                Matrix matrixRotation = Matrix.CreateFromAxisAngle(Vector3.Forward, headDirection.Z) * Matrix.CreateFromAxisAngle(Vector3.Right, headDirection.X);
                lookVector = Vector3D.Transform(lookVector, matrixRotation);
            }

            return(MatrixD.CreateLookAt(position, position + lookVector, m_targetOrientation.Up));
        }
Ejemplo n.º 15
0
 private void ProcessSpringCalculation()
 {
     Vector3D stretch = m_position - m_desiredPosition;
     Vector3D force = -m_currentSpring.Stiffness * stretch - m_currentSpring.Dampening * m_velocity;
     force.AssertIsValid();
     // Apply acceleration
     Vector3 acceleration = (Vector3) force / m_currentSpring.Mass;
     m_velocity += acceleration * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
     m_velocity.AssertIsValid();
     // Apply velocity
     m_position += m_velocity * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
     m_position.AssertIsValid();
 }
Ejemplo n.º 16
0
        /// <summary>
        /// Applies the impulse.
        /// </summary>
        /// <param name="impulse">The dir.</param>
        /// <param name="pos">The pos.</param>
        public override void ApplyImpulse(Vector3 impulse, Vector3D pos)
        {
            impulse.AssertIsValid();
            pos.AssertIsValid();
            System.Diagnostics.Debug.Assert(IsInWorld == true);

            var offset = MyPhysics.Clusters.GetObjectOffset(ClusterObjectID);
            var posF = (Vector3)(pos - offset);

            RigidBody.ApplyPointImpulse(impulse, posF);
        }
Ejemplo n.º 17
0
        internal static void AddBillboardOriented(string material,
            Color color, Vector3D origin, Vector3 leftVector, Vector3 upVector, float radius, int priority = 0, int customViewProjection = -1)
        {
            Debug.Assert(material != null);

            origin.AssertIsValid();
            leftVector.AssertIsValid();
            upVector.AssertIsValid();
            radius.AssertIsValid();
            MyDebug.AssertDebug(radius > 0);

            MyBillboard billboard = SpawnBillboard();
            if (billboard == null)
                return;

            billboard.Priority = priority;
            billboard.CustomViewProjection = customViewProjection;

            MyQuadD quad;
            MyUtils.GetBillboardQuadOriented(out quad, ref origin, radius, ref leftVector, ref upVector);

            CreateBillboard(billboard, ref quad, material, ref color, ref origin);
        }
Ejemplo n.º 18
0
        public static void SetCameraViewMatrix(MatrixD viewMatrix, Matrix projectionMatrix, Matrix nearProjectionMatrix, float safenear, float nearFov, float fov,
            float nearPlane, float farPlane, float nearObjectsNearPlane, float nearObjectsFarPlane,
            Vector3D cameraPosition)
        {
            var message = MessagePool.Get<MyRenderMessageSetCameraViewMatrix>(MyRenderMessageEnum.SetCameraViewMatrix);

            cameraPosition.AssertIsValid();

            message.ViewMatrix = viewMatrix;
            message.ProjectionMatrix = projectionMatrix;
            message.NearProjectionMatrix = nearProjectionMatrix;
            message.SafeNear = safenear;
            message.NearFOV = nearFov;
            message.FOV = fov;
            message.NearPlane = nearPlane;
            message.FarPlane = farPlane;
            message.NearObjectsNearPlane = nearObjectsNearPlane;
            message.NearObjectsFarPlane = nearObjectsFarPlane;
            message.CameraPosition = cameraPosition;

            EnqueueMessage(message);
        }
        internal static void AddBillboardOriented(string material,
            Color color, Vector3D origin, Vector3 leftVector, Vector3 upVector, float radius, int priority = 0, float softParticleDistanceScale = 1.0f, 
            int customViewProjection = -1)
        {
            if (!MyRender11.DebugOverrides.BillboardsDynamic)
                return;

            Debug.Assert(material != null);

            origin.AssertIsValid();
            leftVector.AssertIsValid();
            upVector.AssertIsValid();
            radius.AssertIsValid();
            MyDebug.AssertDebug(radius > 0);

            MyBillboard billboard = MyBillboardRenderer.AddBillboardOnce();
            if (billboard == null)
                return;

            billboard.Priority = priority;
            billboard.CustomViewProjection = customViewProjection;

            MyQuadD quad;
            MyUtils.GetBillboardQuadOriented(out quad, ref origin, radius, ref leftVector, ref upVector);

            CreateBillboard(billboard, ref quad, material, ref color, ref origin, softParticleDistanceScale);
        }
Ejemplo n.º 20
0
        static bool GatherInternal()
        {
            m_batches.Clear();

            // counting sorted billboards
            ClearBucketCounts();
            PreGatherList(MyRenderProxy.BillboardsRead);
            PreGatherList(m_billboardsOnce);

            int billboardCount = 0;

            for (int j = 0; j < BUCKETS_COUNT; j++)
            {
                billboardCount += m_bucketCounts[j];
            }
            if (billboardCount == 0)
            {
                return(false);
            }

            m_billboardCountSafe = billboardCount > MAX_BILLBOARDS_SIZE ? MAX_BILLBOARDS_SIZE : billboardCount;

            InitGatherList(billboardCount, m_billboardCountSafe);
            InitBucketIndices();

            GatherList(MyRenderProxy.BillboardsRead);
            GatherList(m_billboardsOnce);

            InitBucketIndices();

            int i;

            for (i = 0; i < BUCKETS_COUNT; i++)
            {
                Array.Sort(m_tempBuffer, m_bucketIndices[i], m_bucketCounts[i]);
            }

            bool                  resetBindings = false;
            int                   currentOffset = 0;
            ISrvBindable          prevTex       = null;
            MyTransparentMaterial prevMaterial  = null;

            for (i = 0; i < m_billboardCountSafe; i++)
            {
                MyBillboard           billboard = m_tempBuffer[i];
                MyTransparentMaterial material  = MyTransparentMaterials.GetMaterial(billboard.Material);
                ISrvBindable          batchTex  = null;
                if (material.UseAtlas)
                {
                    var atlasItem = m_atlas.FindElement(material.Texture);
                    batchTex = atlasItem.Texture;
                }
                else
                {
                    MyFileTextureManager texManager = MyManagers.FileTextures;
                    switch (material.TextureType)
                    {
                    case MyTransparentMaterialTextureType.FileTexture:
                        if (material.Texture == null || !m_fileTextures.TryGetValue(material.Texture, out batchTex))
                        {
                            batchTex = texManager.GetTexture(material.Texture, MyFileTextureEnum.GUI, true);
                            if (material.Texture != null)
                            {
                                m_fileTextures.Add(material.Texture, batchTex);
                            }
                            else
                            {
                                MyRenderProxy.Fail("Material: " + material.Name + " is missing a texture.");
                            }
                        }

                        break;

                    case MyTransparentMaterialTextureType.RenderTarget:
                        batchTex      = MyRender11.DrawSpritesOffscreen(material.Name, material.TargetSize.X, material.TargetSize.Y);
                        resetBindings = true;
                        break;

                    default:
                        throw new Exception();
                    }
                }

                bool boundary   = IsBucketBoundary(i);
                bool closeBatch = i > 0 && (batchTex != prevTex || boundary);
                if (closeBatch)
                {
                    AddBatch(i, currentOffset, prevTex, prevMaterial);
                    currentOffset = i;
                }


                var billboardData     = new MyBillboardData();
                var billboardVertices = new MyBillboardVertexData();

                billboardData.CustomProjectionID = billboard.CustomViewProjection;
                billboardData.Color                     = billboard.Color;
                billboardData.Color.X                  *= billboard.ColorIntensity;
                billboardData.Color.Y                  *= billboard.ColorIntensity;
                billboardData.Color.Z                  *= billboard.ColorIntensity;
                billboardData.AlphaCutout               = billboard.AlphaCutout;
                billboardData.AlphaSaturation           = material.AlphaSaturation;
                billboardData.SoftParticleDistanceScale = billboard.SoftParticleDistanceScale * material.SoftParticleDistanceScale;

                billboardData.Reflective = billboard.Reflectivity;
                Vector3D pos0 = billboard.Position0;
                Vector3D pos1 = billboard.Position1;
                Vector3D pos2 = billboard.Position2;
                Vector3D pos3 = billboard.Position3;

                if (billboard.ParentID != -1)
                {
                    var parent = MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID);

                    if (parent != null)
                    {
                        var matrix = parent.WorldMatrix;
                        Vector3D.Transform(ref pos0, ref matrix, out pos0);
                        Vector3D.Transform(ref pos1, ref matrix, out pos1);
                        Vector3D.Transform(ref pos2, ref matrix, out pos2);
                        Vector3D.Transform(ref pos3, ref matrix, out pos3);
                    }
                }

                MyEnvironmentMatrices envMatrices = MyRender11.Environment.Matrices;
                if (MyStereoRender.Enable)
                {
                    if (MyStereoRender.RenderRegion == MyStereoRegion.LEFT)
                    {
                        envMatrices = MyStereoRender.EnvMatricesLeftEye;
                    }
                    else if (MyStereoRender.RenderRegion == MyStereoRegion.RIGHT)
                    {
                        envMatrices = MyStereoRender.EnvMatricesRightEye;
                    }
                }

                if (billboard.CustomViewProjection == -1)
                {
                    pos0 -= envMatrices.CameraPosition;
                    pos1 -= envMatrices.CameraPosition;
                    pos2 -= envMatrices.CameraPosition;
                    pos3 -= envMatrices.CameraPosition;
                }

                var normal = Vector3D.Cross(pos1 - pos0, pos2 - pos0);
                normal.Normalize();

                billboardData.Normal = normal;

                billboardVertices.V0.Position = pos0;
                billboardVertices.V1.Position = pos1;
                billboardVertices.V2.Position = pos2;
                billboardVertices.V3.Position = pos3;

                var uv0 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y);
                var uv1 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y);
                var uv2 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y);
                var uv3 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y);

                if (material.UseAtlas)
                {
                    var atlasItem = m_atlas.FindElement(material.Texture);

                    uv0 = uv0 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv1 = uv1 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv2 = uv2 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv3 = uv3 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                }

                billboardVertices.V0.Texcoord = new HalfVector2(uv0);
                billboardVertices.V1.Texcoord = new HalfVector2(uv1);
                billboardVertices.V2.Texcoord = new HalfVector2(uv2);
                billboardVertices.V3.Texcoord = new HalfVector2(uv3);

                pos0.AssertIsValid();
                pos1.AssertIsValid();
                pos2.AssertIsValid();
                pos3.AssertIsValid();


                MyTriangleBillboard triBillboard = billboard as MyTriangleBillboard;
                if (triBillboard != null)
                {
                    billboardVertices.V3.Position = pos2; // second triangle will die in rasterizer

                    billboardVertices.V0.Texcoord = new HalfVector2(triBillboard.UV0);
                    billboardVertices.V1.Texcoord = new HalfVector2(triBillboard.UV1);
                    billboardVertices.V2.Texcoord = new HalfVector2(triBillboard.UV2);

                    billboardData.Normal = triBillboard.Normal0;
                }

                m_arrayDataBillboards.Data[i]   = billboardData;
                m_arrayDataBillboards.Vertex[i] = billboardVertices;

                prevTex      = batchTex;
                prevMaterial = material;
            }
            AddBatch(m_billboardCountSafe, currentOffset, prevTex, prevMaterial);

            TransferDataCustomProjections();
            TransferDataBillboards(0, m_billboardCountSafe, ref m_arrayDataBillboards);

            return(resetBindings);
        }
Ejemplo n.º 21
0
        private void SetPositionAndLookAt(Vector3D lookAt)
        {
            double dist = lookAt.Length();
            m_lookAt = (MySession.Static == null || !(MySession.Static.CameraController is MyCharacter) ? m_lookAtDirection : m_lookAtDirectionCharacter) * dist;

            m_transformedLookAt = Vector3D.Transform(lookAt, m_targetOrientation);
            m_positionSafe = m_target + m_transformedLookAt;
            m_desiredPosition = m_positionSafe;
            m_position = m_positionSafe;
            m_velocity = Vector3.Zero;

            m_positionSafe.AssertIsValid();
        }
        // Updates spectator position (spring connected to desired position)
        public override void UpdateAfterSimulation()
        {
            Game.Entities.IMyControllableEntity genericControlledEntity = MySession.Static.ControlledEntity;
            if (genericControlledEntity == null)
            {
                return;
            }
            var remotelyControlledEntity = genericControlledEntity as MyRemoteControl;
            var controlledEntity         = remotelyControlledEntity != null ? remotelyControlledEntity.Pilot : genericControlledEntity.Entity;

            while (controlledEntity.Parent is MyCockpit)
            {
                controlledEntity = controlledEntity.Parent;
            }
            if (controlledEntity != null && controlledEntity.PositionComp != null)
            {
                var      positionComp = controlledEntity.PositionComp;
                float    localY       = positionComp.LocalAABB.Max.Y - positionComp.LocalAABB.Min.Y;
                Vector3D lastTarget   = m_target;
                var      headMatrix   = remotelyControlledEntity == null?genericControlledEntity.GetHeadMatrix(true) : remotelyControlledEntity.Pilot.GetHeadMatrix(true);

                m_target            = controlledEntity is MyCharacter ? ((positionComp.GetPosition() + (localY + m_lookAtOffsetY) * positionComp.WorldMatrix.Up)) : headMatrix.Translation;
                m_targetOrientation = headMatrix.GetOrientation();
                m_targetUpVec       = m_positionCurrentIsSafe ? (Vector3D)m_targetOrientation.Up : positionComp.WorldMatrix.Up;
                m_transformedLookAt = Vector3D.Transform(m_clampedlookAt, m_targetOrientation);
                m_desiredPosition   = m_target + m_transformedLookAt;

                m_position += m_target - lastTarget; // compensate character movement

                //m_position = m_desiredPosition;
            }
            else
            {
                var headMatrix = genericControlledEntity.GetHeadMatrix(true);
                m_target            = headMatrix.Translation;
                m_targetOrientation = headMatrix.GetOrientation();
                m_targetUpVec       = m_targetOrientation.Up;

                m_transformedLookAt = Vector3D.Transform(m_clampedlookAt, m_targetOrientation);
                m_desiredPosition   = m_target + m_transformedLookAt;
                m_position          = m_desiredPosition;
            }

            Vector3D stretch = m_position - m_desiredPosition;

            Vector3D force = -m_currentSpring.Stiffness * stretch - m_currentSpring.Dampening * m_velocity;

            force.AssertIsValid();

            // Apply acceleration
            Vector3 acceleration = (Vector3)force / m_currentSpring.Mass;

            m_velocity += acceleration * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
            m_velocity.AssertIsValid();

            // Apply velocity
            m_position += m_velocity * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
            m_position.AssertIsValid();

            if (m_disableSpringThisFrame)
            {
                double smoothCoeff = 0.8;
                m_position = Vector3D.Lerp(m_position, m_desiredPosition, smoothCoeff);
                m_disableSpringThisFrame = false;
            }

            // Limit backward distance from target
            double backward = Vector3D.Dot(m_targetOrientation.Backward, (m_target - m_position));

            if (backward > -m_backwardCutoff)
            {
                m_position += (Vector3D)m_targetOrientation.Backward * (backward + m_backwardCutoff);
            }

            // -------- raycast, prevent camera being inside things ------
            if (controlledEntity != null)
            {
                if (!controlledEntity.Closed)
                {
                    HandleIntersection(controlledEntity);
                }
                else
                {
                    m_positionCurrentIsSafe = false;
                }
            }

            // ------- save current settings -------
            if (m_saveSettings)
            {
                MySession.Static.SaveControlledEntityCameraSettings(false);
                m_saveSettings = false;
            }
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Applies external force to the physics object.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="force">The force.</param>
        /// <param name="position">The position.</param>
        /// <param name="torque">The torque.</param>
        public override void AddForce(MyPhysicsForceType type, Vector3? force, Vector3D? position, Vector3? torque)
        {
            force.AssertIsValid();
            position.AssertIsValid();
            torque.AssertIsValid();

            System.Diagnostics.Debug.Assert(IsInWorld == true || IsWelded);

            if (IsStatic)
                return;

            Matrix transform;

            switch (type)
            {
                case MyPhysicsForceType.ADD_BODY_FORCE_AND_BODY_TORQUE:
                    {
                        if (RigidBody != null)
                        {
                            transform = RigidBody.GetRigidBodyMatrix();
                            AddForceTorqueBody(force, torque, RigidBody, ref transform);
                        }
                        if (CharacterProxy != null)
                        {
                            transform = Entity.WorldMatrix;
                            AddForceTorqueBody(force, torque, CharacterProxy.GetHitRigidBody(), ref transform);
                        }
                        if (Ragdoll != null && Ragdoll.IsAddedToWorld && !Ragdoll.IsKeyframed)
                        {
                            transform = Entity.WorldMatrix;
                            ApplyForceTorqueOnRagdoll(force, torque, Ragdoll, ref transform);
                        }
                    }
                    break;
                case MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE:
                    {
                        ApplyImplusesWorld(force, position, torque, RigidBody);

                        if (CharacterProxy != null && force.HasValue && position.HasValue)
                        {
                            CharacterProxy.ApplyLinearImpulse(force.Value);
                        }
                        if (Ragdoll != null && Ragdoll.IsAddedToWorld && !Ragdoll.IsKeyframed)
                        {
                            ApplyImpuseOnRagdoll(force, position, torque, Ragdoll);
                        }
                    }
                    break;
                case MyPhysicsForceType.APPLY_WORLD_FORCE:
                    {
                        ApplyForceWorld(force, position, RigidBody);

                        if (Ragdoll != null && Ragdoll.IsAddedToWorld && !Ragdoll.IsKeyframed)
                        {
                            ApplyForceOnRagdoll(force, position, Ragdoll);
                        }
                    }

                    break;
                default:
                    {
                        Debug.Fail("Unhandled enum!");
                    }
                    break;
            }
        }
Ejemplo n.º 24
0
        private void SetPositionAndLookAt(Vector3D lookAt)
        {
            m_lookAt = lookAt;

            m_transformedLookAt = Vector3D.Transform(lookAt, m_targetOrientation);
            m_positionSafe = m_target + m_transformedLookAt;
            m_desiredPosition = m_positionSafe;
            m_position = m_positionSafe;
            m_velocity = Vector3.Zero;

            m_positionSafe.AssertIsValid();
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Applies external force to the physics object.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="force">The force.</param>
        /// <param name="position">The position.</param>
        /// <param name="torque">The torque.</param>
        public override void AddForce(MyPhysicsForceType type, Vector3? force, Vector3D? position, Vector3? torque)
        {
            force.AssertIsValid();
            position.AssertIsValid();
            torque.AssertIsValid();

            System.Diagnostics.Debug.Assert(IsInWorld == true);

            if (IsStatic)
                return;

            switch (type)
            {
                case MyPhysicsForceType.ADD_BODY_FORCE_AND_BODY_TORQUE:
                    {
                        if (RigidBody != null)
                        {
                            Matrix tempM = RigidBody.GetRigidBodyMatrix();
                            tempM.Translation = Vector3.Zero;

                            if (force != null && !MyUtils.IsZero(force.Value))
                            {
                                Vector3 tmpForce = Vector3.Transform(force.Value, tempM);

                                //RigidBody.Activate(true);
                                //RigidBody.ApplyForce(MyEngineConstants.PHYSICS_STEP_SIZE_IN_SECONDS, tmpForce * 0.0001f);
                                RigidBody.ApplyLinearImpulse(tmpForce * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * MyFakes.SIMULATION_SPEED);
                                //RigidBody.ApplyCentralImpulse(tmpForce);
                            }

                            if (torque != null && !MyUtils.IsZero(torque.Value))
                            {
                                Vector3 tmpTorque = Vector3.Transform(torque.Value, tempM);
                                //SharpDX.Vector3 tmpTorque = SharpDXHelper.ToSharpDX(torque.Value);

                                // RigidBody.Activate(true);
                                //RigidBody.UpdateInertiaTensor();
                                //RigidBody.ApplyTorque(MyEngineConstants.PHYSICS_STEP_SIZE_IN_SECONDS, tmpTorque * 0.0001f);
                                RigidBody.ApplyAngularImpulse(tmpTorque * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * MyFakes.SIMULATION_SPEED);
                                //RigidBody.ApplyTorqueImpulse(tmpTorque);
                            }
                        }
                        if (CharacterProxy != null)
                        {
                            Matrix tempM = Entity.WorldMatrix;
                            tempM.Translation = Vector3.Zero;

                            if (force != null && !MyUtils.IsZero(force.Value))
                            {
                                Vector3 tmpForce = Vector3.Transform(force.Value, tempM);

                                CharacterProxy.ApplyLinearImpulse(tmpForce * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * MyFakes.SIMULATION_SPEED);
                            }
                            if (torque != null && !MyUtils.IsZero(torque.Value))
                            {
                                Vector3 tmpTorque = Vector3.Transform(torque.Value, tempM);

                                CharacterProxy.ApplyAngularImpulse(tmpTorque * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * MyFakes.SIMULATION_SPEED);
                            }
                        }
                        if (Ragdoll != null && Ragdoll.IsAddedToWorld && !Ragdoll.IsKeyframed)
                        {
                            
                            foreach (var rigidBody in Ragdoll.RigidBodies)
                            {

                                if (rigidBody != null)
                                {
                                    Matrix tempM = rigidBody.GetRigidBodyMatrix();
                                    tempM.Translation = Vector3.Zero;                                    
                                    if (force != null && !MyUtils.IsZero(force.Value))
                                    {
                                        Vector3 tmpForce = Vector3.Transform(force.Value, tempM) * rigidBody.Mass / Ragdoll.Mass;

                                        //RigidBody.Activate(true);
                                        //RigidBody.ApplyForce(MyEngineConstants.PHYSICS_STEP_SIZE_IN_SECONDS, tmpForce * 0.0001f);
                                        rigidBody.ApplyLinearImpulse(tmpForce * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * MyFakes.SIMULATION_SPEED);
                                        //RigidBody.ApplyCentralImpulse(tmpForce);
                                    }

                                    if (torque != null && !MyUtils.IsZero(torque.Value))
                                    {
                                        Vector3 tmpTorque = Vector3.Transform(torque.Value, tempM) * rigidBody.Mass / Ragdoll.Mass;
                                        //SharpDX.Vector3 tmpTorque = SharpDXHelper.ToSharpDX(torque.Value);

                                        // RigidBody.Activate(true);
                                        //RigidBody.UpdateInertiaTensor();
                                        //RigidBody.ApplyTorque(MyEngineConstants.PHYSICS_STEP_SIZE_IN_SECONDS, tmpTorque * 0.0001f);
                                        rigidBody.ApplyAngularImpulse(tmpTorque * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * MyFakes.SIMULATION_SPEED);
                                        //RigidBody.ApplyTorqueImpulse(tmpTorque);
                                    }
                                }
                            }
                        }
                    }
                    break;
                case MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE:
                    {
                        if (RigidBody != null)
                        {
                            var offset = MyPhysics.Clusters.GetObjectOffset(ClusterObjectID);

                            if (force.HasValue && position.HasValue)
                            {
                                //this.RigidBody.ApplyImpulse(force.Value, position.Value);
                                //RigidBody.Activate(true);
                                RigidBody.ApplyPointImpulse(force.Value, (Vector3)(position.Value - offset));
                            }

                            if (torque.HasValue)
                            {
                                //RigidBody.Activate(true);
                                //RigidBody.ApplyTorque(MyEngineConstants.PHYSICS_STEP_SIZE_IN_SECONDS, torque.Value * 0.0001f);
                                RigidBody.ApplyAngularImpulse(torque.Value * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * MyFakes.SIMULATION_SPEED);
                            }
                        }

                        if (CharacterProxy != null && force.HasValue && position.HasValue)
                        {
                            CharacterProxy.ApplyLinearImpulse(force.Value);
                        }
                        if (Ragdoll != null && Ragdoll.IsAddedToWorld && !Ragdoll.IsKeyframed)
                        {
                            foreach (var rigidBody in Ragdoll.RigidBodies)
                            {
                                if (rigidBody != null)
                                {
                                    var offset = MyPhysics.Clusters.GetObjectOffset(ClusterObjectID);

                                    if (force.HasValue && position.HasValue)
                                    {
                                        //this.RigidBody.ApplyImpulse(force.Value, position.Value);
                                        //RigidBody.Activate(true);
                                        rigidBody.ApplyPointImpulse(force.Value * rigidBody.Mass / Ragdoll.Mass, (Vector3)(position.Value - offset));
                                    }

                                    if (torque.HasValue)
                                    {
                                        //RigidBody.Activate(true);
                                        //RigidBody.ApplyTorque(MyEngineConstants.PHYSICS_STEP_SIZE_IN_SECONDS, torque.Value * 0.0001f);
                                        rigidBody.ApplyAngularImpulse(torque.Value * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * MyFakes.SIMULATION_SPEED * rigidBody.Mass / Ragdoll.Mass);
                                    }
                                }
                            }
                        }
                    }
                    break;
                case MyPhysicsForceType.APPLY_WORLD_FORCE:
                    {
                        if (RigidBody != null)
                        {
                            var offset = MyPhysics.Clusters.GetObjectOffset(ClusterObjectID);

                            if (force != null && !MyUtils.IsZero(force.Value))
                            {
                                if (position.HasValue)
                                {
                                    Vector3 point = position.Value - offset;
                                    RigidBody.ApplyForce(MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS, force.Value, point);
                                }
                                else
                                    RigidBody.ApplyForce(MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS, force.Value);
                            }                                
                        }
                        if (Ragdoll != null && Ragdoll.IsAddedToWorld && !Ragdoll.IsKeyframed)
                        {
                            foreach (var rigidBody in Ragdoll.RigidBodies)
                            {
                                if (rigidBody != null)
                                {
                                    var offset = MyPhysics.Clusters.GetObjectOffset(ClusterObjectID);

                                    if (force != null && !MyUtils.IsZero(force.Value))
                                    {
                                        if (position.HasValue)
                                        {
                                            Vector3 point = position.Value - offset;
                                            rigidBody.ApplyForce(MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS, force.Value * rigidBody.Mass / Ragdoll.Mass, point);
                                        }
                                        else
                                            rigidBody.ApplyForce(MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS, force.Value * rigidBody.Mass / Ragdoll.Mass);
                                    }
                                }
                            }
                        }
                    }

                    break;
                default:
                    {
                        Debug.Fail("Unhandled enum!");
                    }
                    break;
            }
        }
        //  Add billboard for one frame only. This billboard isn't particle (it doesn't survive this frame, doesn't have update/draw methods, etc).
        //  This billboard isn't facing the camera. It's always oriented in specified direction. May be used as thrusts, or inner light of reflector.
        //  It's used by other classes when they want to draw some billboard (e.g. rocket thrusts, reflector glare).
        public static void AddBillboardOriented(string material,
            Color color, Vector3D origin, Vector3 leftVector, Vector3 upVector, float radius, int priority = 0, bool colorize = false, int customViewProjection = -1)
        {
            Debug.Assert(material != null);

            if (!IsEnabled) return;

            origin.AssertIsValid();
            leftVector.AssertIsValid();
            upVector.AssertIsValid();
            radius.AssertIsValid();
            MyDebug.AssertDebug(radius > 0);


            MyBillboard billboard = m_billboardOncePool.Allocate();
            if (billboard == null)
                return;

            billboard.Priority = priority;
            billboard.CustomViewProjection = customViewProjection;

            MyQuadD quad;
            MyUtils.GetBillboardQuadOriented(out quad, ref origin, radius, ref leftVector, ref upVector);

            CreateBillboard(billboard, ref quad, material, ref color, ref origin, colorize);

            m_billboardsOnce.Add(billboard);
        }
Ejemplo n.º 27
0
        // Updates spectator position (spring connected to desired position)
        public override void UpdateAfterSimulation()
        {
            Sandbox.Game.Entities.IMyControllableEntity controlledEntity = MySession.Static.ControlledEntity as Sandbox.Game.Entities.IMyControllableEntity;
            if (controlledEntity == null)
            {
                return;
            }

            var headMatrix = controlledEntity.GetHeadMatrix(true);

            if (controlledEntity is MyCharacter)
            {
                var character = controlledEntity as MyCharacter;
                headMatrix = character.Get3rdBoneMatrix(true, true);
            }

            m_targetOrientation = (Matrix)headMatrix.GetOrientation();
            m_target            = headMatrix.Translation;


            //VRageRender.MyRenderProxy.DebugDrawAxis(headMatrix, 1, false);

            UpdateCurrentSpring();

            m_transformedLookAt = Vector3D.Transform(m_lookAt, m_targetOrientation);
            m_desiredPosition   = m_target + m_transformedLookAt;

            //m_position = m_desiredPosition;
            //m_velocity = Vector3.Zero;
            // Calculate spring force
            Vector3D stretch = m_position - m_desiredPosition;

            Vector3D force = -m_currentSpring.Stiffness * stretch - m_currentSpring.Damping * m_velocity;

            force.AssertIsValid();

            // Apply acceleration
            Vector3 acceleration = (Vector3)force / m_currentSpring.Mass;

            m_velocity += acceleration * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
            m_velocity.AssertIsValid();

            // Apply velocity
            if (!Sandbox.Game.Multiplayer.Sync.IsServer)
            {  //We are not able to interpolate camera correctly if position is updated through server
                m_position = m_desiredPosition;
            }
            else
            {
                m_position += m_velocity * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
            }
            m_position.AssertIsValid();

            // Limit backward distance from target
            double backward = Vector3D.Dot((Vector3D)m_targetOrientation.Backward, (m_target - m_position));

            if (backward > -BACKWARD_CUTOFF)
            {
                m_position += (Vector3D)m_targetOrientation.Backward * (backward + BACKWARD_CUTOFF);
            }

            // Roll spring
            Quaternion targetOrientation = Quaternion.CreateFromRotationMatrix(m_targetOrientation);

            // Computes angle difference between current and target orientation
            var angleDifference = (float)Math.Acos(MathHelper.Clamp(Quaternion.Dot(m_orientation, targetOrientation), -1, 1));

            // Normalize angle
            angleDifference = angleDifference > MathHelper.PiOver2 ? MathHelper.Pi - angleDifference : angleDifference;

            // Compute spring physics
            float angleForce = -AngleSpring.Stiffness * angleDifference - AngleSpring.Damping * m_angleVelocity;

            m_angleVelocity += angleForce / AngleSpring.Mass * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
            if (angleDifference > 0)
            {
                float factor = Math.Abs(m_angleVelocity * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS / angleDifference);
                if (angleDifference > MathHelper.PiOver4)
                {
                    factor = Math.Max(factor, 1.0f - MathHelper.PiOver4 / angleDifference);
                }
                factor              = MathHelper.Clamp(factor, 0, 1);
                m_orientation       = Quaternion.Slerp(m_orientation, targetOrientation, factor);
                m_orientationMatrix = Matrix.CreateFromQuaternion(m_orientation);
            }

            if ((m_position - m_desiredPosition).LengthSquared() > MAX_DISTANCE * MAX_DISTANCE)
            {
                RecalibrateCameraPosition();
            }

            if (m_saveSettings)
            {
                MySession.Static.SaveControlledEntityCameraSettings(false);
                m_saveSettings = false;
            }

            ++m_updateCount;
        }
Ejemplo n.º 28
0
        static void Gather()
        {
            m_batches.Clear();

            // counting sorted billboards
            m_sortedCount   = 0;
            m_unsortedCount = 0;
            m_windowCount   = 0;
            PreGatherList(MyRenderProxy.BillboardsRead);
            PreGatherList(m_billboardsOnce);

            if (BillboardCount == 0)
            {
                return;
            }

            ResizeStorage();

            int sortedIndex   = 0;
            int unsortedIndex = 0;

            GatherList(MyRenderProxy.BillboardsRead, ref sortedIndex, ref unsortedIndex);
            GatherList(m_billboardsOnce, ref sortedIndex, ref unsortedIndex);

            Array.Sort(m_sortedBuffer, 0, m_sortedCount);

            int   i             = 0;
            int   windowidx     = 0;
            var   N             = BillboardCountSafe;
            int   currentOffset = 0;
            TexId prevTexId     = TexId.NULL;
            TexId batchTexId    = TexId.NULL;
            MyTransparentMaterial prevMaterial = null;

            while (true)
            {
                if (i == N)
                {
                    AddBatch(N, currentOffset, prevTexId, prevMaterial);
                    break;
                }

                MyBillboard           billboard = m_sortedBuffer[i];
                MyTransparentMaterial material  = MyTransparentMaterials.GetMaterial(billboard.Material);
                if (material.UseAtlas)
                {
                    var atlasItem = m_atlas.FindElement(material.Texture);
                    batchTexId = atlasItem.TextureId;
                }
                else
                {
                    batchTexId = MyTextures.GetTexture(material.Texture, MyTextureEnum.GUI, true);
                }

                bool closeBatch = i > 0 && (batchTexId != prevTexId || i == m_sortedCount);
                if (closeBatch)
                {
                    AddBatch(i, currentOffset, prevTexId, prevMaterial);
                    currentOffset = i;
                }

                var billboardData     = new MyBillboardData();
                var billboardVertices = new MyBillboardVertexData();

                billboardData.CustomProjectionID = billboard.CustomViewProjection;
                billboardData.Color                     = billboard.Color;
                billboardData.Color.X                  *= billboard.ColorIntensity;
                billboardData.Color.Y                  *= billboard.ColorIntensity;
                billboardData.Color.Z                  *= billboard.ColorIntensity;
                billboardData.AlphaCutout               = billboard.AlphaCutout;
                billboardData.AlphaSaturation           = material.AlphaSaturation;
                billboardData.SoftParticleDistanceScale = billboard.SoftParticleDistanceScale * material.SoftParticleDistanceScale;

                billboardData.Reflective = billboard.Reflectivity;
                Vector3D pos0 = billboard.Position0;
                Vector3D pos1 = billboard.Position1;
                Vector3D pos2 = billboard.Position2;
                Vector3D pos3 = billboard.Position3;

                if (billboard.ParentID != -1)
                {
                    if (MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID) != null)
                    {
                        var matrix = MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID).WorldMatrix;

                        Vector3D.Transform(ref pos0, ref matrix, out pos0);
                        Vector3D.Transform(ref pos1, ref matrix, out pos1);
                        Vector3D.Transform(ref pos2, ref matrix, out pos2);
                        Vector3D.Transform(ref pos3, ref matrix, out pos3);
                    }
                }

                MyEnvironmentMatrices envMatrices = MyRender11.Environment;
                if (MyStereoRender.Enable)
                {
                    if (MyStereoRender.RenderRegion == MyStereoRegion.LEFT)
                    {
                        envMatrices = MyStereoRender.EnvMatricesLeftEye;
                    }
                    else if (MyStereoRender.RenderRegion == MyStereoRegion.RIGHT)
                    {
                        envMatrices = MyStereoRender.EnvMatricesRightEye;
                    }
                }

                if (billboard.CustomViewProjection != -1)
                {
                    var billboardViewProjection = MyRenderProxy.BillboardsViewProjectionRead[billboard.CustomViewProjection];

                    //pos0 -= envMatrices.CameraPosition;
                    //pos1 -= envMatrices.CameraPosition;
                    //pos2 -= envMatrices.CameraPosition;
                    //pos3 -= envMatrices.CameraPosition;
                }
                else
                {
                    pos0 -= envMatrices.CameraPosition;
                    pos1 -= envMatrices.CameraPosition;
                    pos2 -= envMatrices.CameraPosition;
                    pos3 -= envMatrices.CameraPosition;
                }

                var normal = Vector3.Cross(pos1 - pos0, pos2 - pos0);
                normal.Normalize();

                billboardData.Normal = normal;

                billboardVertices.V0.Position = pos0;
                billboardVertices.V1.Position = pos1;
                billboardVertices.V2.Position = pos2;
                billboardVertices.V3.Position = pos3;

                var uv0 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y);
                var uv1 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y);
                var uv2 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y);
                var uv3 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y);

                if (material.UseAtlas)
                {
                    var atlasItem = m_atlas.FindElement(material.Texture);

                    uv0 = uv0 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv1 = uv1 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv2 = uv2 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv3 = uv3 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                }

                billboardVertices.V0.Texcoord = new HalfVector2(uv0);
                billboardVertices.V1.Texcoord = new HalfVector2(uv1);
                billboardVertices.V2.Texcoord = new HalfVector2(uv2);
                billboardVertices.V3.Texcoord = new HalfVector2(uv3);

                pos0.AssertIsValid();
                pos1.AssertIsValid();
                pos2.AssertIsValid();
                pos3.AssertIsValid();


                MyTriangleBillboard triBillboard = billboard as MyTriangleBillboard;
                if (triBillboard != null)
                {
                    billboardVertices.V3.Position = pos2; // second triangle will die in rasterizer

                    billboardVertices.V0.Texcoord = new HalfVector2(triBillboard.UV0);
                    billboardVertices.V1.Texcoord = new HalfVector2(triBillboard.UV1);
                    billboardVertices.V2.Texcoord = new HalfVector2(triBillboard.UV2);

                    billboardData.Normal = triBillboard.Normal0;
                }

                m_arrayDataBillboards.Data[i]   = billboardData;
                m_arrayDataBillboards.Vertex[i] = billboardVertices;

                if (billboard.Window && MyScreenDecals.HasEntityDecals((uint)billboard.ParentID))
                {
                    m_arrayDataWindows.Data[windowidx]   = billboardData;
                    m_arrayDataWindows.Vertex[windowidx] = billboardVertices;
                    windowidx++;
                }

                prevTexId    = batchTexId;
                prevMaterial = material;
                i++;
            }
        }
Ejemplo n.º 29
0
 public void AssertIsValid()
 {
     Min.AssertIsValid();
     Max.AssertIsValid();
 }
Ejemplo n.º 30
0
        static bool GatherInternal(Func <MyBillboard, bool> handleWindow)
        {
            m_batches.Clear();

            // counting sorted billboards
            m_sortedCount   = 0;
            m_unsortedCount = 0;
            m_windowCount   = 0;
            PreGatherList(MyRenderProxy.BillboardsRead);
            PreGatherList(m_billboardsOnce);

            if (BillboardCount == 0)
            {
                return(false);
            }

            ResizeStorage();

            int sortedIndex   = 0;
            int unsortedIndex = 0;

            GatherList(MyRenderProxy.BillboardsRead, ref sortedIndex, ref unsortedIndex);
            GatherList(m_billboardsOnce, ref sortedIndex, ref unsortedIndex);

            Array.Sort(m_sortedBuffer, 0, m_sortedCount);

            int                   i             = 0;
            bool                  resetBindings = false;
            int                   windowidx     = 0;
            var                   N             = BillboardCountSafe;
            int                   currentOffset = 0;
            ISrvBindable          prevTex       = null;
            ISrvBindable          batchTex      = null;
            MyTransparentMaterial prevMaterial  = null;

            while (true)
            {
                if (i == N)
                {
                    AddBatch(N, currentOffset, prevTex, prevMaterial);
                    break;
                }

                MyBillboard           billboard = m_sortedBuffer[i];
                MyTransparentMaterial material  = MyTransparentMaterials.GetMaterial(billboard.Material);
                if (material.UseAtlas)
                {
                    var atlasItem = m_atlas.FindElement(material.Texture);
                    batchTex = atlasItem.Texture;
                }
                else
                {
                    MyFileTextureManager texManager = MyManagers.FileTextures;
                    switch (material.TextureType)
                    {
                    case MyTransparentMaterialTextureType.FileTexture:
                        batchTex = texManager.GetTexture(material.Texture, MyFileTextureEnum.GUI, true);
                        break;

                    case MyTransparentMaterialTextureType.RenderTarget:
                        batchTex      = MyRender11.DrawSpritesOffscreen(material.Name, material.TargetSize.X, material.TargetSize.Y);
                        resetBindings = true;
                        break;

                    default:
                        throw new Exception();
                    }
                }

                bool closeBatch = i > 0 && (batchTex != prevTex || i == m_sortedCount);
                if (closeBatch)
                {
                    AddBatch(i, currentOffset, prevTex, prevMaterial);
                    currentOffset = i;
                }

                var billboardData     = new MyBillboardData();
                var billboardVertices = new MyBillboardVertexData();

                billboardData.CustomProjectionID = billboard.CustomViewProjection;
                billboardData.Color                     = billboard.Color;
                billboardData.Color.X                  *= billboard.ColorIntensity;
                billboardData.Color.Y                  *= billboard.ColorIntensity;
                billboardData.Color.Z                  *= billboard.ColorIntensity;
                billboardData.AlphaCutout               = billboard.AlphaCutout;
                billboardData.AlphaSaturation           = material.AlphaSaturation;
                billboardData.SoftParticleDistanceScale = billboard.SoftParticleDistanceScale * material.SoftParticleDistanceScale;

                billboardData.Reflective = billboard.Reflectivity;
                Vector3D pos0 = billboard.Position0;
                Vector3D pos1 = billboard.Position1;
                Vector3D pos2 = billboard.Position2;
                Vector3D pos3 = billboard.Position3;

                if (billboard.ParentID != -1)
                {
                    if (MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID) != null)
                    {
                        var matrix = MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID).WorldMatrix;

                        Vector3D.Transform(ref pos0, ref matrix, out pos0);
                        Vector3D.Transform(ref pos1, ref matrix, out pos1);
                        Vector3D.Transform(ref pos2, ref matrix, out pos2);
                        Vector3D.Transform(ref pos3, ref matrix, out pos3);
                    }
                }

                MyEnvironmentMatrices envMatrices = MyRender11.Environment.Matrices;
                if (MyStereoRender.Enable)
                {
                    if (MyStereoRender.RenderRegion == MyStereoRegion.LEFT)
                    {
                        envMatrices = MyStereoRender.EnvMatricesLeftEye;
                    }
                    else if (MyStereoRender.RenderRegion == MyStereoRegion.RIGHT)
                    {
                        envMatrices = MyStereoRender.EnvMatricesRightEye;
                    }
                }

                if (billboard.CustomViewProjection != -1)
                {
                    var billboardViewProjection = MyRenderProxy.BillboardsViewProjectionRead[billboard.CustomViewProjection];

                    //pos0 -= envMatrices.CameraPosition;
                    //pos1 -= envMatrices.CameraPosition;
                    //pos2 -= envMatrices.CameraPosition;
                    //pos3 -= envMatrices.CameraPosition;
                }
                else
                {
                    pos0 -= envMatrices.CameraPosition;
                    pos1 -= envMatrices.CameraPosition;
                    pos2 -= envMatrices.CameraPosition;
                    pos3 -= envMatrices.CameraPosition;
                }

                var normal = Vector3.Cross(pos1 - pos0, pos2 - pos0);
                normal.Normalize();

                billboardData.Normal = normal;

                billboardVertices.V0.Position = pos0;
                billboardVertices.V1.Position = pos1;
                billboardVertices.V2.Position = pos2;
                billboardVertices.V3.Position = pos3;

                var uv0 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y);
                var uv1 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y);
                var uv2 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y);
                var uv3 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y);

                if (material.UseAtlas)
                {
                    var atlasItem = m_atlas.FindElement(material.Texture);

                    uv0 = uv0 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv1 = uv1 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv2 = uv2 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv3 = uv3 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                }

                billboardVertices.V0.Texcoord = new HalfVector2(uv0);
                billboardVertices.V1.Texcoord = new HalfVector2(uv1);
                billboardVertices.V2.Texcoord = new HalfVector2(uv2);
                billboardVertices.V3.Texcoord = new HalfVector2(uv3);

                pos0.AssertIsValid();
                pos1.AssertIsValid();
                pos2.AssertIsValid();
                pos3.AssertIsValid();


                MyTriangleBillboard triBillboard = billboard as MyTriangleBillboard;
                if (triBillboard != null)
                {
                    billboardVertices.V3.Position = pos2; // second triangle will die in rasterizer

                    billboardVertices.V0.Texcoord = new HalfVector2(triBillboard.UV0);
                    billboardVertices.V1.Texcoord = new HalfVector2(triBillboard.UV1);
                    billboardVertices.V2.Texcoord = new HalfVector2(triBillboard.UV2);

                    billboardData.Normal = triBillboard.Normal0;
                }

                m_arrayDataBillboards.Data[i]   = billboardData;
                m_arrayDataBillboards.Vertex[i] = billboardVertices;

                if (billboard.Window && handleWindow(billboard))
                {
                    m_sorteWindowIndices[windowidx] = i;
                    windowidx++;
                }

                prevTex      = batchTex;
                prevMaterial = material;
                i++;
            }

            // Sort windows data from closer to farest
            int windowCount = WindowCountSafe;

            Array.Sort(m_sorteWindowIndices, 0, windowCount, BillboardComparer);
            for (int it = 0; it < windowCount; it++)
            {
                m_arrayDataWindows.Data[it]   = m_arrayDataBillboards.Data[m_sorteWindowIndices[it]];
                m_arrayDataWindows.Vertex[it] = m_arrayDataBillboards.Vertex[m_sorteWindowIndices[it]];
            }

            return(resetBindings);
        }
        //  Add billboard for one frame only. This billboard isn't particle (it doesn't survive this frame, doesn't have update/draw methods, etc).
        //  It's used by other classes when they want to draw some billboard (e.g. rocket thrusts, reflector glare).
        public static void AddPointBillboard(string material,
            Color color, Vector3D origin, float radius, float angle, int priority = 0, bool colorize = false, bool near = false, bool lowres = false, int customViewProjection = -1,bool cullwithStencil = false)
        {
            Debug.Assert(material != null);

            if (!IsEnabled) return;

            origin.AssertIsValid();
            angle.AssertIsValid();

            MyQuadD quad;
            if (MyUtils.GetBillboardQuadAdvancedRotated(out quad, origin, radius, angle, MyRenderCamera.Position) != false)
            {
                VRageRender.MyBillboard billboard = m_billboardOncePool.Allocate();
                if (billboard == null)
                    return;

                billboard.CullWithStencil = cullwithStencil;
                billboard.Priority = priority;
                billboard.CustomViewProjection = customViewProjection;
                CreateBillboard(billboard, ref quad, material, ref color, ref origin, colorize, near, lowres);

                // TODO: OP! Nothing should add into BillboardsRead, especially when it may be used for more than one rendering frame
                m_billboardsOnce.Add(billboard);
            }
        }
 public void SetPosition(Vector3D position)
 {
     if (Vector3D.DistanceSquared(Position, position) > 0.0001)
     {
         position.AssertIsValid();
         Position = position;
         m_spotParamsDirty = true;
         UpdatePositionWithOffset();
         m_pointBoundingSphere.Center = PositionWithOffset;
     }
 }
        //  Add billboard for one frame only. This billboard isn't particle (it doesn't survive this frame, doesn't have update/draw methods, etc).
        //  It's used by other classes when they want to draw some billboard (e.g. rocket thrusts, reflector glare).
        public static void AddLineBillboard(string material,
            Color color, Vector3D origin, Vector3 directionNormalized, float length, float thickness, int priority = 0, bool near = false, int customViewProjection = -1)
        {
            Debug.Assert(material != null);

            if (!IsEnabled) return;

            origin.AssertIsValid();
            length.AssertIsValid();
            MyDebug.AssertDebug(length > 0);
            MyDebug.AssertDebug(thickness > 0);

            VRageRender.MyBillboard billboard = m_billboardOncePool.Allocate();
            if (billboard == null)
                return;

            billboard.Priority = priority;
            billboard.CustomViewProjection = customViewProjection;

            MyPolyLineD polyLine;
            polyLine.LineDirectionNormalized = directionNormalized;
            polyLine.Point0 = origin;
            polyLine.Point1 = origin + directionNormalized * length;
            polyLine.Thickness = thickness;

            MyQuadD quad;
            MyUtilsRender9.GetPolyLineQuad(out quad, ref polyLine);

            CreateBillboard(billboard, ref quad, material, ref color, ref origin, false, near);

            m_billboardsOnce.Add(billboard);
        }
Ejemplo n.º 34
0
        static void Gather()
        {
            // counting sorted billboards
            m_batches.Clear();
            m_sortedNum = 0;

            PreGatherList(MyRenderProxy.BillboardsRead);
            PreGatherList(m_billboardsOnce);

            m_sortedBillboardsNum = m_sortedNum;

            m_unsorted = 0;
            m_sorted   = 0;

            GatherList(MyRenderProxy.BillboardsRead);
            GatherList(m_billboardsOnce);

            Array.Sort(m_sortBuffer, 0, m_sortedNum);
            //Array.Reverse(m_sortBuffer, 0, m_sortedNum);
            //Array.Sort(m_sortBuffer, m_sortedNum, m_unsorted);

            var N = m_sorted + m_unsorted;

            var batch = new MyBillboardBatch();
            //MyAssetTexture prevTexture = null;
            var prevTexId     = TexId.NULL;
            int currentOffset = 0;

            if (N > 0)
            {
                var material = MyTransparentMaterials.GetMaterial(m_sortBuffer[0].Material);

                if (material.UseAtlas)
                {
                    var item = m_atlasedTextures[material.Texture];
                    prevTexId = item.TextureId;
                }
                else
                {
                    PreloadTexture(material.Texture);
                    //prevTexture = MyTextureManager.GetTextureFast(material.Texture);
                    prevTexId = MyTextures.GetTexture(material.Texture, MyTextureEnum.GUI, true);
                }
            }

            TexId batchTexId = TexId.NULL;
            MyTransparentMaterial prevMaterial = null;

            for (int i = 0; i < N; i++)
            {
                var billboard = m_sortBuffer[i];
                var material  = MyTransparentMaterials.GetMaterial(billboard.Material);

                var billboardData = new MyBillboardData();

                billboardData.CustomProjectionID = billboard.CustomViewProjection;
                billboardData.Color = billboard.Color;
                if (material.UseAtlas)
                {
                    var atlasItem = m_atlasedTextures[material.Texture];
                    //billboardData.UvModifiers = new HalfVector4(atlasItem.UvOffsetScale);
                    batchTexId = atlasItem.TextureId;
                }
                else
                {
                    batchTexId = MyTextures.GetTexture(material.Texture, MyTextureEnum.GUI, true);
                }

                billboardData.Reflective = billboard.Reflectivity;
                Vector3D pos0 = billboard.Position0;
                Vector3D pos1 = billboard.Position1;
                Vector3D pos2 = billboard.Position2;
                Vector3D pos3 = billboard.Position3;

                if (billboard.ParentID != -1)
                {
                    if (MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID) != null)
                    {
                        var matrix = MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID).WorldMatrix;

                        Vector3D.Transform(ref pos0, ref matrix, out pos0);
                        Vector3D.Transform(ref pos1, ref matrix, out pos1);
                        Vector3D.Transform(ref pos2, ref matrix, out pos2);
                        Vector3D.Transform(ref pos3, ref matrix, out pos3);
                    }
                }

                if (billboard.CustomViewProjection != -1)
                {
                    var billboardViewProjection = MyRenderProxy.BillboardsViewProjectionRead[billboard.CustomViewProjection];

                    //pos0 -= MyEnvironment.CameraPosition;
                    //pos1 -= MyEnvironment.CameraPosition;
                    //pos2 -= MyEnvironment.CameraPosition;
                    //pos3 -= MyEnvironment.CameraPosition;
                }
                else
                {
                    pos0 -= MyEnvironment.CameraPosition;
                    pos1 -= MyEnvironment.CameraPosition;
                    pos2 -= MyEnvironment.CameraPosition;
                    pos3 -= MyEnvironment.CameraPosition;
                }

                var normal = Vector3.Cross(pos1 - pos0, pos2 - pos0);
                normal.Normalize();

                billboardData.Normal = normal;

                m_vertexData[i * 4 + 0].Position = pos0;
                m_vertexData[i * 4 + 1].Position = pos1;
                m_vertexData[i * 4 + 2].Position = pos2;
                m_vertexData[i * 4 + 3].Position = pos3;

                var uv0 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y);
                var uv1 = new Vector2(material.UVOffset.X + material.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y);
                var uv2 = new Vector2(material.UVOffset.X + material.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + material.UVSize.Y + billboard.UVOffset.Y);
                var uv3 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + material.UVSize.Y + billboard.UVOffset.Y);

                if (material.UseAtlas)
                {
                    var atlasItem = m_atlasedTextures[material.Texture];

                    uv0 = uv0 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv1 = uv1 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv2 = uv2 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                    uv3 = uv3 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y);
                }

                m_vertexData[i * 4 + 0].Texcoord = new HalfVector2(uv0);
                m_vertexData[i * 4 + 1].Texcoord = new HalfVector2(uv1);
                m_vertexData[i * 4 + 2].Texcoord = new HalfVector2(uv2);
                m_vertexData[i * 4 + 3].Texcoord = new HalfVector2(uv3);

                pos0.AssertIsValid();
                pos1.AssertIsValid();
                pos2.AssertIsValid();
                pos3.AssertIsValid();


                MyTriangleBillboard triBillboard = billboard as MyTriangleBillboard;
                if (triBillboard != null)
                {
                    m_vertexData[i * 4 + 3].Position = pos2; // second triangle will die in rasterizer

                    m_vertexData[i * 4 + 0].Texcoord = new HalfVector2(triBillboard.UV0);
                    m_vertexData[i * 4 + 1].Texcoord = new HalfVector2(triBillboard.UV1);
                    m_vertexData[i * 4 + 2].Texcoord = new HalfVector2(triBillboard.UV2);

                    billboardData.Normal = triBillboard.Normal0; // pew pew pew :O
                }

                m_billboardData[i] = billboardData;

                bool closeBatch = (batchTexId != prevTexId) || ((i == m_sortedNum) && (i > 0));

                if (closeBatch)
                {
                    batch = new MyBillboardBatch();

                    batch.Offset  = currentOffset;
                    batch.Num     = i - currentOffset;
                    batch.Texture = prevTexId != TexId.NULL ? MyTextures.Views[prevTexId.Index] : null;

                    batch.Lit = prevMaterial.CanBeAffectedByOtherLights;

                    m_batches.Add(batch);
                    currentOffset = i;
                }

                prevTexId    = batchTexId;
                prevMaterial = material;
            }

            if (N > 0)
            {
                batch         = new MyBillboardBatch();
                batch.Offset  = currentOffset;
                batch.Num     = N - currentOffset;
                batch.Texture = prevTexId != TexId.NULL ? MyTextures.GetView(prevTexId) : null;

                batch.Lit = prevMaterial.CanBeAffectedByOtherLights;

                m_batches.Add(batch);
            }
        }