Beispiel #1
0
        private void ProcessDirtyCells()
        {
            foreach (var cell in m_dirtyCellsToAdd)
            {
                m_dirtyCells.Add(cell);
            }
            m_dirtyCellsToAdd.Clear();

            if (m_dirtyCells.Count == 0)
            {
                return;
            }
            ProfilerShort.Begin("Find false possitive dirty cells");
            foreach (var cell in m_dirtyCells)
            {
                foreach (var tracker in m_trackedEntities.Values)
                {
                    if (tracker.BoundingVolume.Contains(cell.BoundingVolume) != ContainmentType.Disjoint)
                    {
                        m_dirtyCellsToRemove.Add(cell);
                        break;
                    }
                }
            }

            ProfilerShort.BeginNextBlock("Remove false possitive dirty cells");
            foreach (var cell in m_dirtyCellsToRemove)
            {
                m_dirtyCells.Remove(cell);
            }
            m_dirtyCellsToRemove.Clear();

            ProfilerShort.BeginNextBlock("Remove stuff");
            foreach (var cell in m_dirtyCells)
            {
                cell.GetAll(m_tempObjectSeedList);

                foreach (var objectSeed in m_tempObjectSeedList)
                {
                    switch (objectSeed.Type)
                    {
                    case MyObjectSeedType.Asteroid:
                    case MyObjectSeedType.AsteroidCluster:
                        var bbox = objectSeed.BoundingVolume;
                        MyGamePruningStructure.GetAllVoxelMapsInBox(ref bbox, m_tmpVoxelMapsList);

                        String storageName = string.Format("Asteroid_{0}_{1}_{2}_{3}_{4}", cell.CellId.X, cell.CellId.Y, cell.CellId.Z, objectSeed.Index, objectSeed.Seed);

                        foreach (var voxelMap in m_tmpVoxelMapsList)
                        {
                            if (voxelMap.StorageName == storageName)
                            {
                                if (!voxelMap.Save)     // for now
                                {
                                    m_asteroidCount--;
                                    voxelMap.Close();
                                }
                                break;
                            }
                        }
                        m_asteroidSeedCount--;
                        m_tmpVoxelMapsList.Clear();
                        break;

                    case MyObjectSeedType.EncounterAlone:
                    case MyObjectSeedType.EncounterSingle:
                    case MyObjectSeedType.EncounterMulti:
                        if (MyEncounterGenerator.RemoveEncounter(objectSeed.BoundingVolume, objectSeed.Seed))
                        {
                            m_encounterCount--;
                        }
                        m_encounterSeedCount--;
                        break;

                    default:
                        throw new InvalidBranchException();
                        break;
                    }
                }
            }
            m_tempObjectSeedList.Clear();

            ProfilerShort.BeginNextBlock("Remove dirty cells");
            foreach (var cell in m_dirtyCells)
            {
                m_cells.Remove(cell.CellId);
                m_cellsTree.RemoveProxy(cell.proxyId);
            }
            m_dirtyCells.Clear();
            ProfilerShort.End();
        }
Beispiel #2
0
        public override void Init(MyObjectBuilder_EntityBase builder, Sandbox.Engine.Voxels.IMyStorage storage)
        {
            ProfilerShort.Begin("MyPlanet::Init()");
            if (MyFakes.ENABLE_PLANETS == false)
            {
                throw new PlanetsNotEnabledException();
            }

            ProfilerShort.Begin("MyVoxelBase Init");

            SyncFlag = true;

            base.Init(builder);
            base.Init(null, null, null, null, null);

            ProfilerShort.BeginNextBlock("Load Saved Data");

            var ob = (MyObjectBuilder_Planet)builder;

            if (ob == null)
            {
                return;
            }

            if (ob.MutableStorage)
            {
                StorageName = ob.StorageName;
            }
            else
            {
                StorageName = string.Format("{0}", ob.StorageName);
            }
            if (ob.SavedEnviromentSectors != null)
            {
                foreach (var sect in ob.SavedEnviromentSectors)
                {
                    MyPlanetSectorId id;
                    id.Position      = sect.IdPos;
                    id.Direction     = sect.IdDir;
                    SavedSectors[id] = new List <int>(sect.RemovedItems);
                    SavedSectors[id].Sort();
                }
            }

            m_planetInitValues.StorageName           = StorageName;
            m_planetInitValues.PositionMinCorner     = ob.PositionAndOrientation.Value.Position;
            m_planetInitValues.HasAtmosphere         = ob.HasAtmosphere;
            m_planetInitValues.AtmosphereRadius      = ob.AtmosphereRadius;
            m_planetInitValues.AtmosphereWavelengths = ob.AtmosphereWavelengths;
            m_planetInitValues.GravityFalloff        = ob.GravityFalloff;
            m_planetInitValues.MarkAreaEmpty         = ob.MarkAreaEmpty;
            m_planetInitValues.SurfaceGravity        = ob.SurfaceGravity;
            m_planetInitValues.AddGps = ob.ShowGPS;
            m_planetInitValues.SpherizeWithDistance = ob.SpherizeWithDistance;
            m_planetInitValues.Generator            = ob.PlanetGenerator == "" ? null : MyDefinitionManager.Static.GetDefinition <MyPlanetGeneratorDefinition>(MyStringHash.GetOrCompute(ob.PlanetGenerator));
            if (m_planetInitValues.Generator == null)
            {
                string message = string.Format("No definition found for planet generator {0}.", ob.PlanetGenerator);
                MyLog.Default.WriteLine(message);
                throw new Exception(message);
            }

            m_planetInitValues.AtmosphereSettings = m_planetInitValues.Generator.AtmosphereSettings.HasValue ? m_planetInitValues.Generator.AtmosphereSettings.Value : MyAtmosphereSettings.Defaults();
            m_planetInitValues.UserCreated        = false;

            ProfilerShort.BeginNextBlock("Load Storage");
            if (storage != null)
            {
                m_planetInitValues.Storage = storage;
            }
            else
            {
                m_planetInitValues.Storage = MyStorageBase.Load(ob.StorageName);
            }

            ProfilerShort.BeginNextBlock("Init Internal");
            Init(m_planetInitValues);
            ProfilerShort.End();

            ProfilerShort.End();
        }
Beispiel #3
0
        public void GetPlanetMaps(string folder, MyModContext context, MyPlanetMaps mapsToUse, out MyCubemap[] maps)
        {
            if (m_planetMaps.ContainsKey(folder))
            {
                maps = m_planetMaps[folder];
                return;
            }

            maps = new MyCubemap[4];

            MyCubemapData <byte>[] tmpMaps = new MyCubemapData <byte> [4 * 6];

            byte[][] streams = new byte[4][];

            string fullPath;

            ProfilerShort.Begin("MyHeightmapLoadingSystem::GetPlanetMaps()");

            ProfilerShort.Begin("Load _mat");
            // Round one: material, ore, biome
            if (mapsToUse.Material || mapsToUse.Biome || mapsToUse.Ores)
            {
                for (int i = 0; i < 6; ++i)
                {
                    string name = Path.Combine(folder, MyCubemapHelpers.GetNameForFace(i));

                    using (var texture = TryGetPlanetTexture(name, context, "_mat", out fullPath))
                    {
                        if (texture == null)
                        {
                            ClearMatValues(tmpMaps);
                            break;
                        }

                        PixelBuffer buffer = texture.GetPixelBuffer(0, 0, 0);

                        if (buffer.Format != Format.B8G8R8A8_UNorm &&
                            buffer.Format != Format.R8G8B8A8_UNorm)
                        {
                            MyDebug.FailRelease("While loading maps from {1}: Unsupported planet map format: {0}.", buffer.Format, fullPath);
                            break;
                        }

                        if (buffer.Width != buffer.Height)
                        {
                            MyDebug.FailRelease("While loading maps from {0}: Width and height must be the same.", fullPath);
                            break;
                        }

                        if (mapsToUse.Material)
                        {
                            tmpMaps[i * 4] = new MyCubemapData <byte>(buffer.Width);
                            streams[0]     = tmpMaps[i * 4].Data;
                        }

                        if (mapsToUse.Biome)
                        {
                            tmpMaps[i * 4 + 1] = new MyCubemapData <byte>(buffer.Width);
                            streams[1]         = tmpMaps[i * 4 + 1].Data;
                        }

                        if (mapsToUse.Ores)
                        {
                            tmpMaps[i * 4 + 2] = new MyCubemapData <byte>(buffer.Width);
                            streams[2]         = tmpMaps[i * 4 + 2].Data;
                        }

                        // Invert channels for BGRA
                        if (buffer.Format == Format.B8G8R8A8_UNorm)
                        {
                            var tmp = streams[2];
                            streams[2] = streams[0];
                            streams[0] = tmp;
                        }

                        ReadChannelsFromImage(streams, buffer);
                    }
                }
            }

            ProfilerShort.BeginNextBlock("Load _add");
            // round two: add map
            if (mapsToUse.Occlusion)
            {
                for (int i = 0; i < 6; ++i)
                {
                    string name = Path.Combine(folder, MyCubemapHelpers.GetNameForFace(i));

                    using (var texture = TryGetPlanetTexture(name, context, "_add", out fullPath))
                    {
                        if (texture == null)
                        {
                            ClearAddValues(tmpMaps);
                            break;
                        }

                        PixelBuffer buffer = texture.GetPixelBuffer(0, 0, 0);

                        if (buffer.Format != Format.B8G8R8A8_UNorm &&
                            buffer.Format != Format.R8G8B8A8_UNorm)
                        {
                            MyDebug.FailRelease("While loading maps from {1}: Unsupported planet map format: {0}.", buffer.Format, fullPath);
                            break;
                        }

                        if (buffer.Width != buffer.Height)
                        {
                            MyDebug.FailRelease("While loading maps from {0}: Width and height must be the same.", fullPath);
                            break;
                        }

                        if (mapsToUse.Occlusion)
                        {
                            tmpMaps[i * 4 + 3] = new MyCubemapData <byte>(buffer.Width);
                            streams[0]         = tmpMaps[i * 4 + 3].Data;
                        }

                        streams[1] = streams[2] = null;

                        // Invert channels for BGRA
                        if (buffer.Format == Format.B8G8R8A8_UNorm)
                        {
                            var tmp = streams[2];
                            streams[2] = streams[0];
                            streams[0] = tmp;
                        }

                        ReadChannelsFromImage(streams, buffer);
                    }
                }
            }

            ProfilerShort.BeginNextBlock("Finish");

            for (int i = 0; i < 4; ++i)
            {
                if (tmpMaps[i] != null)
                {
                    var cmaps = new MyCubemapData <byte> [6];
                    for (int j = 0; j < 6; j++)
                    {
                        cmaps[j] = tmpMaps[i + j * 4];
                    }
                    maps[i] = new MyCubemap(cmaps);
                }
            }

            m_planetMaps[folder] = maps;

            ProfilerShort.End();
            ProfilerShort.End();
        }
        public static bool PlayContactSound(long entityId, MyStringId strID, Vector3D position, MyStringHash materialA, MyStringHash materialB, float volume = 1, Func <bool> canHear = null, Func <bool> shouldPlay2D = null, MyEntity surfaceEntity = null, float separatingVelocity = 0f)
        {
            ProfilerShort.Begin("GetCue");

            MyEntity firstEntity = null;

            MyEntities.TryGetEntityById(entityId, out firstEntity);
            if (firstEntity == null)
            {
                ProfilerShort.End();
                return(false);
            }

            MySoundPair cue = (firstEntity.Physics != null && firstEntity.Physics.IsStatic == false) ?
                              MyMaterialPropertiesHelper.Static.GetCollisionCueWithMass(strID, materialA, materialB, ref volume, firstEntity.Physics.Mass, separatingVelocity) :
                              MyMaterialPropertiesHelper.Static.GetCollisionCue(strID, materialA, materialB);

            if (cue == null || cue.SoundId == null || MyAudio.Static == null)
            {
                return(false);
            }

            if (separatingVelocity > 0f && separatingVelocity < 0.5f)
            {
                return(false);
            }

            if (!cue.SoundId.IsNull && MyAudio.Static.SourceIsCloseEnoughToPlaySound(position, cue.SoundId))
            {
                MyEntity3DSoundEmitter emitter = MyAudioComponent.TryGetSoundEmitter();
                if (emitter == null)
                {
                    ProfilerShort.End();
                    return(false);
                }
                ProfilerShort.BeginNextBlock("Emitter lambdas");
                MyAudioComponent.ContactSoundsPool.TryAdd(entityId, 0);
                emitter.StoppedPlaying += (e) =>
                {
                    byte val;
                    MyAudioComponent.ContactSoundsPool.TryRemove(entityId, out val);
                };
                if (MySession.Static.Settings.RealisticSound && MyFakes.ENABLE_NEW_SOUNDS)
                {
                    Action <MyEntity3DSoundEmitter> remove = null;
                    remove = (e) =>
                    {
                        emitter.EmitterMethods[MyEntity3DSoundEmitter.MethodsEnum.CanHear].Remove(canHear);
                        emitter.EmitterMethods[MyEntity3DSoundEmitter.MethodsEnum.ShouldPlay2D].Remove(shouldPlay2D);
                        emitter.StoppedPlaying -= remove;
                    };
                    emitter.EmitterMethods[MyEntity3DSoundEmitter.MethodsEnum.CanHear].Add(canHear);
                    emitter.EmitterMethods[MyEntity3DSoundEmitter.MethodsEnum.ShouldPlay2D].Add(shouldPlay2D);
                    emitter.StoppedPlaying += remove;
                }
                ProfilerShort.BeginNextBlock("PlaySound");
                bool inSpace = MySession.Static.Settings.RealisticSound && MyFakes.ENABLE_NEW_SOUNDS && MySession.Static.LocalCharacter != null && MySession.Static.LocalCharacter.AtmosphereDetectorComp.InVoid;
                if (surfaceEntity != null && !inSpace)
                {
                    emitter.Entity = surfaceEntity;
                }
                else
                {
                    emitter.Entity = firstEntity;
                }
                emitter.SetPosition(position);

                //GR: Changed stopPrevious argument to false due to bugs with explosion sound. May revision to the future
                emitter.PlaySound(cue, false);

                if (emitter.Sound != null)
                {
                    emitter.Sound.SetVolume(emitter.Sound.Volume * volume);
                }

                if (inSpace && surfaceEntity != null)
                {
                    MyEntity3DSoundEmitter emitter2 = MyAudioComponent.TryGetSoundEmitter();
                    if (emitter2 == null)
                    {
                        ProfilerShort.End();
                        return(false);
                    }
                    ProfilerShort.BeginNextBlock("Emitter 2 lambdas");
                    Action <MyEntity3DSoundEmitter> remove = null;
                    remove = (e) =>
                    {
                        emitter2.EmitterMethods[MyEntity3DSoundEmitter.MethodsEnum.CanHear].Remove(canHear);
                        emitter2.EmitterMethods[MyEntity3DSoundEmitter.MethodsEnum.ShouldPlay2D].Remove(shouldPlay2D);
                        emitter2.StoppedPlaying -= remove;
                    };
                    emitter2.EmitterMethods[MyEntity3DSoundEmitter.MethodsEnum.CanHear].Add(canHear);
                    emitter2.EmitterMethods[MyEntity3DSoundEmitter.MethodsEnum.ShouldPlay2D].Add(shouldPlay2D);
                    emitter2.StoppedPlaying += remove;

                    ProfilerShort.BeginNextBlock("PlaySound");
                    emitter2.Entity = surfaceEntity;
                    emitter2.SetPosition(position);

                    emitter2.PlaySound(cue, false);

                    if (emitter2.Sound != null)
                    {
                        emitter2.Sound.SetVolume(emitter2.Sound.Volume * volume);
                    }
                }

                ProfilerShort.End();
                return(true);
            }

            ProfilerShort.End();
            return(false);
        }
Beispiel #5
0
        public static void MakeCrater(MyVoxelBase voxelMap, BoundingSphereD sphere, Vector3 direction, MyVoxelMaterialDefinition material)
        {
            ProfilerShort.Begin("MakeCrater");

            Vector3 normal = Vector3.Normalize(sphere.Center - voxelMap.RootVoxel.WorldMatrix.Translation);

            Vector3I minCorner, maxCorner;

            {
                Vector3D sphereMin = sphere.Center - (sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES) * 1.3f;
                Vector3D sphereMax = sphere.Center + (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES) * 1.3f;
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMin, out minCorner);
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMax, out maxCorner);
            }

            voxelMap.Storage.ClampVoxelCoord(ref minCorner);
            voxelMap.Storage.ClampVoxelCoord(ref maxCorner);

            Vector3I worldMinCorner = minCorner + voxelMap.StorageMin;
            Vector3I worldMaxCorner = maxCorner + voxelMap.StorageMin;

            //  We are tracking which voxels were changed, so we can invalidate only needed cells in the cache
            bool changed = false;

            ProfilerShort.Begin("Reading cache");
            m_cache.Resize(minCorner, maxCorner);

            voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref worldMinCorner, ref worldMaxCorner);

            ProfilerShort.End();

            ProfilerShort.Begin("Changing cache");
            int      removedVoxelContent = 0;
            Vector3I tempVoxelCoord;
            Vector3I cachePos = (maxCorner - minCorner) / 2;

            byte oldMaterial = m_cache.Material(ref cachePos);

            float digRatio = 1 - Vector3.Dot(normal, direction);

            Vector3 newCenter = sphere.Center - normal * (float)sphere.Radius * 1.1f;//0.9f;
            float   sphRadA   = (float)(sphere.Radius * 1.5f);
            float   sphRadSqA = (float)(sphRadA * sphRadA);
            float   voxelSizeHalfTransformedPosA = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadA + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF);
            float   voxelSizeHalfTransformedNegA = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (-2 * sphRadA + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF);

            Vector3 newDelCenter = newCenter + normal * (float)sphere.Radius * (0.7f + digRatio) + direction * (float)sphere.Radius * 0.65f;
            float   sphRadD      = (float)(sphere.Radius);
            float   sphRadSqD    = (float)(sphRadD * sphRadD);
            float   voxelSizeHalfTransformedPosD = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadD + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF);
            float   voxelSizeHalfTransformedNegD = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (-2 * sphRadD + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF);

            Vector3 newSetCenter = newCenter + normal * (float)sphere.Radius * (digRatio) + direction * (float)sphere.Radius * 0.3f;
            float   sphRadS      = (float)(sphere.Radius * 0.1f);
            float   sphRadSqS    = (float)(sphRadS * sphRadS);
            float   voxelSizeHalfTransformedPosS = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadS + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF);

            for (tempVoxelCoord.Z = minCorner.Z, cachePos.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, ++cachePos.Z)
            {
                for (tempVoxelCoord.Y = minCorner.Y, cachePos.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, ++cachePos.Y)
                {
                    for (tempVoxelCoord.X = minCorner.X, cachePos.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, ++cachePos.X)
                    {
                        Vector3D voxelPosition;
                        MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref tempVoxelCoord, out voxelPosition);

                        byte originalContent = m_cache.Content(ref cachePos);

                        //Add sphere
                        if (originalContent != MyVoxelConstants.VOXEL_CONTENT_FULL)
                        {
                            float addDist = (float)(voxelPosition - newCenter).LengthSquared();
                            float addDiff = (float)(addDist - sphRadSqA);

                            byte newContent;
                            if (addDiff > voxelSizeHalfTransformedPosA)
                            {
                                newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                            }
                            else if (addDiff < voxelSizeHalfTransformedNegA)
                            {
                                newContent = MyVoxelConstants.VOXEL_CONTENT_FULL;
                            }
                            else
                            {
                                float value = (float)Math.Sqrt(addDist + sphRadSqA - 2 * sphRadA * Math.Sqrt(addDist));
                                if (addDiff < 0)
                                {
                                    value = -value;
                                }
                                //  This formula will work even if diff is positive or negative
                                newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - value / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                            }

                            if (newContent > originalContent)
                            {
                                if (material != null)
                                {
                                    m_cache.Material(ref cachePos, oldMaterial);
                                }

                                changed = true;
                                m_cache.Content(ref cachePos, newContent);
                            }
                        }

                        //Delete sphere
                        float delDist = (float)(voxelPosition - newDelCenter).LengthSquared();
                        float delDiff = (float)(delDist - sphRadSqD);

                        byte contentToRemove;
                        if (delDiff > voxelSizeHalfTransformedPosD)
                        {
                            contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                        }
                        else if (delDiff < voxelSizeHalfTransformedNegD)
                        {
                            contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL;
                        }
                        else
                        {
                            float value = (float)Math.Sqrt(delDist + sphRadSqD - 2 * sphRadD * Math.Sqrt(delDist));
                            if (delDiff < 0)
                            {
                                value = -value;
                            }
                            //  This formula will work even if diff is positive or negative
                            contentToRemove = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - value / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                        }

                        originalContent = m_cache.Content(ref cachePos);

                        if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY && contentToRemove > MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                        {
                            changed = true;

                            int newVal = originalContent - contentToRemove;
                            if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                            {
                                newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                            }
                            m_cache.Content(ref cachePos, (byte)newVal);

                            removedVoxelContent += originalContent - newVal;
                        }

                        //Set material

                        float setDist = (float)(voxelPosition - newSetCenter).LengthSquared();
                        float setDiff = (float)(setDist - sphRadSqS);

                        if (setDiff <= MyVoxelConstants.VOXEL_SIZE_IN_METRES * 1.5f)  // could be VOXEL_SIZE_IN_METRES_HALF, but we want to set material in empty cells correctly
                        {
                            MyVoxelMaterialDefinition originalMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref cachePos));

                            // Change the material:
                            // - always on boundaries between material and nothing
                            // - smoothly on inner boundaries
                            MyVoxelMaterialDefinition newMaterial = material;
                            if (setDiff > 0)
                            {
                                byte content = m_cache.Content(ref cachePos);
                                if (content == MyVoxelConstants.VOXEL_CONTENT_FULL)
                                {
                                    newMaterial = originalMaterial;
                                }
                                if (setDiff >= voxelSizeHalfTransformedPosS && content != MyVoxelConstants.VOXEL_CONTENT_EMPTY)  // set material behind boundary only for empty voxels
                                {
                                    newMaterial = originalMaterial;
                                }
                            }

                            if (originalMaterial == newMaterial)
                            {
                                continue;
                            }

                            m_cache.Material(ref cachePos, newMaterial.Index);
                            changed = true;
                        }

                        float dist = (float)(voxelPosition - newCenter).LengthSquared();
                        float diff = (float)(dist - sphRadSqA);

                        if (diff <= 0f)
                        {
                            originalContent = m_cache.Content(ref cachePos);
                            if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                            {
                                bool wrinkled = m_cache.WrinkleVoxelContent(ref cachePos, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_ADD, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_REMOVE);
                                if (wrinkled)
                                {
                                    changed = true;
                                }
                            }
                        }
                    }
                }
            }
            ProfilerShort.End();

            if (changed)
            {
                ProfilerShort.Begin("RemoveSmallVoxelsUsingChachedVoxels");
                RemoveSmallVoxelsUsingChachedVoxels();
                ProfilerShort.BeginNextBlock("Writing cache");
                minCorner += voxelMap.StorageMin;
                maxCorner += voxelMap.StorageMin;
                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref minCorner, ref maxCorner);
                MyShapeSphere sphereShape = new MyShapeSphere();
                sphereShape.Center = sphere.Center;
                sphereShape.Radius = (float)(sphere.Radius * 1.5);
                OnVoxelChanged(OperationType.Cut, voxelMap, sphereShape);
                ProfilerShort.End();
            }

            ProfilerShort.End();
        }
        void UpdateLodState()
        {
            ProfilerShort.Begin("MyInstancingComponent::UpdateLodState");
            foreach (var pair in m_activeTransitions)
            {
                var lodTransitionData = pair.Value;
                ProfilerShort.Begin("SetAlphaForInstance");
                float delta = lodTransitionData.Delta;
                if (MyLodUtils.LOD_TRANSITION_DISTANCE)
                {
                    float distance = (float)(MyRender11.Environment.CameraPosition - m_lastCameraPosition).Length();
                    if (distance < 0.01f)
                    {
                        distance = m_lastCameraSpeed;
                    }
                    delta  = distance * 0.01f;// MyLodUtils.GetTransitionDelta(distance * 0.1f, pair.Value.Time, m_instances[pair.Key].CurrentLod);
                    delta  = Math.Max(distance * 0.01f, 0.025f);
                    delta *= Math.Sign(lodTransitionData.Delta);
                    m_lastCameraPosition = MyRender11.Environment.CameraPosition;
                    m_lastCameraSpeed    = distance;
                }
                lodTransitionData.Time = lodTransitionData.Time + delta;
                SetAlphaForInstance(pair.Key.Id, pair.Key.InstanceIndex, lodTransitionData.Time);

                ProfilerShort.BeginNextBlock("Transitions");
                if (lodTransitionData.IsProxyToInstance)
                {
                    if (lodTransitionData.Time >= 1.0f)
                    {
                        ProfilerShort.Begin("PositiveTransition");

                        var instance = m_instances[pair.Key];

                        RemoveAndReleaseInstance(instance);
                        m_instances.Remove(pair.Key);

                        m_completedTransitions.Add(pair.Key);

                        ProfilerShort.End();
                        ProfilerShort.End();
                        continue;
                    }
                    else if (lodTransitionData.Time <= -1.0f)
                    {
                        ProfilerShort.Begin("NegativeTransition");
                        MyInstancing.Instancings.Data[pair.Key.Id.Index].SetVisibility(pair.Key.InstanceIndex, false);
                        m_dirtyInstances.Add(pair.Key.Id);

                        m_completedTransitions.Add(pair.Key);
                        lodTransitionData.Time = 0;
                        ProfilerShort.End();
                    }
                }
                else
                {
                    if (Math.Abs(lodTransitionData.Time) >= 1.0f)
                    {
                        var instance = m_instances[pair.Key];
                        instance.CurrentLod    += Math.Sign(lodTransitionData.Delta);
                        lodTransitionData.Delta = -lodTransitionData.Delta;

                        m_completedTransitions.Add(pair.Key);
                        lodTransitionData.Time = 0;
                        instance.IsDirty       = true;
                    }
                }
                ProfilerShort.End();

                SetAlphaForProxies(pair.Key, lodTransitionData);
            }

            foreach (var key in m_completedTransitions)
            {
                RemoveTransition(key);
            }

            m_completedTransitions.Clear();
            ProfilerShort.End();
        }
        public static void MakeCrater(MyVoxelBase voxelMap, BoundingSphereD sphere, Vector3 normal, MyVoxelMaterialDefinition material)
        {
            ProfilerShort.Begin("MakeCrater");

            Vector3I minCorner, maxCorner;

            {
                Vector3D sphereMin = sphere.Center - (sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES);
                Vector3D sphereMax = sphere.Center + (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES);
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMin, out minCorner);
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMax, out maxCorner);
            }


            voxelMap.Storage.ClampVoxelCoord(ref minCorner);
            voxelMap.Storage.ClampVoxelCoord(ref maxCorner);

            //  We are tracking which voxels were changed, so we can invalidate only needed cells in the cache
            bool changed = false;

            ProfilerShort.Begin("Reading cache");
            m_cache.Resize(minCorner, maxCorner);
            voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref minCorner, ref maxCorner);
            ProfilerShort.End();

            ProfilerShort.Begin("Changing cache");
            int      removedVoxelContent = 0;
            Vector3I tempVoxelCoord;
            Vector3I cachePos;

            for (tempVoxelCoord.Z = minCorner.Z, cachePos.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, ++cachePos.Z)
            {
                for (tempVoxelCoord.Y = minCorner.Y, cachePos.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, ++cachePos.Y)
                {
                    for (tempVoxelCoord.X = minCorner.X, cachePos.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, ++cachePos.X)
                    {
                        Vector3D voxelPosition;
                        MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref tempVoxelCoord, out voxelPosition);

                        float addDist = (float)(voxelPosition - sphere.Center).Length();
                        float addDiff = (float)(addDist - sphere.Radius);

                        byte newContent;
                        if (addDiff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)
                        {
                            newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                        }
                        else if (addDiff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)
                        {
                            newContent = MyVoxelConstants.VOXEL_CONTENT_FULL;
                        }
                        else
                        {
                            //  This formula will work even if diff is positive or negative
                            newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - addDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                        }

                        byte originalContent = m_cache.Content(ref cachePos);

                        if (newContent > originalContent && originalContent > 0)
                        {
                            if (material != null)
                            {
                                m_cache.Material(ref cachePos, material.Index);
                            }

                            changed = true;
                            m_cache.Content(ref cachePos, newContent);
                        }

                        float delDist = (float)(voxelPosition - (sphere.Center + (float)sphere.Radius * 0.7f * normal)).Length();
                        float delDiff = (float)(delDist - sphere.Radius);

                        byte contentToRemove;
                        if (delDiff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)
                        {
                            contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                        }
                        else if (delDiff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)
                        {
                            contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL;
                        }
                        else
                        {
                            //  This formula will work even if diff is positive or negative
                            contentToRemove = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - delDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                        }

                        originalContent = m_cache.Content(ref cachePos);

                        if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY && contentToRemove > MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                        {
                            changed = true;

                            int newVal = originalContent - contentToRemove;
                            if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                            {
                                newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                            }
                            m_cache.Content(ref cachePos, (byte)newVal);

                            removedVoxelContent += originalContent - newVal;
                        }

                        float setDist = (float)(voxelPosition - (sphere.Center - (float)sphere.Radius * 0.5f * normal)).Length();
                        float setDiff = (float)(setDist - sphere.Radius / 4f);

                        if (setDiff <= MyVoxelConstants.VOXEL_SIZE_IN_METRES * 1.5f)  // could be VOXEL_SIZE_IN_METRES_HALF, but we want to set material in empty cells correctly
                        {
                            byte indestructibleContentToSet = MyVoxelConstants.VOXEL_CONTENT_FULL;
                            if (setDiff >= MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)  // outside
                            {
                                indestructibleContentToSet = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                            }
                            else if (setDiff >= -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)  // boundary
                            {
                                indestructibleContentToSet = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - setDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                            }

                            MyVoxelMaterialDefinition originalMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref cachePos));

                            // Change the material:
                            // - always on boundaries between material and nothing
                            // - smoothly on inner boundaries
                            MyVoxelMaterialDefinition newMaterial = material;
                            if (setDiff > 0)
                            {
                                byte content = m_cache.Content(ref cachePos);
                                if (content == MyVoxelConstants.VOXEL_CONTENT_FULL)
                                {
                                    newMaterial = originalMaterial;
                                }
                                if (setDiff >= MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF && content != MyVoxelConstants.VOXEL_CONTENT_EMPTY)  // set material behind boundary only for empty voxels
                                {
                                    newMaterial = originalMaterial;
                                }
                            }

                            if (originalMaterial == newMaterial)
                            {
                                continue;
                            }

                            m_cache.Material(ref cachePos, newMaterial.Index);
                            changed = true;
                        }

                        float dist = (float)(voxelPosition - sphere.Center).Length();
                        float diff = (float)(dist - sphere.Radius);

                        if (diff <= 0f)
                        {
                            originalContent = m_cache.Content(ref cachePos);
                            if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                            {
                                bool wrinkled = m_cache.WrinkleVoxelContent(ref cachePos, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_ADD, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_REMOVE);
                                if (wrinkled)
                                {
                                    changed = true;
                                }
                            }
                        }
                    }
                }
            }
            ProfilerShort.End();

            if (changed)
            {
                ProfilerShort.Begin("RemoveSmallVoxelsUsingChachedVoxels");
                RemoveSmallVoxelsUsingChachedVoxels();
                ProfilerShort.BeginNextBlock("Writing cache");
                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref minCorner, ref maxCorner);
                ProfilerShort.End();
            }

            ProfilerShort.End();
        }
        internal static void Render(IRtvTexture gbuffer1Copy)
        {
            IBorrowedUavTexture accumTarget    = MyManagers.RwTexturesPool.BorrowUav("MyTransparentRendering.AccumTarget", Format.R16G16B16A16_Float);
            IBorrowedUavTexture coverageTarget = MyManagers.RwTexturesPool.BorrowUav("MyTransparentRendering.CoverageTarget", Format.R16_UNorm);

            ProfilerShort.Begin("Atmosphere");
            MyGpuProfiler.IC_BeginBlock("Atmosphere");
            if (MyRender11.DebugOverrides.Atmosphere)
            {
                MyAtmosphereRenderer.RenderGBuffer();
            }

            ProfilerShort.BeginNextBlock("Clouds");
            MyGpuProfiler.IC_BeginNextBlock("Clouds");
            if (MyRender11.DebugOverrides.Clouds)
            {
                MyCloudRenderer.Render();
            }

            var depthResource = MyGBuffer.Main.ResolvedDepthStencil;

            // setup weighted blended OIT targets + blend states
            if (MyRender11.Settings.DrawBillboards)
            {
                ProfilerShort.BeginNextBlock("Billboards");
                MyGpuProfiler.IC_BeginNextBlock("Billboards");
                MyBillboardRenderer.Gather();

                MyBillboardRenderer.RenderAdditveBottom(depthResource.SrvDepth);

                SetupTargets(accumTarget, coverageTarget, true);

                MyBillboardRenderer.RenderStandard(depthResource.SrvDepth);
            }
            else
            {
                SetupTargets(accumTarget, coverageTarget, true);
            }

            ProfilerShort.BeginNextBlock("GPU Particles");
            MyGpuProfiler.IC_BeginNextBlock("GPU Particles");
            if (MyRender11.DebugOverrides.GPUParticles)
            {
                MyGPUParticleRenderer.Run(depthResource.SrvDepth, MyGBuffer.Main.GBuffer1);
            }

            // Render decals on transparent surfaces in 2 steps: first far, second proximity
            if (MyRender11.Settings.DrawGlass)
            {
                ProfilerShort.BeginNextBlock("Static glass");
                MyGpuProfiler.IC_BeginNextBlock("Static glass");
                m_glassWithDecals.Clear();
                MyStaticGlassRenderer.Render(HandleGlass);

                float intervalMax = MyScreenDecals.VISIBLE_DECALS_SQ_TH;
                for (int it = 0; it < m_distances.Length; it++)
                {
                    float intervalMin = m_distances[it];

                    ProfilerShort.BeginNextBlock("Glass - Depth Only");
                    MyGpuProfiler.IC_BeginNextBlock("Glass - Depth Only");
                    //TODO: This code should properly render glass decals, that they are visible when looking through window on another window
                    // Anyway, it is italian code and it doesnt work. Solve after Beta
                    bool glassFound = MyStaticGlassRenderer.RenderGlassDepthOnly(depthResource, gbuffer1Copy, intervalMin, intervalMax);

                    // if (glassFound)
                    {
                        SetupTargets(accumTarget, coverageTarget, false);

                        ProfilerShort.BeginNextBlock("Render decals - Transparent");
                        MyGpuProfiler.IC_BeginNextBlock("Render decals - Transparent");
                        MyScreenDecals.Draw(gbuffer1Copy, true /*, m_glassWithDecals*/);
                    }

                    intervalMax = intervalMin;
                }

                ProfilerShort.BeginNextBlock("New static glass");
                //MyManagers.GeometryRenderer.RenderGlass();
            }

            if (IsUsedOverlappingHeatMap())
            {
                DisplayOverlappingHeatMap(accumTarget, coverageTarget, MyRender11.Settings.DisplayTransparencyHeatMapInGrayscale);
            }

            MyGpuProfiler.IC_BeginNextBlock("OIT Resolve");
            // resolve weighted blended OIT in  accum / coverage to LBuffer
            if (MyRender11.DebugOverrides.OIT)
            {
                ResolveOIT(accumTarget, coverageTarget);
            }

            ProfilerShort.BeginNextBlock("Billboards");
            MyGpuProfiler.IC_BeginNextBlock("Billboards");
            if (MyRender11.Settings.DrawBillboards)
            {
                MyBillboardRenderer.RenderAdditveTop(depthResource.SrvDepth);
            }

            RC.SetRtv(null);

            MyGpuProfiler.IC_EndBlock();

            coverageTarget.Release();
            accumTarget.Release();

            ProfilerShort.End();
        }
Beispiel #9
0
        // Returns the final image and copies it to renderTarget if non-null
        private static IRtvTexture DrawGameScene(IRtvBindable renderTarget, out IBorrowedRtvTexture debugAmbientOcclusion)
        {
            MyGpuProfiler.IC_BeginBlockAlways("ClearAndGeometryRender");

            PrepareGameScene();

            // todo: shouldn't be necessary
            if (true)
            {
                ProfilerShort.Begin("Clear");
                MyRender11.RC.ClearState();
                ProfilerShort.End();
            }

            if (MyStereoRender.Enable && MyStereoRender.EnableUsingStencilMask)
            {
                ProfilerShort.Begin("MyStereoStencilMask.Draw");
                MyGpuProfiler.IC_BeginBlock("MyStereoStencilMask.Draw");
                MyStereoStencilMask.Draw();
                MyGpuProfiler.IC_EndBlock();
                ProfilerShort.End();
            }

            ProfilerShort.Begin("MyLights.Update");
            MyLights.Update();
            ProfilerShort.End();

            ProfilerShort.Begin("DynamicGeometryRenderer");
            MyCullQuery cullQuery = m_dynamicGeometryRenderer.PrepareCullQuery(true); // it is used to share rendering settings between the old and the new pipeline

            ProfilerShort.End();

            MyGpuProfiler.IC_BeginBlock("NewGeometryRenderer");
            ProfilerShort.Begin("NewGeometryRenderer");
            IGeometrySrvStrategy geometrySrvStrategy = MyManagers.GeometrySrvResolver.GetGeometrySrvStrategy();

            if (MyDebugGeometryStage2.EnableNewGeometryPipeline)
            {
                MyManagers.GeometryRenderer.Render(cullQuery, geometrySrvStrategy);
            }
            ProfilerShort.End();
            MyGpuProfiler.IC_EndBlock();

            MyGpuProfiler.IC_BeginBlock("MyGeometryRenderer.Render");
            Debug.Assert(m_commandLists.Count == 0, "Not all command lists executed last frame!");
            ProfilerShort.Begin("DynamicGeometryRenderer");
            m_dynamicGeometryRenderer.Render(m_commandLists);
            ProfilerShort.End();    // End function block
            if (MyScene.SeparateGeometry)
            {
                ProfilerShort.Begin("StaticGeometryRenderer");
                m_staticGeometryRenderer.Render(m_commandLists); // , false);
                ProfilerShort.End();                             // End function block
            }

            SendGlobalOutputMessages();
            ExecuteCommandLists(m_commandLists);
            MyGpuProfiler.IC_EndBlock();

#if !UNSHARPER_TMP
            MyManagers.EnvironmentProbe.FinalizeEnvProbes();
#endif

            // cleanup context atfer deferred lists
            if (true)
            {
                ProfilerShort.Begin("Clear3");
                MyRender11.RC.ClearState();
                ProfilerShort.End();
            }

            MyGpuProfiler.IC_EndBlockAlways();

            IBorrowedRtvTexture gbuffer1Copy = MyGBuffer.Main.GetGbuffer1CopyRtv();

            ProfilerShort.Begin("Render decals - Opaque");
            MyGpuProfiler.IC_BeginBlock("Render decals - Opaque");
            MyScreenDecals.Draw(gbuffer1Copy, false);
            MyGpuProfiler.IC_EndBlock();

            IBorrowedDepthStencilTexture depthStencilCopy = null; // Highlights need the depth state before foliage
            if (MyHighlight.HasHighlights)
            {
                depthStencilCopy = MyGBuffer.Main.GetDepthStencilCopyRtv();
            }

            ProfilerShort.BeginNextBlock("Render foliage");
            MyGpuProfiler.IC_BeginBlockAlways("RenderFoliage");
            m_foliageRenderer.Render();
            MyGpuProfiler.IC_EndBlockAlways();

            MyGpuProfiler.IC_BeginBlock("GBuffer Resolve");
            ProfilerShort.BeginNextBlock("MySceneMaterials.MoveToGPU");
            MySceneMaterials.MoveToGPU();

            MyRender11.RC.ResetTargets();

            IBorrowedRtvTexture ambientOcclusionRtv = MyManagers.RwTexturesPool.BorrowRtv("MyScreenDependants.AmbientOcclusion",
                                                                                          ResolutionI.X, ResolutionI.Y, SharpDX.DXGI.Format.R8_UNorm);
            debugAmbientOcclusion = ambientOcclusionRtv; // Pass the texture to the outside

            int nPasses = MyStereoRender.Enable ? 2 : 1;
            for (int i = 0; i < nPasses; i++)
            {
                if (MyStereoRender.Enable)
                {
                    MyStereoRender.RenderRegion = i == 0 ? MyStereoRegion.LEFT : MyStereoRegion.RIGHT;
                }

                MyGBuffer.Main.ResolveMultisample();

                ProfilerShort.BeginNextBlock("Shadows");
                MyGpuProfiler.IC_BeginBlockAlways("Shadows");
                IBorrowedUavTexture postProcessedShadows;
                if (MyScene.SeparateGeometry)
                {
                    MyShadowCascadesPostProcess.Combine(MyShadowCascades.CombineShadowmapArray, DynamicShadows.ShadowCascades, StaticShadows.ShadowCascades);
                    postProcessedShadows = DynamicShadows.ShadowCascades.PostProcess(MyShadowCascades.CombineShadowmapArray);
                    //MyShadowCascadesPostProcess.Combine(MyShadowCascades.CombineShadowmapArray,
                    //    DynamicShadows.ShadowCascades, StaticShadows.ShadowCascades);
                    //postProcessedShadows =
                    //    DynamicShadows.ShadowCascades.PostProcess(MyShadowCascades.CombineShadowmapArray);
                }
                else
                {
                    postProcessedShadows = DynamicShadows.ShadowCascades.PostProcess(DynamicShadows.ShadowCascades.CascadeShadowmapArray);
                    //postProcessedShadows = MyManagers.Shadow.Evaluate();
                }
                MyGpuProfiler.IC_EndBlockAlways();

                if (MySSAO.Params.Enabled && Settings.User.AmbientOcclusionEnabled &&
                    m_debugOverrides.Postprocessing && m_debugOverrides.SSAO)
                {
                    ProfilerShort.BeginNextBlock("SSAO");
                    MyGpuProfiler.IC_BeginBlockAlways("SSAO");
                    MySSAO.Run(ambientOcclusionRtv, MyGBuffer.Main);

                    if (MySSAO.Params.UseBlur)
                    {
                        IBorrowedRtvTexture ambientOcclusionHelper = MyManagers.RwTexturesPool.BorrowRtv("MyScreenDependants.AmbientOcclusionHelper",
                                                                                                         ResolutionI.X, ResolutionI.Y, SharpDX.DXGI.Format.R8_UNorm);

                        MyBlur.Run(ambientOcclusionRtv, ambientOcclusionHelper, ambientOcclusionRtv, clearColor: Color4.White);
                        ambientOcclusionHelper.Release();
                    }
                    MyGpuProfiler.IC_EndBlockAlways();
                }
                else if (MyHBAO.Params.Enabled && Settings.User.AmbientOcclusionEnabled &&
                         m_debugOverrides.Postprocessing && m_debugOverrides.SSAO)
                {
                    ProfilerShort.BeginNextBlock("HBAO");
                    MyGpuProfiler.IC_BeginBlock("HBAO");
                    MyHBAO.Run(ambientOcclusionRtv, MyGBuffer.Main);
                    MyGpuProfiler.IC_EndBlock();
                }
                else
                {
                    MyRender11.RC.ClearRtv(ambientOcclusionRtv, Color4.White);
                }

                ProfilerShort.BeginNextBlock("Lights");
                MyGpuProfiler.IC_BeginBlockAlways("Lights");
                if (m_debugOverrides.Lighting)
                {
                    MyLightsRendering.Render(postProcessedShadows, ambientOcclusionRtv);
                }
                MyGpuProfiler.IC_EndBlockAlways();
                postProcessedShadows.Release();

                if (MyRender11.DebugOverrides.Flares)
                {
                    MyLightsRendering.DrawFlares();
                }
            }
            MyStereoRender.RenderRegion = MyStereoRegion.FULLSCREEN;
            MyGpuProfiler.IC_EndBlock();

            ProfilerShort.BeginNextBlock("Occlusion Queries");
            MyGpuProfiler.IC_BeginBlock("Occlusion Queries");
            MyOcclusionQueryRenderer.Render(RC, MyGBuffer.Main.ResolvedDepthStencil, MyGBuffer.Main.LBuffer);
            MyGpuProfiler.IC_EndBlock();

            // Rendering for VR is solved inside of Transparent rendering
            ProfilerShort.BeginNextBlock("Transparent Pass");
            MyGpuProfiler.IC_BeginBlockAlways("TransparentPass");
            if (m_debugOverrides.Transparent)
            {
                MyTransparentRendering.Render(gbuffer1Copy);
            }
            MyGpuProfiler.IC_EndBlockAlways();

            gbuffer1Copy.Release();

            ProfilerShort.BeginNextBlock("PostProcess");
            MyGpuProfiler.IC_BeginBlockAlways("PostProcess");
            MyGpuProfiler.IC_BeginBlock("Luminance reduction");
            IBorrowedUavTexture avgLum = null;

            if (MyRender11.Postprocess.EnableEyeAdaptation)
            {
                if (m_resetEyeAdaptation)
                {
                    MyLuminanceAverage.Reset();
                    m_resetEyeAdaptation = false;
                }

                avgLum = MyLuminanceAverage.Run(MyGBuffer.Main.LBuffer);
            }
            else
            {
                avgLum = MyLuminanceAverage.Skip();
            }

            MyGpuProfiler.IC_EndBlock();

            IBorrowedUavTexture histogram = null;
            if (MyRender11.Settings.DisplayHistogram)
            {
                histogram = MyHdrDebugTools.CreateHistogram(MyGBuffer.Main.LBuffer, MyGBuffer.Main.SamplesCount);
            }
            if (MyRender11.Settings.DisplayHdrIntensity)
            {
                MyHdrDebugTools.DisplayHdrIntensity(MyGBuffer.Main.LBuffer);
            }

            MyGpuProfiler.IC_BeginBlock("Bloom");
            IBorrowedUavTexture bloom;
            if (m_debugOverrides.Postprocessing && m_debugOverrides.Bloom)
            {
                bloom = MyBloom.Run(MyGBuffer.Main.LBuffer, MyGBuffer.Main.GBuffer2, MyGBuffer.Main.ResolvedDepthStencil.SrvDepth);
            }
            else
            {
                bloom = MyManagers.RwTexturesPool.BorrowUav("bloom_EightScreenUavHDR", MyRender11.ResolutionI.X / 8, MyRender11.ResolutionI.Y / 8, MyGBuffer.LBufferFormat);
                MyRender11.RC.ClearRtv(bloom, Color4.Black);
            }
            MyGpuProfiler.IC_EndBlock();

            MyGpuProfiler.IC_BeginBlock("Tone mapping");
            IBorrowedUavTexture tonemapped = MyToneMapping.Run(MyGBuffer.Main.LBuffer, avgLum, bloom, Postprocess.EnableTonemapping && m_debugOverrides.Postprocessing && m_debugOverrides.Tonemapping);
            bloom.Release();
            MyGpuProfiler.IC_EndBlock();

            IRtvTexture renderedImage;

            IBorrowedCustomTexture fxaaTarget = null;
            bool fxaa = MyRender11.FxaaEnabled;
            if (fxaa)
            {
                fxaaTarget = MyManagers.RwTexturesPool.BorrowCustom("MyRender11.FXAA.Rgb8");
                MyGpuProfiler.IC_BeginBlock("FXAA");
                MyFXAA.Run(fxaaTarget.Linear, tonemapped);
                MyGpuProfiler.IC_EndBlock();

                renderedImage = fxaaTarget.SRgb;
            }
            else
            {
                renderedImage = tonemapped;
            }


            ProfilerShort.Begin("MyHighlight.Run");
            MyHighlight.Run(renderedImage, fxaaTarget, depthStencilCopy);
            ProfilerShort.End();

            if (depthStencilCopy != null)
            {
                depthStencilCopy.Release();
            }

            if (renderTarget != null)
            {
                MyCopyToRT.Run(renderTarget, renderedImage);
            }

            if (MyRender11.Settings.DisplayHistogram)
            {
                if (renderTarget != null && avgLum != null)
                {
                    MyHdrDebugTools.DisplayHistogram(renderTarget, avgLum, histogram);
                }
            }
            MyGpuProfiler.IC_EndBlockAlways();
            ProfilerShort.End();

            if (fxaaTarget != null)
            {
                fxaaTarget.Release();
            }
            if (histogram != null)
            {
                histogram.Release();
            }
            avgLum.Release();
            tonemapped.Release();

            // HOTFIX: MyDebugTextureDisplay uses borrowed textures. If we place MyDebugTextureDisplay to the different location, we will have problem with borrowed textures (comment by Michal)
            ProfilerShort.Begin("MyDebugTextureDisplay.Draw");
            MyGpuProfiler.IC_BeginBlock("MyDebugTextureDisplay.Draw");
            MyDebugTextureDisplay.Draw(MyRender11.Backbuffer);
            MyGpuProfiler.IC_EndBlock();
            ProfilerShort.End();

            return(renderedImage);
        }
Beispiel #10
0
        internal void InitFromBreakableBody(HkdBreakableBody b, MatrixD worldMatrix, MyCubeBlock block)
        {
            ProfilerShort.Begin("RemoveGen&SetFixed");

            OriginalBlocks.Clear();
            if (block != null)
            {
                if (block is MyCompoundCubeBlock)
                {
                    foreach (var block2 in (block as MyCompoundCubeBlock).GetBlocks())
                    {
                        OriginalBlocks.Add(block2.BlockDefinition.Id);
                    }
                }
                else if (block is MyFracturedBlock)
                {
                    OriginalBlocks.AddRange((block as MyFracturedBlock).OriginalBlocks);
                }
                else
                {
                    OriginalBlocks.Add(block.BlockDefinition.Id);
                }
            }

            var  rigidBody = b.GetRigidBody();
            bool isFixed   = MyDestructionHelper.IsFixed(b.BreakableShape);

            if (isFixed)
            {
                rigidBody.UpdateMotionType(HkMotionType.Fixed);
                rigidBody.LinearVelocity  = Vector3.Zero;
                rigidBody.AngularVelocity = Vector3.Zero;
            }

            ProfilerShort.Begin("Sync");
            if (SyncFlag)
            {
                CreateSync();
            }
            ProfilerShort.End();

            PositionComp.WorldMatrix = worldMatrix;
            Physics.Flags            = isFixed ? RigidBodyFlag.RBF_STATIC : RigidBodyFlag.RBF_DEBRIS;
            Physics.BreakableBody    = b;
            rigidBody.UserObject     = Physics;
            if (!isFixed)
            {
                rigidBody.Motion.SetDeactivationClass(HkSolverDeactivation.High);
                rigidBody.EnableDeactivation = true;
                if (MyFakes.REDUCE_FRACTURES_COUNT)
                {
                    if (b.BreakableShape.Volume < 1 && MyRandom.Instance.Next(6) > 1)
                    {
                        rigidBody.Layer = MyFracturedPiecesManager.FakePieceLayer;
                    }
                    else
                    {
                        rigidBody.Layer = MyPhysics.DefaultCollisionLayer;
                    }
                }
                else
                {
                    rigidBody.Layer = MyPhysics.DefaultCollisionLayer;
                }
            }
            else
            {
                rigidBody.Layer = MyPhysics.StaticCollisionLayer;
            }
            Physics.BreakableBody.AfterReplaceBody += Physics.FracturedBody_AfterReplaceBody;

            if (OriginalBlocks.Count > 0)
            {
                MyPhysicalModelDefinition def;
                if (MyDefinitionManager.Static.TryGetDefinition <MyPhysicalModelDefinition>(OriginalBlocks[0], out def))
                {
                    Physics.MaterialType = def.PhysicalMaterial.Id.SubtypeId;
                }
            }

            ProfilerShort.BeginNextBlock("Enable");
            Physics.Enabled = true;
            MyDestructionHelper.FixPosition(this);
            SetDataFromHavok(b.BreakableShape);
            var coml = b.GetRigidBody().CenterOfMassLocal;
            var comw = b.GetRigidBody().CenterOfMassWorld;
            var com  = b.BreakableShape.CoM;

            b.GetRigidBody().CenterOfMassLocal = com;
            b.BreakableShape.RemoveReference();
            ProfilerShort.End();
        }
Beispiel #11
0
        public bool Drill(bool collectOre = true, bool performCutout = true, bool assignDamagedMaterial = false)
        {
            ProfilerShort.Begin("MyDrillBase::Drill()");

            bool drillingSuccess = false;

            MySoundPair sound = null;

            if ((m_drillEntity.Parent != null) && (m_drillEntity.Parent.Physics != null) && !m_drillEntity.Parent.Physics.Enabled)
            {
                return(false);
            }

            if (performCutout)
            {
                var          entitiesInRange = m_sensor.EntitiesInRange;
                MyStringHash targetMaterial  = MyStringHash.NullOrEmpty;
                bool         targetIsBlock   = false;
                foreach (var entry in entitiesInRange)
                {
                    drillingSuccess = false;
                    var entity = entry.Value.Entity;
                    if (entity.MarkedForClose)
                    {
                        continue;
                    }
                    if (entity is MyCubeGrid)
                    {
                        var grid = entity as MyCubeGrid;
                        if (grid.Physics != null && grid.Physics.Enabled)
                        {
                            drillingSuccess = TryDrillBlocks(grid, entry.Value.DetectionPoint, !Sync.IsServer, out targetMaterial);
                            targetIsBlock   = true;
                        }
                        if (drillingSuccess)
                        {
                            m_initialHeatup = false;
                            CreateParticles(entry.Value.DetectionPoint, false, true, false);
                        }
                    }
                    else if (entity is MyVoxelBase)
                    {
                        ProfilerShort.Begin("Drill voxel map");
                        var voxels = entity as MyVoxelBase;
                        drillingSuccess = TryDrillVoxels(voxels, entry.Value.DetectionPoint, collectOre, !Sync.IsServer, assignDamagedMaterial);
                        ProfilerShort.BeginNextBlock("Create particles");
                        if (drillingSuccess)
                        {
                            Vector3D drillHitPoint = entry.Value.DetectionPoint;
                            if (targetMaterial == MyStringHash.NullOrEmpty)
                            {
                                var voxelMaterial = voxels.GetMaterialAt(ref drillHitPoint);
                                if (voxelMaterial != null)
                                {
                                    targetMaterial = MyStringHash.GetOrCompute(voxelMaterial.MaterialTypeName);
                                }
                            }
                            CreateParticles(entry.Value.DetectionPoint, true, false, false);
                        }
                        ProfilerShort.End();
                    }
                    else if (entity is MyFloatingObject)
                    {
                        var sphere = (BoundingSphereD)m_cutOut.Sphere;
                        sphere.Radius *= 1.33f;
                        if (entity.GetIntersectionWithSphere(ref sphere))
                        {
                            MyFloatingObject flObj = entity as MyFloatingObject;
                            if (Sync.IsServer)
                            {
                                if (flObj.Item.Content.TypeId == typeof(MyObjectBuilder_Ore))
                                {
                                    var invOwn = (m_drillEntity != null && m_drillEntity.HasInventory) ? m_drillEntity : null;
                                    if (invOwn == null)
                                    {
                                        invOwn = (m_drillEntity as MyHandDrill).Owner;
                                    }

                                    System.Diagnostics.Debug.Assert((invOwn.GetInventory(0) as MyInventory) != null, "Null or unexpected inventory type!");
                                    (invOwn.GetInventory(0) as MyInventory).TakeFloatingObject(flObj);
                                }
                                else
                                {
                                    (entity as MyFloatingObject).DoDamage(70, MyDamageType.Drill, true, attackerId: m_drillEntity != null ? m_drillEntity.EntityId : 0);
                                }
                            }
                            drillingSuccess = true;
                        }
                    }
                    else if (entity is MyCharacter)
                    {
                        var sphere = (BoundingSphereD)m_cutOut.Sphere;
                        sphere.Radius *= 0.8f;
                        var character = entity as MyCharacter;
                        if (targetMaterial == MyStringHash.NullOrEmpty)
                        {
                            targetMaterial = MyStringHash.GetOrCompute((entity as MyCharacter).Definition.PhysicalMaterial);
                        }
                        if (entity.GetIntersectionWithSphere(ref sphere))
                        {
                            //MyRenderProxy.DebugDrawSphere(sphere.Center, sphere.Radius, Color.Green.ToVector3(), 1, true);

                            //damage tracking
                            if ((m_drillEntity is MyHandDrill) && (m_drillEntity as MyHandDrill).Owner == MySession.Static.LocalCharacter && character != MySession.Static.LocalCharacter && character.IsDead == false)
                            {
                                MySession.Static.TotalDamageDealt += 20;
                            }

                            if (Sync.IsServer)
                            {
                                character.DoDamage(20, MyDamageType.Drill, true, attackerId: m_drillEntity != null ? m_drillEntity.EntityId : 0);
                            }
                            drillingSuccess = true;
                        }
                        else
                        {
                            BoundingSphereD headSphere = new BoundingSphereD(character.PositionComp.WorldMatrix.Translation + character.WorldMatrix.Up * 1.25f, 0.6f);
                            //MyRenderProxy.DebugDrawSphere(headSphere.Center, headSphere.Radius, Color.Red.ToVector3(), 1, false);
                            if (headSphere.Intersects(sphere))
                            {
                                //MyRenderProxy.DebugDrawSphere(sphere.Center, sphere.Radius, Color.Green.ToVector3(), 1, true);

                                //damage tracking
                                if ((m_drillEntity is MyHandDrill) && (m_drillEntity as MyHandDrill).Owner == MySession.Static.LocalCharacter && character != MySession.Static.LocalCharacter && character.IsDead == false)
                                {
                                    MySession.Static.TotalDamageDealt += 20;
                                }

                                if (Sync.IsServer)
                                {
                                    character.DoDamage(20, MyDamageType.Drill, true, attackerId: m_drillEntity != null ? m_drillEntity.EntityId : 0);
                                }
                                drillingSuccess = true;
                            }
                        }
                    }
                    if (drillingSuccess)
                    {
                        m_lastContactTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;
                    }
                }
                if (targetMaterial != null && targetMaterial != MyStringHash.NullOrEmpty)
                {
                    sound = MyMaterialPropertiesHelper.Static.GetCollisionCue(MyMaterialPropertiesHelper.CollisionType.Start, m_drillMaterial, targetMaterial);
                    if (sound == null || sound == MySoundPair.Empty)//target material was not set in definition - using metal/rock sound
                    {
                        if (targetIsBlock)
                        {
                            targetMaterial = m_metalMaterial;
                        }
                        else
                        {
                            targetMaterial = m_rockMaterial;
                        }
                    }
                    sound = MyMaterialPropertiesHelper.Static.GetCollisionCue(MyMaterialPropertiesHelper.CollisionType.Start, m_drillMaterial, targetMaterial);
                }
            }

            if (sound != null && sound != MySoundPair.Empty)
            {
                StartLoopSound(sound);
            }
            else
            {
                StartIdleSound(m_idleSoundLoop);
            }

            if (!IsDrilling)
            {
                IsDrilling = true;
                m_animationLastUpdateTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;
            }

            ProfilerShort.End();
            return(drillingSuccess);
        }
Beispiel #12
0
        internal static void Render(IRtvTexture gbuffer1Copy)
        {
            IBorrowedUavTexture accumTarget    = MyManagers.RwTexturesPool.BorrowUav("MyTransparentRendering.AccumTarget", Format.R16G16B16A16_Float);
            IBorrowedUavTexture coverageTarget = MyManagers.RwTexturesPool.BorrowUav("MyTransparentRendering.CoverageTarget", Format.R16_UNorm);

            ProfilerShort.Begin("Atmosphere");
            MyGpuProfiler.IC_BeginBlock("Atmosphere");
            if (MyRender11.DebugOverrides.Atmosphere)
            {
                MyAtmosphereRenderer.Render();
            }

            ProfilerShort.BeginNextBlock("Clouds");
            MyGpuProfiler.IC_BeginNextBlock("Clouds");
            if (MyRender11.DebugOverrides.Clouds)
            {
                MyCloudRenderer.Render();
            }
            MyGpuProfiler.IC_EndBlock();

            var depthResource = MyGBuffer.Main.ResolvedDepthStencil;

            // setup weighted blended OIT targets + blend states
            SetupTargets(accumTarget, coverageTarget, true);

            ProfilerShort.BeginNextBlock("Static glass");
            MyGpuProfiler.IC_BeginBlock("Static glass");
            m_glassWithDecals.Clear();
            MyStaticGlassRenderer.Render(HandleGlass);
            MyGpuProfiler.IC_EndBlock();

            ProfilerShort.BeginNextBlock("Billboards");
            MyGpuProfiler.IC_BeginBlock("Billboards");
            bool resetBindings = MyBillboardRenderer.Gather();

            if (resetBindings)
            {
                SetupTargets(accumTarget, coverageTarget, false);
            }

            MyBillboardRenderer.Render(depthResource.SrvDepth);

            ProfilerShort.BeginNextBlock("GPU Particles");
            MyGpuProfiler.IC_BeginNextBlock("GPU Particles");
            if (MyRender11.DebugOverrides.GPUParticles)
            {
                MyGPUParticleRenderer.Run(depthResource.SrvDepth, MyGBuffer.Main.GBuffer1);
            }
            MyGpuProfiler.IC_EndBlock();

            // Render decals on transparent surfaces in 2 steps: first far, second proximity
            float intervalMax = MyScreenDecals.VISIBLE_DECALS_SQ_TH;

            for (int it = 0; it < m_distances.Length; it++)
            {
                float intervalMin = m_distances[it];

                ProfilerShort.BeginNextBlock("Glass - Depth Only");
                MyGpuProfiler.IC_BeginBlock("Glass - Depth Only");
                bool glassFound = MyStaticGlassRenderer.RenderGlassDepthOnly(depthResource, gbuffer1Copy, intervalMin, intervalMax);
                MyGpuProfiler.IC_EndBlock();

                if (glassFound)
                {
                    SetupTargets(accumTarget, coverageTarget, false);

                    ProfilerShort.BeginNextBlock("Render decals - Transparent");
                    MyGpuProfiler.IC_BeginBlock("Render decals - Transparent");
                    MyScreenDecals.Draw(gbuffer1Copy, true, m_glassWithDecals);
                    MyGpuProfiler.IC_EndBlock();
                }

                intervalMax = intervalMin;
            }

            if (IsUsedOverlappingHeatMap())
            {
                DisplayOverlappingHeatMap(accumTarget, coverageTarget, MyRender11.Settings.DisplayTransparencyHeatMapInGrayscale);
            }

            MyGpuProfiler.IC_BeginBlock("OIT Resolve");
            // resolve weighted blended OIT in  accum / coverage to LBuffer
            if (MyRender11.DebugOverrides.OIT)
            {
                ResolveOIT(accumTarget, coverageTarget);
            }
            else
            {
                RC.SetRtv(null);
            }
            MyGpuProfiler.IC_EndBlock();

            coverageTarget.Release();
            accumTarget.Release();

            ProfilerShort.End();
        }
Beispiel #13
0
        public void Weld(MyPhysicsBody other, bool recreateShape = true)
        {
            if (other.WeldInfo.Parent == this) //already welded to this
            {
                return;
            }

            if (other.IsWelded && !IsWelded)
            {
                other.Weld(this);
                return;
            }

            if (IsWelded)
            {
                WeldInfo.Parent.Weld(other);
                return;
            }
            if (other.WeldInfo.Children.Count > 0)
            {
                Debug.Fail("Welding other welded gorup");
                other.UnweldAll(false); //they should end in same group and get welded
            }
            ProfilerShort.Begin("Weld");
            HkShape thisShape;
            bool    firstWelded = WeldInfo.Children.Count == 0;

            if (firstWelded)
            {
                //RemoveConstraints(RigidBody);
                WeldedRigidBody = RigidBody;
                thisShape       = RigidBody.GetShape();
                if (HavokWorld != null)
                {
                    HavokWorld.RemoveRigidBody(WeldedRigidBody);
                }
                RigidBody = HkRigidBody.Clone(WeldedRigidBody);
                if (HavokWorld != null)
                {
                    HavokWorld.AddRigidBody(RigidBody);
                }
                HkShape.SetUserData(thisShape, RigidBody);
                Entity.OnPhysicsChanged += WeldedEntity_OnPhysicsChanged;
                WeldInfo.UpdateMassProps(RigidBody);
                //Entity.OnClose += Entity_OnClose;
            }
            else
            {
                thisShape = GetShape();
            }

            other.Deactivate();

            var transform = other.Entity.WorldMatrix * Entity.WorldMatrixInvScaled;

            other.WeldInfo.Transform = transform;
            other.WeldInfo.UpdateMassProps(other.RigidBody);
            Debug.Assert(other.WeldedRigidBody == null);
            other.WeldedRigidBody = other.RigidBody;
            other.RigidBody       = RigidBody;
            other.WeldInfo.Parent = this;
            other.ClusterObjectID = ClusterObjectID;
            WeldInfo.Children.Add(other);

            //if(recreateShape)
            //    RecreateWeldedShape(thisShape);

            ProfilerShort.BeginNextBlock("OnPhysicsChanged");
            //(other.Entity as MyEntity).RaisePhysicsChanged();
            //other.Entity.OnPhysicsChanged += WeldedEntity_OnPhysicsChanged;
            //Debug.Assert(other.m_constraints.Count == 0, "Constraints left in welded body");
            ProfilerShort.BeginNextBlock("RemoveConstraints");
            ProfilerShort.End();
            OnWelded(other);
            other.OnWelded(this);
        }
        public void WriteRange(MyStorageData source, MyStorageDataTypeFlags dataToWrite, ref Vector3I voxelRangeMin, ref Vector3I voxelRangeMax)
        {
            MyPrecalcComponent.AssertUpdateThread();

            ProfilerShort.Begin(GetType().Name + ".WriteRange");
            try
            {
                m_compressedData = null;

                if (CachedWrites && (m_pendingChunksToWrite.Count < WriteCacheCap || OverlapsAnyCachedCell(voxelRangeMin, voxelRangeMax)))
                {
                    var lodDiff = VoxelChunk.SizeBits;

                    var chunkMin = voxelRangeMin >> lodDiff;
                    var chunkMax = voxelRangeMax >> lodDiff;

                    var pos = Vector3I.Zero;
                    for (pos.Z = chunkMin.Z; pos.Z <= chunkMax.Z; ++pos.Z)
                    {
                        for (pos.Y = chunkMin.Y; pos.Y <= chunkMax.Y; ++pos.Y)
                        {
                            for (pos.X = chunkMin.X; pos.X <= chunkMax.X; ++pos.X)
                            {
                                var celPos = pos << lodDiff;

                                var lodCkStart = pos << lodDiff;
                                lodCkStart = Vector3I.Max(lodCkStart, voxelRangeMin);

                                var lodCkEnd = ((pos + 1) << lodDiff) - 1;
                                lodCkEnd = Vector3I.Min(lodCkEnd, voxelRangeMax);

                                var targetOffset = lodCkStart - voxelRangeMin;

                                VoxelChunk chunk;
                                // Do not read the chunk if the range overlaps the whole chunk
                                var toRead = (lodCkEnd - lodCkStart + 1).Size != VoxelChunk.Volume ? dataToWrite : 0;
                                GetChunk(ref pos, out chunk, toRead);

                                lodCkStart -= celPos;
                                lodCkEnd   -= celPos;

                                using (chunk.Lock.AcquireExclusiveUsing())
                                {
                                    bool dirty = chunk.Dirty != 0;
                                    chunk.Write(source, dataToWrite, ref targetOffset, ref lodCkStart, ref lodCkEnd);
                                    if (!dirty)
                                    {
                                        m_pendingChunksToWrite.Enqueue(pos);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    using (m_storageLock.AcquireExclusiveUsing())
                        WriteRangeInternal(source, dataToWrite, ref voxelRangeMin, ref voxelRangeMax);
                }

                ProfilerShort.BeginNextBlock(GetType().Name + ".OnRangeChanged");

                OnRangeChanged(voxelRangeMin, voxelRangeMax, dataToWrite);
            }
            finally
            {
                ProfilerShort.End();
            }
        }
        public static void CutOutShapeWithProperties(
            MyVoxelBase voxelMap,
            MyShape shape,
            out float voxelsCountInPercent,
            out MyVoxelMaterialDefinition voxelMaterial,
            Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null,
            bool updateSync = false,
            bool onlyCheck  = false)
        {
            if (MySession.Static.EnableVoxelDestruction == false)
            {
                voxelsCountInPercent = 0;
                voxelMaterial        = null;
                return;
            }

            ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()");

            int originalSum = 0;
            int removedSum  = 0;

            // Some shapes just ignore transforms so we round the bbox conservativelly by converting it to sphere
            var bbox   = shape.GetWorldBoundaries();
            var center = bbox.Center;
            var radius = (center - bbox.Min).Length();

            MatrixD mat = voxelMap.PositionComp.WorldMatrix;
            MatrixD inverse;

            //Vector3D translation = mat.Translation;
            //mat.Translation = Vector3D.Zero;

            // invert is used to bring voxel coordinates back to world.
            inverse = voxelMap.PositionComp.WorldMatrixInvScaled;//MatrixD.Invert(ref mat, out inverse);

            Vector3 offset = voxelMap.StorageMin + voxelMap.SizeInMetresHalf;

            Vector3D.Transform(ref center, ref inverse, out center);

            // The transform is centered, but the code expects voxel local coordinates.
            center += voxelMap.SizeInMetresHalf;

            bbox = new BoundingBoxD(center - radius, center + radius);

            Vector3I minCorner, maxCorner;

            ComputeShapeBounds(voxelMap, ref bbox, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner);

            var cacheMin = minCorner - 1;
            var cacheMax = maxCorner + 1;

            voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
            voxelMap.Storage.ClampVoxelCoord(ref cacheMax);
            m_cache.Resize(cacheMin, cacheMax);
            voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cacheMin, ref cacheMax);

            {
                var      shapeCenter = bbox.Center;
                Vector3I exactCenter;
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(Vector3.Zero, ref shapeCenter, out exactCenter);
                exactCenter  -= cacheMin;
                exactCenter   = Vector3I.Clamp(exactCenter, Vector3I.Zero, m_cache.Size3D - 1);
                voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref exactCenter));
            }

            ProfilerShort.Begin("Main loop");
            for (var it = new Vector3I.RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext())
            {
                var relPos   = it.Current - cacheMin; // get original amount
                var original = m_cache.Content(ref relPos);

                if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove
                {
                    continue;
                }

                Vector3D vpos;
                MyVoxelCoordSystems.VoxelCoordToLocalPosition(ref it.Current, out vpos);

                // center
                vpos -= offset;

                // transform back to world space.
                Vector3D.Transform(ref vpos, ref mat, out vpos);

                var volume = shape.GetVolume(ref vpos);

                if (volume == 0f) // if there is no intersection
                {
                    continue;
                }

                var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                var voxelMat  = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos));
                var toRemove  = (int)(maxRemove * voxelMat.DamageRatio);
                var newVal    = MathHelper.Clamp(original - toRemove, 0, original - maxRemove);
                var removed   = Math.Abs(original - newVal);

                if (!onlyCheck)
                {
                    m_cache.Content(ref relPos, (byte)newVal);
                }

                originalSum += original;
                removedSum  += removed;

                if (exactCutOutMaterials != null)
                {
                    int value = 0;
                    exactCutOutMaterials.TryGetValue(voxelMat, out value);
                    value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed);
                    exactCutOutMaterials[voxelMat] = value;
                }
            }

            if (removedSum > 0 && updateSync && Sync.IsServer)
            {
                shape.SendDrillCutOutRequest(voxelMap);
            }

            ProfilerShort.BeginNextBlock("Write");


            if (removedSum > 0 && !onlyCheck)
            {
                //  Clear all small voxel that may have been created during explosion. They can be created even outside the range of
                //  explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the
                //  explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we
                //  will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove
                //  B voxels too.
                //!! TODO AR & MK : check if this is needed !!
                RemoveSmallVoxelsUsingChachedVoxels();

                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax);
            }
            ProfilerShort.End();


            voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f;

            if (removedSum > 0)
            {
                CheckNeighbourStaticGridsAfterVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, shape);
            }

            ProfilerShort.End();
        }
        public bool Drill(bool collectOre = true, bool performCutout = true)
        {
            ProfilerShort.Begin("MyDrillBase::Drill()");

            bool drillingSuccess = false;

            MySoundPair sound = null;

            if ((m_drillEntity.Parent != null) && (m_drillEntity.Parent.Physics != null) && !m_drillEntity.Parent.Physics.Enabled)
            {
                return(false);
            }

            if (performCutout)
            {
                var entitiesInRange = m_sensor.EntitiesInRange;
                foreach (var entry in entitiesInRange)
                {
                    drillingSuccess = false;
                    var entity = entry.Value.Entity;
                    if (entity.MarkedForClose)
                    {
                        continue;
                    }
                    if (entity is MyCubeGrid)
                    {
                        var grid = entity as MyCubeGrid;
                        if (grid.Physics != null && grid.Physics.Enabled)
                        {
                            drillingSuccess = TryDrillBlocks(grid, entry.Value.DetectionPoint, !Sync.IsServer);
                        }
                        if (drillingSuccess)
                        {
                            m_initialHeatup = false;
                            sound           = m_sounds.MetalLoop;
                            CreateParticles(entry.Value.DetectionPoint, false, true, false);
                        }
                    }
                    else if (entity is MyVoxelBase)
                    {
                        ProfilerShort.Begin("Drill voxel map");
                        var voxels = entity as MyVoxelBase;
                        drillingSuccess = TryDrillVoxels(voxels, entry.Value.DetectionPoint, collectOre, !Sync.IsServer);
                        ProfilerShort.BeginNextBlock("Create particles");
                        if (drillingSuccess)
                        {
                            sound = m_sounds.RockLoop;
                            CreateParticles(entry.Value.DetectionPoint, true, false, true);
                        }
                        ProfilerShort.End();
                    }
                    else if (entity is MyFloatingObject)
                    {
                        var sphere = (BoundingSphereD)m_cutOut.Sphere;
                        sphere.Radius *= 1.33f;
                        if (entity.GetIntersectionWithSphere(ref sphere))
                        {
                            MyFloatingObject flObj = entity as MyFloatingObject;
                            if (Sync.IsServer)
                            {
                                if (flObj.Item.Content.TypeId == typeof(MyObjectBuilder_Ore))
                                {
                                    IMyInventoryOwner invOwn = m_drillEntity as IMyInventoryOwner;
                                    if (invOwn == null)
                                    {
                                        invOwn = (m_drillEntity as MyHandDrill).Owner as IMyInventoryOwner;
                                    }
                                    invOwn.GetInventory(0).TakeFloatingObject(flObj);
                                }
                                else
                                {
                                    (entity as MyFloatingObject).DoDamage(70, MyDamageType.Drill, true);
                                }
                            }
                            drillingSuccess = true;
                        }
                    }
                    else if (entity is MyCharacter)
                    {
                        var sphere = (BoundingSphereD)m_cutOut.Sphere;
                        sphere.Radius *= (4 / 5f);
                        var character = entity as MyCharacter;
                        if (entity.GetIntersectionWithSphere(ref sphere))
                        {
                            //MyRenderProxy.DebugDrawSphere(sphere.Center, sphere.Radius, Color.Green.ToVector3(), 1, true);
                            if (Sync.IsServer)
                            {
                                character.DoDamage(20, MyDamageType.Drill, true);
                            }
                            drillingSuccess = true;
                        }
                        else
                        {
                            BoundingSphereD headSphere = new BoundingSphereD(character.PositionComp.WorldMatrix.Translation + character.WorldMatrix.Up * 1.25f, 0.6f);
                            //MyRenderProxy.DebugDrawSphere(headSphere.Center, headSphere.Radius, Color.Red.ToVector3(), 1, false);
                            if (headSphere.Intersects(sphere))
                            {
                                //MyRenderProxy.DebugDrawSphere(sphere.Center, sphere.Radius, Color.Green.ToVector3(), 1, true);
                                if (Sync.IsServer)
                                {
                                    character.DoDamage(20, MyDamageType.Drill, true);
                                }
                                drillingSuccess = true;
                            }
                        }
                    }
                    if (drillingSuccess)
                    {
                        m_lastContactTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;
                    }
                }
            }

            if (sound != null)
            {
                StartLoopSound(sound);
            }
            else
            {
                StartIdleSound(m_sounds.IdleLoop);
            }

            IsDrilling = true;

            m_animationLastUpdateTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;
            ProfilerShort.End();
            return(drillingSuccess);
        }
        protected override void ProcessCullQueryResults(MyCullQuery cullQuery)
        {
            ProfilerShort.Begin("Reset");

            foreach (MyFrustumCullQuery frustumQuery in cullQuery.FrustumCullQueries)
            {
                var cullProxies = frustumQuery.List;
                foreach (MyCullProxy cullProxy in cullProxies)
                {
                    cullProxy.Updated = false;
                    cullProxy.FirstFullyContainingCascadeIndex = uint.MaxValue;
                }
            }
            ProfilerShort.End();
            foreach (var frustumQuery in cullQuery.FrustumCullQueries)
            {
                ProfilerShort.Begin("Distance cull and update");

                var  cullProxies     = frustumQuery.List;
                bool isShadowFrustum = (frustumQuery.Type == MyFrustumEnum.ShadowCascade) || (frustumQuery.Type == MyFrustumEnum.ShadowProjection);
                for (int cullProxyIndex = 0; cullProxyIndex < cullProxies.Count; ++cullProxyIndex)
                {
                    MyCullProxy cullProxy = cullProxies[cullProxyIndex];
                    if (cullProxy == null || cullProxy.RenderableProxies == null || cullProxy.RenderableProxies.Length == 0 || cullProxy.RenderableProxies[0].Parent == null || !cullProxy.RenderableProxies[0].Parent.IsVisible)
                    {
                        m_tmpIndicesToRemove.Add(cullProxyIndex);
                        continue;
                    }

                    if (!cullProxy.Updated)
                    {
                        var renderableComponent = cullProxy.Parent;
                        if (renderableComponent != null)
                        {
                            renderableComponent.OnFrameUpdate();
                            if (renderableComponent.IsCulled)
                            {
                                m_tmpIndicesToRemove.Add(cullProxyIndex);
                                continue;
                            }
                            renderableComponent.UpdateInstanceLods();
                        }

                        // Proxies can get removed in UpdateInstanceLods
                        if (cullProxy.RenderableProxies == null)
                        {
                            m_tmpIndicesToRemove.Add(cullProxyIndex);
                            continue;
                        }

                        foreach (MyRenderableProxy proxy in cullProxy.RenderableProxies)
                        {
                            bool shouldCastShadows = proxy.Flags.HasFlags(MyRenderableProxyFlags.CastShadows) &&
                                                     (proxy.Flags.HasFlags(MyRenderableProxyFlags.DrawOutsideViewDistance) || frustumQuery.CascadeIndex < 4);

                            if (isShadowFrustum && !shouldCastShadows)
                            {
                                m_tmpIndicesToRemove.Add(cullProxyIndex);
                                break;
                            }
                            var worldMat = proxy.WorldMatrix;
                            worldMat.Translation -= MyRender11.Environment.CameraPosition;
                            proxy.CommonObjectData.LocalMatrix   = worldMat;
                            proxy.CommonObjectData.MaterialIndex = MySceneMaterials.GetDrawMaterialIndex(proxy.PerMaterialIndex);
                        }
                        cullProxy.Updated = true;
                    }
                }

                for (int removeIndex = m_tmpIndicesToRemove.Count - 1; removeIndex >= 0; --removeIndex)
                {
                    cullProxies.RemoveAtFast(m_tmpIndicesToRemove[removeIndex]);
                    frustumQuery.IsInsideList.RemoveAtFast(m_tmpIndicesToRemove[removeIndex]);
                }
                m_tmpIndicesToRemove.SetSize(0);

                ProfilerShort.BeginNextBlock("Culling by query type");
                if (frustumQuery.Type == MyFrustumEnum.MainFrustum)
                {
                    MyPerformanceCounter.PerCameraDraw11Write.ViewFrustumObjectsNum = frustumQuery.List.Count;
                }
                else if (frustumQuery.Type == MyFrustumEnum.ShadowCascade)
                {
                    while (m_shadowCascadeProxies2.Count < MyRenderProxy.Settings.ShadowCascadeCount)
                    {
                        m_shadowCascadeProxies2.Add(new HashSet <MyCullProxy_2>());
                    }

                    bool isHighCascade = frustumQuery.CascadeIndex < 3;

                    if (cullProxies.Count == 0)
                    {
                        MyShadowCascades.ShadowCascadeObjectsCounter[frustumQuery.CascadeIndex]  = 0;
                        MyShadowCascades.ShadowCascadeTriangleCounter[frustumQuery.CascadeIndex] = 0;
                    }

                    // List 1
                    for (int cullProxyIndex = 0; cullProxyIndex < cullProxies.Count; ++cullProxyIndex)
                    {
                        var cullProxy = cullProxies[cullProxyIndex];

                        if ((isHighCascade && (cullProxy.FirstFullyContainingCascadeIndex < frustumQuery.CascadeIndex - 1)) ||
                            (!isHighCascade && cullProxy.FirstFullyContainingCascadeIndex < frustumQuery.CascadeIndex) ||
                            cullProxy.RenderableProxies == null)
                        {
                            cullProxies.RemoveAtFast(cullProxyIndex);
                            frustumQuery.IsInsideList.RemoveAtFast(cullProxyIndex);
                            --cullProxyIndex;
                            continue;
                        }
                        else
                        {
                            foreach (var renderableProxy in cullProxy.RenderableProxies)
                            {
                                MyShadowCascades.ShadowCascadeTriangleCounter[frustumQuery.CascadeIndex] += (renderableProxy.InstanceCount > 0 ? renderableProxy.InstanceCount : 1) * renderableProxy.DrawSubmesh.IndexCount / 3;
                            }

                            if (frustumQuery.IsInsideList[cullProxyIndex])
                            {
                                cullProxy.FirstFullyContainingCascadeIndex = (uint)frustumQuery.CascadeIndex;
                            }
                        }
                    }

                    // List 2
                    var cullProxies2 = frustumQuery.List2;
                    m_shadowCascadeProxies2[frustumQuery.CascadeIndex].Clear();
                    for (int cullProxyIndex = 0; cullProxyIndex < cullProxies2.Count; ++cullProxyIndex)
                    {
                        var  cullProxy2 = cullProxies2[cullProxyIndex];
                        bool containedInHigherCascade = false;

                        // Cull items if they're fully contained in higher resolution cascades
                        for (int hashSetIndex = 0; hashSetIndex < frustumQuery.CascadeIndex; ++hashSetIndex)
                        {
                            if (m_shadowCascadeProxies2[hashSetIndex].Contains(cullProxy2))
                            {
                                cullProxies2.RemoveAtFast(cullProxyIndex);
                                frustumQuery.IsInsideList2.RemoveAtFast(cullProxyIndex);
                                --cullProxyIndex;
                                containedInHigherCascade = true;
                                break;
                            }
                        }

                        if (!containedInHigherCascade && frustumQuery.IsInsideList2[cullProxyIndex])
                        {
                            m_shadowCascadeProxies2[frustumQuery.CascadeIndex].Add(cullProxy2);
                        }
                    }

                    MyShadowCascades.ShadowCascadeObjectsCounter[frustumQuery.CascadeIndex] = cullProxies.Count;
                }
                else if (frustumQuery.Type == MyFrustumEnum.ShadowProjection)
                {
                    MyShadows.OtherShadowsTriangleCounter = 0;
                    for (int cullProxyIndex = 0; cullProxyIndex < cullProxies.Count; ++cullProxyIndex)
                    {
                        var cullProxy = frustumQuery.List[cullProxyIndex];
                        if (cullProxy.RenderableProxies == null)
                        {
                            cullProxies.RemoveAtFast(cullProxyIndex);
                            frustumQuery.IsInsideList.RemoveAtFast(cullProxyIndex);
                            --cullProxyIndex;
                            continue;
                        }
                        foreach (var proxy in cullProxy.RenderableProxies)
                        {
                            MyShadows.OtherShadowsTriangleCounter += Math.Max(proxy.InstanceCount, 1) * proxy.DrawSubmesh.IndexCount / 3;
                        }
                    }
                }
                ProfilerShort.End();
                if (frustumQuery.Ignored != null)
                {
                    for (int cullProxyIndex = 0; cullProxyIndex < cullProxies.Count; cullProxyIndex++)
                    {
                        if ((cullProxies[cullProxyIndex].RenderableProxies == null || cullProxies[cullProxyIndex].RenderableProxies.Length == 0 || cullProxies[cullProxyIndex].RenderableProxies[0] == null) || (frustumQuery.Ignored.Contains(cullProxies[cullProxyIndex].RenderableProxies[0].Parent.Owner.ID)))
                        {
                            cullProxies.RemoveAtFast(cullProxyIndex);
                            frustumQuery.IsInsideList.RemoveAtFast(cullProxyIndex);
                            --cullProxyIndex;
                            continue;
                        }
                    }
                }
            }
            for (int cascadeIndex = 0; cascadeIndex < MyRenderProxy.Settings.ShadowCascadeCount; ++cascadeIndex)
            {
                if (MyShadowCascades.ShadowCascadeObjectsCounter[cascadeIndex] >= 0)
                {
                    MyPerformanceCounter.PerCameraDraw11Write.ShadowCascadeObjectsNum[cascadeIndex] = MyShadowCascades.ShadowCascadeObjectsCounter[cascadeIndex];
                    MyShadowCascades.ShadowCascadeObjectsCounter[cascadeIndex] = -1;
                }
                if (MyShadowCascades.ShadowCascadeTriangleCounter[cascadeIndex] >= 0)
                {
                    MyPerformanceCounter.PerCameraDraw11Write.ShadowCascadeTriangles[cascadeIndex] = MyShadowCascades.ShadowCascadeTriangleCounter[cascadeIndex];
                    MyShadowCascades.ShadowCascadeTriangleCounter[cascadeIndex] = -1;
                }
            }
            if (MyShadows.OtherShadowsTriangleCounter >= 0)
            {
                MyPerformanceCounter.PerCameraDraw11Write.OtherShadowTriangles = MyShadows.OtherShadowsTriangleCounter;
                MyShadows.OtherShadowsTriangleCounter = -1;
            }
        }
Beispiel #18
0
        public virtual void UnregisterFromSystems(MyCubeBlock block)
        {
            // Note: ResourceDistributor, WeaponSystem and TemrminalSystem can be null on closing (they are not in the ship but in the logical group). That's why they are null-checked
            if (ResourceDistributor != null)
            {
                ProfilerShort.Begin("Unregister Power producer");
                var powerProducer = block.Components.Get <MyResourceSourceComponent>();
                if (powerProducer != null)
                {
                    ResourceDistributor.RemoveSource(powerProducer);
                }

                ProfilerShort.BeginNextBlock("Unregister Power consumer");
                var powerConsumer = block.Components.Get <MyResourceSinkComponent>();
                if (powerConsumer != null)
                {
                    ResourceDistributor.RemoveSink(powerConsumer);
                }
                ProfilerShort.End();

                var socketOwner = block as IMyRechargeSocketOwner;
                if (socketOwner != null)
                {
                    socketOwner.RechargeSocket.ResourceDistributor = null;
                }
            }

            ProfilerShort.Begin("Unregister gun object");
            if (WeaponSystem != null)
            {
                var weapon = block as IMyGunObject <MyDeviceBase>;
                if (weapon != null)
                {
                    WeaponSystem.Unregister(weapon);
                }
            }

            ProfilerShort.BeginNextBlock("Unregister functional block");
            if (TerminalSystem != null)
            {
                var functionalBlock = block as MyTerminalBlock;
                if (functionalBlock != null)
                {
                    TerminalSystem.Remove(functionalBlock);
                }
            }

            // CH: We probably don't need to unregister controller blocks here. It's done in ShipController's OnUnregisteredFromGridSystems

            /*ProfilerShort.BeginNextBlock("Unregister controller block");
             * if (ControlSystem != null)
             * {
             *  var controllableBlock = block as MyShipController;
             *  if (controllableBlock != null && controllableBlock.ControllerInfo.Controller != null)
             *      ControlSystem.RemoveControllerBlock(controllableBlock);
             * }*/

            ProfilerShort.BeginNextBlock("Unregister inventory block");
            var inventoryBlock = (block != null && block.HasInventory) ? block : null;

            if (inventoryBlock != null && inventoryBlock.HasInventory)
            {
                ConveyorSystem.Remove(inventoryBlock);
            }

            ProfilerShort.BeginNextBlock("Unregister conveyor block");
            var conveyorBlock = block as IMyConveyorEndpointBlock;

            if (conveyorBlock != null)
            {
                ConveyorSystem.RemoveConveyorBlock(conveyorBlock);
            }

            ProfilerShort.BeginNextBlock("Unregister segment block");
            var segmentBlock = block as IMyConveyorSegmentBlock;

            if (segmentBlock != null)
            {
                ConveyorSystem.RemoveSegmentBlock(segmentBlock);
            }

            ProfilerShort.BeginNextBlock("Unregister Reflector light");
            var reflectorLight = block as MyReflectorLight;

            if (reflectorLight != null)
            {
                ReflectorLightSystem.Unregister(reflectorLight);
            }

            if (MyFakes.ENABLE_WHEEL_CONTROLS_IN_COCKPIT)
            {
                ProfilerShort.BeginNextBlock("Unregister wheel");
                var wheel = block as MyMotorSuspension;
                if (wheel != null)
                {
                    WheelSystem.Unregister(wheel);
                }
            }

            ProfilerShort.BeginNextBlock("Unregister landing gear");
            var gear = block as IMyLandingGear;

            if (gear != null)
            {
                LandingSystem.Unregister(gear);
            }

            ProfilerShort.BeginNextBlock("Unregister gyro");
            var gyro = block as MyGyro;

            if (gyro != null)
            {
                GyroSystem.Unregister(gyro);
            }

            ProfilerShort.BeginNextBlock("Unregister camera");
            var camera = block as MyCameraBlock;

            if (camera != null)
            {
                CameraSystem.Unregister(camera);
            }

            ProfilerShort.BeginNextBlock("block.OnUnregisteredFromGridSystems()");
            block.OnUnregisteredFromGridSystems();

            ProfilerShort.End();
        }
Beispiel #19
0
        internal static void Render(MyUnorderedAccessTexture accumTarget, MyUnorderedAccessTexture coverageTarget)
        {
            ProfilerShort.Begin("Billboards");
            MyGpuProfiler.IC_BeginBlock("Billboards");
            if (MyRender11.MultisamplingEnabled)
            {
                MyBillboardRenderer.Render(MyGBuffer.Main.Get(MyGbufferSlot.LBuffer), MyScreenDependants.m_resolvedDepth, MyScreenDependants.m_resolvedDepth.Depth);
            }
            else
            {
                MyBillboardRenderer.Render(MyGBuffer.Main.Get(MyGbufferSlot.LBuffer), MyGBuffer.Main.DepthStencil, MyGBuffer.Main.DepthStencil.Depth);
            }
            MyGpuProfiler.IC_EndBlock();

            // setup weighted blended OIT targets + blend states
            if (MyRender11.DebugOverrides.OIT)
            {
                SetupOIT(accumTarget, coverageTarget);
            }
            else
            {
                SetupStandard();
            }

            ProfilerShort.BeginNextBlock("GPU Particles");
            MyGpuProfiler.IC_BeginBlock("GPU Particles");
            if (MyRender11.DebugOverrides.GPUParticles)
            {
                if (MyRender11.MultisamplingEnabled)
                {
                    MyGPUParticleRenderer.Run(MyScreenDependants.m_resolvedDepth.Depth);
                }
                else
                {
                    MyGPUParticleRenderer.Run(MyGBuffer.Main.DepthStencil.Depth);
                }
            }
            MyGpuProfiler.IC_EndBlock();

            // resolve weighted blended OIT in  accum / coverage to LBuffer
            if (MyRender11.DebugOverrides.OIT)
            {
                ResolveOIT(accumTarget, coverageTarget);
            }

            ProfilerShort.BeginNextBlock("Atmosphere");
            MyGpuProfiler.IC_BeginBlock("Atmosphere");
            if (MyRender11.DebugOverrides.Atmosphere)
            {
                MyAtmosphereRenderer.Render();
            }
            MyGpuProfiler.IC_EndBlock();

            ProfilerShort.BeginNextBlock("Clouds");
            MyGpuProfiler.IC_BeginBlock("Clouds");
            if (MyRender11.DebugOverrides.Clouds)
            {
                MyCloudRenderer.Render();
            }
            MyGpuProfiler.IC_EndBlock();

            ProfilerShort.End();
        }
Beispiel #20
0
        public static void CutOutShapeWithProperties(
            MyVoxelBase voxelMap,
            MyShape shape,
            out float voxelsCountInPercent,
            out MyVoxelMaterialDefinition voxelMaterial,
            Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null,
            bool updateSync          = false,
            bool onlyCheck           = false,
            bool applyDamageMaterial = false,
            bool onlyApplyMaterial   = false)
        {
            if (MySession.Static.EnableVoxelDestruction == false)
            {
                voxelsCountInPercent = 0;
                voxelMaterial        = null;
                return;
            }

            ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()");

            int  originalSum = 0;
            int  removedSum  = 0;
            bool materials   = exactCutOutMaterials != null;

            // Bring the shape into voxel space.
            var oldTranmsform = shape.Transformation;
            var newTransf     = oldTranmsform * voxelMap.PositionComp.WorldMatrixInvScaled;

            newTransf.Translation += voxelMap.SizeInMetresHalf;
            shape.Transformation   = newTransf;

            // This boundary should now be in our local space
            var bbox = shape.GetWorldBoundaries();

            Vector3I minCorner, maxCorner;

            ComputeShapeBounds(voxelMap, ref bbox, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner);

            bool readMaterial = exactCutOutMaterials != null || applyDamageMaterial;

            var cacheMin = minCorner - 1;
            var cacheMax = maxCorner + 1;

            //try on making the read/write cell alligned see MyOctreeStorage.WriteRange - Micro octree leaf

            /*const int SHIFT = 4;
             * const int REM = (1 << SHIFT) - 1;
             * const int MASK = ~REM;
             * cacheMin &= MASK;
             * cacheMax = (cacheMax + REM) & MASK;*/

            voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
            voxelMap.Storage.ClampVoxelCoord(ref cacheMax);
            m_cache.Resize(cacheMin, cacheMax);
            m_cache.ClearMaterials(0);

            // Advise that the read content shall be cached
            MyVoxelRequestFlags flags = MyVoxelRequestFlags.AdviseCache;

            voxelMap.Storage.ReadRange(m_cache, readMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax, ref flags);

            Vector3I center;

            if (materials)
            {
                center        = m_cache.Size3D / 2;
                voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref center));
            }
            else
            {
                center        = (cacheMin + cacheMax) / 2;
                voxelMaterial = voxelMap.Storage.GetMaterialAt(ref center);
            }

            MyVoxelMaterialDefinition voxelMat = null;

            ProfilerShort.Begin("Main loop");
            Vector3I pos;

            for (pos.X = minCorner.X; pos.X <= maxCorner.X; ++pos.X)
            {
                for (pos.Y = minCorner.Y; pos.Y <= maxCorner.Y; ++pos.Y)
                {
                    for (pos.Z = minCorner.Z; pos.Z <= maxCorner.Z; ++pos.Z)
                    {
                        // get original amount
                        var relPos   = pos - cacheMin;
                        var lin      = m_cache.ComputeLinear(ref relPos);
                        var original = m_cache.Content(lin);

                        if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove
                        {
                            continue;
                        }

                        Vector3D spos   = (Vector3D)(pos - voxelMap.StorageMin) * MyVoxelConstants.VOXEL_SIZE_IN_METRES;
                        var      volume = shape.GetVolume(ref spos);

                        if (volume == 0f) // if there is no intersection
                        {
                            continue;
                        }

                        var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                        var toRemove  = maxRemove;                        // (int)(maxRemove * voxelMat.DamageRatio);
                        var newVal    = Math.Max(original - toRemove, 0); //MathHelper.Clamp(original - toRemove, 0, original-maxRemove);
                        var removed   = original - newVal;

                        if (!onlyCheck && !onlyApplyMaterial)
                        {
                            m_cache.Content(lin, (byte)newVal);
                        }

                        originalSum += original;
                        removedSum  += removed;

                        var material = m_cache.Material(lin);
                        if (material != MyVoxelConstants.NULL_MATERIAL)
                        {
                            if (readMaterial)
                            {
                                voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material);
                            }

                            if (exactCutOutMaterials != null)
                            {
                                int value = 0;
                                exactCutOutMaterials.TryGetValue(voxelMat, out value);
                                value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed);
                                exactCutOutMaterials[voxelMat] = value;
                            }

                            if (applyDamageMaterial && voxelMat.HasDamageMaterial && !onlyCheck)
                            {
                                m_cache.Material(lin, voxelMat.DamagedMaterialId);
                            }
                        }
                    }
                }
            }

            if (removedSum > 0 && updateSync && Sync.IsServer)
            {
                shape.SendDrillCutOutRequest(voxelMap, applyDamageMaterial);
            }

            ProfilerShort.BeginNextBlock("Write");

            if (removedSum > 0 && !onlyCheck)
            {
                //  Clear all small voxel that may have been created during explosion. They can be created even outside the range of
                //  explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the
                //  explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we
                //  will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove
                //  B voxels too.
                //!! TODO AR & MK : check if this is needed !!
                //RemoveSmallVoxelsUsingChachedVoxels();

                var dataTypeFlags = applyDamageMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content;
                if (MyFakes.LOG_NAVMESH_GENERATION && MyAIComponent.Static.Pathfinding != null)
                {
                    MyAIComponent.Static.Pathfinding.GetPathfindingLog().LogStorageWrite(voxelMap, m_cache, dataTypeFlags, cacheMin, cacheMax);
                }
                voxelMap.Storage.WriteRange(m_cache, dataTypeFlags, ref cacheMin, ref cacheMax);
            }
            ProfilerShort.End();


            voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f;

            shape.Transformation = oldTranmsform;

            if (removedSum > 0)
            {
                OnVoxelChanged(OperationType.Cut, voxelMap, shape);
            }

            ProfilerShort.End();
        }
Beispiel #21
0
        public override void Draw()
        {
            ProfilerShort.Begin("base.Draw()");
            base.Draw();

            ProfilerShort.BeginNextBlock("Crosshair");
            if (BlockCreationIsActivated)
            {
                MyHud.Crosshair.Recenter();
            }

            ProfilerShort.BeginNextBlock("IsActivated");
            if (IsActivated)
            {
                if (DynamicMode)
                {
                    CurrentGrid     = null;
                    CurrentVoxelMap = null;
                }
                else
                {
                    ChoosePlacementObject();
                }
            }

            ProfilerShort.BeginNextBlock("UpdateClipboards");
            if (UpdateClipboards())
            {
                ProfilerShort.End();
                return;
            }

            ProfilerShort.BeginNextBlock("DrawBuildingStepsCount");
            DrawBuildingStepsCount(m_gizmo.SpaceDefault.m_startBuild, m_gizmo.SpaceDefault.m_startRemove, m_gizmo.SpaceDefault.m_continueBuild, ref m_gizmo.SpaceDefault.m_localMatrixAdd);
            ProfilerShort.End();

            bool addPos    = m_gizmo.SpaceDefault.m_startBuild.HasValue;
            bool removePos = false;

            if (DynamicMode)
            {
                ProfilerShort.Begin("DynamicMode");
                Vector3D freePlacementIntersectionPoint = GetFreeSpacePlacementPosition(out m_gizmo.SpaceDefault.m_dynamicBuildAllowed);
                m_gizmo.SpaceDefault.m_worldMatrixAdd.Translation = freePlacementIntersectionPoint;

                addPos = true;
                ProfilerShort.End();
            }
            else
            {
                if (m_gizmo.SpaceDefault.m_startBuild == null && m_gizmo.SpaceDefault.m_startRemove == null)
                {
                    ProfilerShort.Begin("!FreezeGizmo");
                    if (!FreezeGizmo)
                    {
                        float gridSize = MyDefinitionManager.Static.GetCubeSize(CurrentBlockDefinition.CubeSize);
                        m_gizmo.SpaceDefault.m_removeBlocksInMultiBlock.Clear();
                        addPos = GetAddAndRemovePositions(gridSize, PlacingSmallGridOnLargeStatic, out m_gizmo.SpaceDefault.m_addPos, out m_gizmo.SpaceDefault.m_addPosSmallOnLarge, out m_gizmo.SpaceDefault.m_addDir,
                                                          out m_gizmo.SpaceDefault.m_removePos, out m_gizmo.SpaceDefault.m_removeBlock, out m_gizmo.SpaceDefault.m_blockIdInCompound, m_gizmo.SpaceDefault.m_removeBlocksInMultiBlock);
                    }

                    ProfilerShort.BeginNextBlock("addPos");
                    if (addPos)
                    {
                        if (PlacingSmallGridOnLargeStatic)
                        {
                            m_gizmo.SpaceDefault.m_localMatrixAdd.Translation = m_gizmo.SpaceDefault.m_addPosSmallOnLarge.Value;
                        }
                        else
                        {
                            m_gizmo.SpaceDefault.m_localMatrixAdd.Translation = m_gizmo.SpaceDefault.m_addPos;
                        }

                        if (CurrentGrid != null)
                        {
                            m_gizmo.SpaceDefault.m_worldMatrixAdd = m_gizmo.SpaceDefault.m_localMatrixAdd * CurrentGrid.WorldMatrix;
                        }
                        else
                        {
                            m_gizmo.SpaceDefault.m_worldMatrixAdd = m_gizmo.SpaceDefault.m_localMatrixAdd;
                        }
                        Debug.Assert(!m_gizmo.SpaceDefault.m_worldMatrixAdd.IsNan(), "Invalid gizmo matrix");

                        if (m_gizmo.SpaceDefault.m_removeBlock != null)
                        {
                            removePos = true;
                        }
                    }
                    ProfilerShort.End();
                }
            }

            ProfilerShort.Begin("buildingDisabledByCockpit");
            bool buildingDisabledByCockpit = MySession.Static.ControlledEntity != null && MySession.Static.ControlledEntity is MyCockpit && !SpectatorIsBuilding;

            //bool buildingDisabledByCockpit = true;
            if (!buildingDisabledByCockpit)
            {
                if (IsInSymmetrySettingMode)
                {
                    m_gizmo.SpaceDefault.m_continueBuild = null;
                    addPos    = false;
                    removePos = false;

                    if (m_gizmo.SpaceDefault.m_removeBlock != null)
                    {
                        var min = (m_gizmo.SpaceDefault.m_removeBlock.Min * CurrentGrid.GridSize);
                        var max = (m_gizmo.SpaceDefault.m_removeBlock.Max * CurrentGrid.GridSize);

                        Vector3 center = (min + max) * 0.5f;

                        Color color = DrawSymmetryPlane(m_symmetrySettingMode, CurrentGrid, center);

                        DrawSemiTransparentBox(CurrentGrid, m_gizmo.SpaceDefault.m_removeBlock, color.ToVector4());
                    }
                }

                if (CurrentGrid != null && (UseSymmetry || IsInSymmetrySettingMode))
                {
                    if (CurrentGrid.XSymmetryPlane != null)
                    {
                        Vector3 center = CurrentGrid.XSymmetryPlane.Value * CurrentGrid.GridSize;
                        DrawSymmetryPlane(CurrentGrid.XSymmetryOdd ? MySymmetrySettingModeEnum.XPlaneOdd : MySymmetrySettingModeEnum.XPlane, CurrentGrid, center);
                    }

                    if (CurrentGrid.YSymmetryPlane != null)
                    {
                        Vector3 center = CurrentGrid.YSymmetryPlane.Value * CurrentGrid.GridSize;
                        DrawSymmetryPlane(CurrentGrid.YSymmetryOdd ? MySymmetrySettingModeEnum.YPlaneOdd : MySymmetrySettingModeEnum.YPlane, CurrentGrid, center);
                    }

                    if (CurrentGrid.ZSymmetryPlane != null)
                    {
                        Vector3 center = CurrentGrid.ZSymmetryPlane.Value * CurrentGrid.GridSize;
                        DrawSymmetryPlane(CurrentGrid.ZSymmetryOdd ? MySymmetrySettingModeEnum.ZPlaneOdd : MySymmetrySettingModeEnum.ZPlane, CurrentGrid, center);
                    }
                }
            }

            ProfilerShort.BeginNextBlock("UpdateGizmos");
            UpdateGizmos(addPos, removePos, true);

            ProfilerShort.BeginNextBlock("UpdateRenderInstanceData");
            m_renderData.UpdateRenderInstanceData();

            ProfilerShort.BeginNextBlock("CurrentVoxelMap");
            if (DynamicMode || CurrentVoxelMap != null)
            {
                MatrixD  drawMatrix = m_gizmo.SpaceDefault.m_worldMatrixAdd;
                Vector3D rotatedModelOffset;
                Vector3D.TransformNormal(ref CurrentBlockDefinition.ModelOffset, ref drawMatrix, out rotatedModelOffset);

                drawMatrix.Translation = drawMatrix.Translation + rotatedModelOffset;

                m_renderData.UpdateRenderEntitiesData(drawMatrix, UseTransparency);
            }
            else
            {
                m_renderData.UpdateRenderEntitiesData(CurrentGrid != null ? CurrentGrid.WorldMatrix : MatrixD.Identity, UseTransparency);
            }

            ProfilerShort.BeginNextBlock("UpdateBlockInfoHud");
            UpdateBlockInfoHud();

            ProfilerShort.BeginNextBlock("DebugDraw");
            DebugDraw();
            ProfilerShort.End();
        }
        // Returns the final image and copies it to renderTarget if non-null
        private static MyBindableResource DrawGameScene(MyBindableResource renderTarget)
        {
            ProfilerShort.Begin("DrawGameScene");

            PrepareGameScene();

            // todo: shouldn't be necessary
            if (true)
            {
                ProfilerShort.Begin("Clear");
                MyRenderContext.Immediate.Clear();
                MyRenderContext.Immediate.DeviceContext.ClearState();
                ProfilerShort.End();
            }

            Debug.Assert(m_commandLists.Count == 0, "Not all command lists executed last frame!");
            DynamicGeometryRenderer.Render(m_commandLists, true);
            if (MyScene.SeparateGeometry)
            {
                StaticGeometryRenderer.Render(m_commandLists, false);
            }

            SendGlobalOutputMessages();
            ExecuteCommandLists(m_commandLists);
            MyEnvironmentProbe.FinalizeEnvProbes();

            // cleanup context atfer deferred lists
            if (MyRender11.DeferredContextsEnabled)
            {
                ProfilerShort.Begin("Clear2");
                MyRenderContext.Immediate.Clear();
                ProfilerShort.End();
            }

            // todo: shouldn't be necessary
            if (true)
            {
                ProfilerShort.Begin("Clear3");
                MyRenderContext.Immediate.Clear();
                MyRenderContext.Immediate.DeviceContext.ClearState();
                ProfilerShort.End();
            }

            ProfilerShort.Begin("Render decals");
            MyGpuProfiler.IC_BeginBlock("Render decals");
            MyRender11.CopyGbufferToScratch();
            MyScreenDecals.Draw();
            MyGpuProfiler.IC_EndBlock();

            ProfilerShort.BeginNextBlock("Render foliage");
            MyGpuProfiler.IC_BeginBlock("Render foliage");
            m_foliageRenderer.Render();
            MyGpuProfiler.IC_EndBlock();

            ProfilerShort.BeginNextBlock("MySceneMaterials.MoveToGPU");
            MySceneMaterials.MoveToGPU();

            ProfilerShort.BeginNextBlock("Postprocessing");
            MyGpuProfiler.IC_BeginBlock("Postprocessing");
            if (MultisamplingEnabled)
            {
                MyRender11.DeviceContext.ClearDepthStencilView(MyScreenDependants.m_resolvedDepth.m_DSV, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1, 0);
                MyGpuProfiler.IC_BeginBlock("MarkAAEdges");
                MyAAEdgeMarking.Run();
                MyGpuProfiler.IC_EndBlock();
                MyDepthResolve.Run(MyScreenDependants.m_resolvedDepth, MyGBuffer.Main.DepthStencil.Depth);
            }

            if (MyScene.SeparateGeometry)
            {
                MyShadowCascadesPostProcess.Combine(MyShadowCascades.CombineShadowmapArray, DynamicShadows.ShadowCascades, StaticShadows.ShadowCascades);
                DynamicShadows.ShadowCascades.PostProcess(MyRender11.PostProcessedShadows, MyShadowCascades.CombineShadowmapArray);
            }
            else
            {
                DynamicShadows.ShadowCascades.PostProcess(MyRender11.PostProcessedShadows, DynamicShadows.ShadowCascades.CascadeShadowmapArray);
            }

            MyGpuProfiler.IC_BeginBlock("SSAO");
            if (Postprocess.EnableSsao)
            {
                MySSAO.Run(MyScreenDependants.m_ambientOcclusion, MyGBuffer.Main, MyRender11.MultisamplingEnabled ? MyScreenDependants.m_resolvedDepth.Depth : MyGBuffer.Main.DepthStencil.Depth);

                if (MySSAO.UseBlur)
                {
                    MyBlur.Run(MyScreenDependants.m_ambientOcclusion, MyScreenDependants.m_ambientOcclusionHelper, MyScreenDependants.m_ambientOcclusion);
                }
            }
            else
            {
                MyRender11.DeviceContext.ClearRenderTargetView(MyScreenDependants.m_ambientOcclusion.m_RTV, Color4.White);
            }
            MyGpuProfiler.IC_EndBlock();


            MyGpuProfiler.IC_BeginBlock("Lights");
            MyLightRendering.Render();
            MyGpuProfiler.IC_EndBlock();

            ProfilerShort.BeginNextBlock("Billboards");
            MyGpuProfiler.IC_BeginBlock("Billboards");
            if (MyRender11.MultisamplingEnabled)
            {
                MyBillboardRenderer.Render(MyGBuffer.Main.Get(MyGbufferSlot.LBuffer), MyScreenDependants.m_resolvedDepth, MyScreenDependants.m_resolvedDepth.Depth);
            }
            else
            {
                MyBillboardRenderer.Render(MyGBuffer.Main.Get(MyGbufferSlot.LBuffer), MyGBuffer.Main.DepthStencil, MyGBuffer.Main.DepthStencil.Depth);
            }

            MyGpuProfiler.IC_EndBlock();

            ProfilerShort.BeginNextBlock("Atmosphere");
            MyGpuProfiler.IC_BeginBlock("Atmosphere");
            MyAtmosphereRenderer.Render();
            MyGpuProfiler.IC_EndBlock();

            ProfilerShort.BeginNextBlock("Clouds");
            MyGpuProfiler.IC_BeginBlock("Clouds");
            MyCloudRenderer.Render();
            MyGpuProfiler.IC_EndBlock();

            ProfilerShort.End();

            MyGpuProfiler.IC_BeginBlock("Luminance reduction");
            MyBindableResource avgLum = null;

            if (MyRender11.MultisamplingEnabled)
            {
                MyRenderContext.Immediate.DeviceContext.ResolveSubresource(MyGBuffer.Main.Get(MyGbufferSlot.LBuffer).m_resource, 0, MyGBuffer.Main.Get(MyGbufferSlot.LBufferResolved).m_resource, 0, SharpDX.DXGI.Format.R11G11B10_Float);
            }

            if (m_resetEyeAdaptation)
            {
                MyRenderContext.Immediate.DeviceContext.ClearUnorderedAccessView(m_prevLum.m_UAV, Int4.Zero);
                m_resetEyeAdaptation = false;
            }

            avgLum = MyLuminanceAverage.Run(m_reduce0, m_reduce1, MyGBuffer.Main.Get(MyGbufferSlot.LBuffer), m_prevLum);

            MyGpuProfiler.IC_EndBlock();

            if (MyRender11.Settings.DisplayHdrDebug)
            {
                var src = MyGBuffer.Main.Get(MyGbufferSlot.LBuffer) as MyRenderTarget;
                MyHdrDebugTools.CreateHistogram(src.m_SRV, src.m_resolution, src.m_samples.X);
            }


            MyGpuProfiler.IC_BeginBlock("Bloom");
            var bloom = MyBloom.Run(MyGBuffer.Main.Get(MyGbufferSlot.LBuffer), avgLum);

            MyGpuProfiler.IC_EndBlock();

            MyBindableResource tonemapped;

            if (MyRender11.FxaaEnabled)
            {
                tonemapped = m_rgba8_linear;
            }
            else
            {
                tonemapped = m_uav3;
            }

            MyGpuProfiler.IC_BeginBlock("Tone mapping");
            MyToneMapping.Run(tonemapped, MyGBuffer.Main.Get(MyGbufferSlot.LBuffer), avgLum, bloom, Postprocess.EnableTonemapping);
            MyGpuProfiler.IC_EndBlock();

            MyBindableResource renderedImage;

            if (MyRender11.FxaaEnabled)
            {
                MyGpuProfiler.IC_BeginBlock("FXAA");
                MyFXAA.Run(m_rgba8_0.GetView(new MyViewKey {
                    Fmt = SharpDX.DXGI.Format.R8G8B8A8_UNorm, View = MyViewEnum.RtvView
                }), tonemapped);
                MyGpuProfiler.IC_EndBlock();

                renderedImage = m_rgba8_0.GetView(new MyViewKey {
                    Fmt = SharpDX.DXGI.Format.R8G8B8A8_UNorm_SRgb, View = MyViewEnum.SrvView
                });
            }
            else
            {
                //renderedImage = (tonemapped as MyCustomTexture).GetView(new MyViewKey { Fmt = SharpDX.DXGI.Format.R8G8B8A8_UNorm_SRgb, View = MyViewEnum.SrvView });
                renderedImage = tonemapped;
            }
            ProfilerShort.Begin("Outline");
            if (MyOutline.AnyOutline())
            {
                MyOutline.Run();

                MyGpuProfiler.IC_BeginBlock("Outline Blending");
                ProfilerShort.Begin("Outline Blending");
                if (MyRender11.FxaaEnabled)
                {
                    MyBlendTargets.RunWithStencil(
                        m_rgba8_0.GetView(new MyViewKey {
                        Fmt = SharpDX.DXGI.Format.R8G8B8A8_UNorm_SRgb, View = MyViewEnum.RtvView
                    }),
                        MyRender11.m_rgba8_1,
                        MyRender11.BlendAdditive,
                        MyDepthStencilState.TestOutlineMeshStencil,
                        0x40);
                    MyBlendTargets.RunWithStencil(
                        m_rgba8_0.GetView(new MyViewKey {
                        Fmt = SharpDX.DXGI.Format.R8G8B8A8_UNorm_SRgb, View = MyViewEnum.RtvView
                    }),
                        MyRender11.m_rgba8_1,
                        MyRender11.BlendTransparent,
                        MyDepthStencilState.TestHighlightMeshStencil,
                        0x40);
                }
                else
                {
                    if (MyRender11.MultisamplingEnabled)
                    {
                        MyBlendTargets.RunWithPixelStencilTest(tonemapped, MyRender11.m_rgba8_ms, MyRender11.BlendAdditive);
                        MyBlendTargets.RunWithPixelStencilTest(tonemapped, MyRender11.m_rgba8_ms, MyRender11.BlendTransparent, true);
                    }
                    else
                    {
                        MyBlendTargets.RunWithStencil(tonemapped, MyRender11.m_rgba8_1, MyRender11.BlendAdditive, MyDepthStencilState.TestOutlineMeshStencil, 0x40);
                        MyBlendTargets.RunWithStencil(tonemapped, MyRender11.m_rgba8_1, MyRender11.BlendTransparent, MyDepthStencilState.TestHighlightMeshStencil, 0x40);
                    }
                }
                ProfilerShort.End();
                MyGpuProfiler.IC_EndBlock();
            }
            ProfilerShort.End();

            if (renderTarget != null)
            {
                MyCopyToRT.Run(renderTarget, renderedImage);
            }

            if (MyRender11.Settings.DisplayHdrDebug)
            {
                MyHdrDebugTools.DisplayHistogram((renderTarget as IRenderTargetBindable).RTV, (avgLum as IShaderResourceBindable).SRV);
            }

            MyGpuProfiler.IC_EndBlock();
            ProfilerShort.End();
            return(renderedImage);
        }
        public override void Draw()
        {
            ProfilerShort.Begin("base.Draw()");
            base.Draw();

            ProfilerShort.BeginNextBlock("DebugDraw");
            DebugDraw();

            if (BlockCreationIsActivated)
            {
                MyHud.Crosshair.Recenter();
            }

            if (!IsActivated || CurrentBlockDefinition == null)
            {
                this.ClearRenderData();
                ProfilerShort.End();
                return;
            }


            this.DrawGuiIndicators();

            if (!BuildInputValid)
            {
                this.ClearRenderData();
                ProfilerShort.End();
                return;
            }


            ProfilerShort.BeginNextBlock("DrawBuildingStepsCount");
            DrawBuildingStepsCount(m_gizmo.SpaceDefault.m_startBuild, m_gizmo.SpaceDefault.m_startRemove, m_gizmo.SpaceDefault.m_continueBuild, ref m_gizmo.SpaceDefault.m_localMatrixAdd);
            ProfilerShort.End();

            bool addPos    = m_gizmo.SpaceDefault.m_startBuild.HasValue;
            bool removePos = false;

            float gridSize = 0;

            if (CurrentBlockDefinition != null)
            {
                gridSize = MyDefinitionManager.Static.GetCubeSize(CurrentBlockDefinition.CubeSize);
            }

            if (DynamicMode)
            {
                PlaneD   cameraPlane    = new PlaneD(MySector.MainCamera.Position, MySector.MainCamera.UpVector);
                Vector3D projectedPoint = IntersectionStart;
                projectedPoint = cameraPlane.ProjectPoint(ref projectedPoint);
                Vector3D freePlacementIntersectionPoint = projectedPoint + IntersectionDistance * IntersectionDirection;

                if (m_hitInfo != null)
                {
                    freePlacementIntersectionPoint = m_hitInfo.Value.Position;
                }

                addPos = this.CaluclateDynamicModePos(freePlacementIntersectionPoint, IsDynamicOverride());
                MyCoordinateSystem.Static.Visible = false;
            }
            else
            {
                if (m_gizmo.SpaceDefault.m_startBuild == null && m_gizmo.SpaceDefault.m_startRemove == null)
                {
                    if (!FreezeGizmo)
                    {
                        if (CurrentGrid != null)
                        {
                            MyCoordinateSystem.Static.Visible = false;
                            ProfilerShort.Begin("MyCubeBuilder.Draw() - Calculate for grid");
                            addPos = GetAddAndRemovePositions(gridSize, PlacingSmallGridOnLargeStatic,
                                                              out m_gizmo.SpaceDefault.m_addPos, out m_gizmo.SpaceDefault.m_addPosSmallOnLarge,
                                                              out m_gizmo.SpaceDefault.m_addDir,
                                                              out m_gizmo.SpaceDefault.m_removePos, out m_gizmo.SpaceDefault.m_removeBlock,
                                                              out m_gizmo.SpaceDefault.m_blockIdInCompound,
                                                              m_gizmo.SpaceDefault.m_removeBlocksInMultiBlock);

                            if (addPos)
                            {
                                if (PlacingSmallGridOnLargeStatic)
                                {
                                    m_gizmo.SpaceDefault.m_localMatrixAdd.Translation = m_gizmo.SpaceDefault.m_addPosSmallOnLarge.Value;
                                }
                                else
                                {
                                    m_gizmo.SpaceDefault.m_localMatrixAdd.Translation = m_gizmo.SpaceDefault.m_addPos;
                                }

                                m_gizmo.SpaceDefault.m_worldMatrixAdd = m_gizmo.SpaceDefault.m_localMatrixAdd * CurrentGrid.WorldMatrix;

                                var normal = GetSingleMountPointNormal();
                                // Gizmo add dir can be zero in some cases
                                if (normal.HasValue && GridAndBlockValid && m_gizmo.SpaceDefault.m_addDir != Vector3I.Zero)
                                {
                                    m_gizmo.SetupLocalAddMatrix(m_gizmo.SpaceDefault, normal.Value);
                                }
                            }
                            ProfilerShort.End();
                        }
                        else
                        {
                            MyCoordinateSystem.Static.Visible = true;
                            ProfilerShort.Begin("MyCubeBuilder.Draw() - Calculate for voxel");
                            Vector3D localSnappedPos = m_lastLocalCoordSysData.LocalSnappedPos;
                            if (!CubeBuilderDefinition.BuildingSettings.StaticGridAlignToCenter)
                            {
                                localSnappedPos -= new Vector3D(0.5 * gridSize, 0.5 * gridSize, -0.5 * gridSize);
                            }

                            Vector3I gridCoord = Vector3I.Round(localSnappedPos / gridSize);

                            m_gizmo.SpaceDefault.m_addPos = gridCoord;
                            m_gizmo.SpaceDefault.m_localMatrixAdd.Translation = m_lastLocalCoordSysData.LocalSnappedPos;
                            m_gizmo.SpaceDefault.m_worldMatrixAdd             = m_lastLocalCoordSysData.Origin.TransformMatrix;

                            addPos = true;
                            ProfilerShort.End();
                        }
                    }

                    Debug.Assert(!m_gizmo.SpaceDefault.m_worldMatrixAdd.IsNan(), "Invalid gizmo matrix");

                    if (m_gizmo.SpaceDefault.m_removeBlock != null)
                    {
                        removePos = true;
                    }
                }
            }

            ProfilerShort.Begin("buildingDisabledByCockpit");
            bool buildingDisabledByCockpit = MySession.Static.ControlledEntity != null && MySession.Static.ControlledEntity is MyCockpit && !SpectatorIsBuilding;

            if (!buildingDisabledByCockpit)
            {
                if (IsInSymmetrySettingMode)
                {
                    m_gizmo.SpaceDefault.m_continueBuild = null;
                    addPos    = false;
                    removePos = false;

                    if (m_gizmo.SpaceDefault.m_removeBlock != null)
                    {
                        var min = (m_gizmo.SpaceDefault.m_removeBlock.Min * CurrentGrid.GridSize);
                        var max = (m_gizmo.SpaceDefault.m_removeBlock.Max * CurrentGrid.GridSize);

                        Vector3 center = (min + max) * 0.5f;

                        Color color = DrawSymmetryPlane(m_symmetrySettingMode, CurrentGrid, center);

                        DrawSemiTransparentBox(CurrentGrid, m_gizmo.SpaceDefault.m_removeBlock, color.ToVector4());
                    }
                }

                if (CurrentGrid != null && (UseSymmetry || IsInSymmetrySettingMode))
                {
                    if (CurrentGrid.XSymmetryPlane != null)
                    {
                        Vector3 center = CurrentGrid.XSymmetryPlane.Value * CurrentGrid.GridSize;
                        DrawSymmetryPlane(CurrentGrid.XSymmetryOdd ? MySymmetrySettingModeEnum.XPlaneOdd : MySymmetrySettingModeEnum.XPlane, CurrentGrid, center);
                    }

                    if (CurrentGrid.YSymmetryPlane != null)
                    {
                        Vector3 center = CurrentGrid.YSymmetryPlane.Value * CurrentGrid.GridSize;
                        DrawSymmetryPlane(CurrentGrid.YSymmetryOdd ? MySymmetrySettingModeEnum.YPlaneOdd : MySymmetrySettingModeEnum.YPlane, CurrentGrid, center);
                    }

                    if (CurrentGrid.ZSymmetryPlane != null)
                    {
                        Vector3 center = CurrentGrid.ZSymmetryPlane.Value * CurrentGrid.GridSize;
                        DrawSymmetryPlane(CurrentGrid.ZSymmetryOdd ? MySymmetrySettingModeEnum.ZPlaneOdd : MySymmetrySettingModeEnum.ZPlane, CurrentGrid, center);
                    }
                }
            }

            ProfilerShort.BeginNextBlock("UpdateGizmos");
            UpdateGizmos(addPos, removePos, true);

            ProfilerShort.BeginNextBlock("UpdateRenderInstanceData");
            m_renderData.UpdateRenderInstanceData();

            ProfilerShort.BeginNextBlock("CurrentVoxelBase");
            if (CurrentGrid == null || (DynamicMode && CurrentGrid != null))
            {
                MatrixD  drawMatrix = m_gizmo.SpaceDefault.m_worldMatrixAdd;
                Vector3D rotatedModelOffset;
                Vector3D.TransformNormal(ref CurrentBlockDefinition.ModelOffset, ref drawMatrix, out rotatedModelOffset);
                drawMatrix.Translation = drawMatrix.Translation + rotatedModelOffset;

                m_renderData.UpdateRenderEntitiesData(drawMatrix, UseTransparency, CurrentBlockScale);
            }
            else
            {
                m_renderData.UpdateRenderEntitiesData(CurrentGrid.WorldMatrix, UseTransparency);
            }

            ProfilerShort.BeginNextBlock("UpdateBlockInfoHud");
            UpdateBlockInfoHud();
            ProfilerShort.End();
        }
Beispiel #24
0
        public static void UpdateBeforeSimulation()
        {
            if (MySandboxGame.IsGameReady == false)
            {
                return;
            }

            ProfilerShort.Begin("MyEntities.UpdateBeforeSimulation");
            System.Diagnostics.Debug.Assert(MyEntities.UpdateInProgress == false);
            MyEntities.UpdateInProgress = true;

            {
                ProfilerShort.Begin("Before first frame");
                MyEntities.UpdateOnceBeforeFrame();

                ProfilerShort.BeginNextBlock("Each update");
                m_entitiesForUpdate.List.ApplyChanges();
                m_entitiesForUpdate.Update();
                MySimpleProfiler.Begin("Blocks");
                m_entitiesForUpdate.Iterate((x) =>
                {
                    ProfilerShort.Begin(x.GetType().Name);
                    if (x.MarkedForClose == false)
                    {
                        if (ProfilePerBlock)
                        {
                            MyCubeBlock block = x as MyCubeBlock;
                            if (block != null)
                            {
                                MySimpleProfiler.Begin(block.DefinitionDisplayNameText + (ProfilePerGrid ? $" - {block.CubeGrid.DisplayName}" : string.Empty));
                                if (ProfilePerGrid)
                                {
                                    MySimpleProfiler.Begin("&&GRID&&" + block.CubeGrid.DisplayName);
                                }
                            }
                        }
                        if (ProfilePerGrid)
                        {
                            MyCubeGrid grid = x as MyCubeGrid;
                            if (grid != null)
                            {
                                MySimpleProfiler.Begin("&&GRID&&" + grid.DisplayName);
                            }
                        }

                        x.UpdateBeforeSimulation();

                        if (ProfilePerBlock)
                        {
                            MyCubeBlock block = x as MyCubeBlock;
                            if (block != null)
                            {
                                MySimpleProfiler.End(block.DefinitionDisplayNameText + (ProfilePerGrid ? $" - {block.CubeGrid.DisplayName}" : string.Empty));
                                if (ProfilePerGrid)
                                {
                                    MySimpleProfiler.End("&&GRID&&" + block.CubeGrid.DisplayName);
                                }
                            }
                        }
                        if (ProfilePerGrid)
                        {
                            MyCubeGrid grid = x as MyCubeGrid;
                            if (grid != null)
                            {
                                MySimpleProfiler.End("&&GRID&&" + grid.DisplayName);
                            }
                        }
                    }
                    ProfilerShort.End();
                });

                ProfilerShort.BeginNextBlock("10th update");
                m_entitiesForUpdate10.List.ApplyChanges();
                m_entitiesForUpdate10.Update();
                m_entitiesForUpdate10.Iterate((x) =>
                {
                    ProfilerShort.Begin(x.GetType().Name);
                    if (x.MarkedForClose == false)
                    {
                        if (ProfilePerBlock)
                        {
                            MyCubeBlock block = x as MyCubeBlock;
                            if (block != null)
                            {
                                MySimpleProfiler.Begin(block.DefinitionDisplayNameText + (ProfilePerGrid ? $" - {block.CubeGrid.DisplayName}" : string.Empty));
                                if (ProfilePerGrid)
                                {
                                    MySimpleProfiler.Begin("&&GRID&&" + block.CubeGrid.DisplayName);
                                }
                            }
                        }
                        if (ProfilePerGrid)
                        {
                            MyCubeGrid grid = x as MyCubeGrid;
                            if (grid != null)
                            {
                                MySimpleProfiler.Begin("&&GRID&&" + grid.DisplayName);
                            }
                        }

                        x.UpdateBeforeSimulation10();

                        if (ProfilePerBlock)
                        {
                            MyCubeBlock block = x as MyCubeBlock;
                            if (block != null)
                            {
                                MySimpleProfiler.End(block.DefinitionDisplayNameText + (ProfilePerGrid ? $" - {block.CubeGrid.DisplayName}" : string.Empty));
                                if (ProfilePerGrid)
                                {
                                    MySimpleProfiler.End("&&GRID&&" + block.CubeGrid.DisplayName);
                                }
                            }
                        }
                        if (ProfilePerGrid)
                        {
                            MyCubeGrid grid = x as MyCubeGrid;
                            if (grid != null)
                            {
                                MySimpleProfiler.End("&&GRID&&" + grid.DisplayName);
                            }
                        }
                    }
                    ProfilerShort.End();
                });


                ProfilerShort.BeginNextBlock("100th update");
                m_entitiesForUpdate100.List.ApplyChanges();
                m_entitiesForUpdate100.Update();
                m_entitiesForUpdate100.Iterate((x) =>
                {
                    ProfilerShort.Begin(x.GetType().Name);
                    if (x.MarkedForClose == false)
                    {
                        if (ProfilePerBlock)
                        {
                            MyCubeBlock block = x as MyCubeBlock;
                            if (block != null)
                            {
                                MySimpleProfiler.Begin(block.DefinitionDisplayNameText + (ProfilePerGrid ? $" - {block.CubeGrid.DisplayName}" : string.Empty));
                                if (ProfilePerGrid)
                                {
                                    MySimpleProfiler.Begin("&&GRID&&" + block.CubeGrid.DisplayName);
                                }
                            }
                        }
                        if (ProfilePerGrid)
                        {
                            MyCubeGrid grid = x as MyCubeGrid;
                            if (grid != null)
                            {
                                MySimpleProfiler.Begin("&&GRID&&" + grid.DisplayName);
                            }
                        }

                        x.UpdateBeforeSimulation100();

                        if (ProfilePerBlock)
                        {
                            MyCubeBlock block = x as MyCubeBlock;
                            if (block != null)
                            {
                                MySimpleProfiler.End(block.DefinitionDisplayNameText + (ProfilePerGrid ? $" - {block.CubeGrid.DisplayName}" : string.Empty));
                                if (ProfilePerGrid)
                                {
                                    MySimpleProfiler.End("&&GRID&&" + block.CubeGrid.DisplayName);
                                }
                            }
                        }
                        if (ProfilePerGrid)
                        {
                            MyCubeGrid grid = x as MyCubeGrid;
                            if (grid != null)
                            {
                                MySimpleProfiler.Begin("&&GRID&&" + grid.DisplayName);
                            }
                        }
                    }
                    ProfilerShort.End();
                });

                ProfilerShort.End();
            }
            MySimpleProfiler.End("Blocks");

            MyEntities.UpdateInProgress = false;

            ProfilerShort.End();
        }
Beispiel #25
0
        private void SortJobs()
        {
            ProfilerShort.Begin("SortJobs");
            m_sortedJobs.Lock();
            var list  = m_sortedJobs.List;
            int front = 0;
            int mid   = 0;
            int back  = list.Count - 1;

            ProfilerShort.Begin("FirstPAss");
            //for (int i = 0; i <= back; i++)
            //{
            //    var p = list[i].Priority;
            //    if (p == int.MaxValue)
            //        list.Swap(i, back--);
            //}
            ProfilerShort.BeginNextBlock("SecondPass");

            int   rnd = 0;
            int   min = int.MaxValue;
            float avg = 0;

            if (list.Count > 100)
            {
                for (int i = 0; i < 100; i++)
                {
                    int x = VRage.Library.Utils.MyRandom.Instance.Next() % back;
                    var p = list[x].Priority;
                    if (p > 1 && p < min)
                    {
                        min = p;
                    }
                }
            }
            //avg *= 0.1f;
            min += 100;
            min  = Math.Max(1, min);
            for (int i = 0; i < list.Count; i++)
            {
                if (list[i].IsCanceled)
                {
                    list.RemoveAtFast(i--);
                    continue;
                }
                var p = list[i].Priority;
                if (p <= min)
                {
                    if (p <= 1)
                    {
                        list.Swap(i, front++);
                    }
                    list.Swap(i, mid++);
                }
            }
            ProfilerShort.BeginNextBlock("Sort");
            if (mid < list.Count)
            {
                list.Sort(front, mid - front, m_comparer);
            }
            ProfilerShort.End(mid - front);
            m_sortedJobs.Unlock();
            ProfilerShort.End();
        }
Beispiel #26
0
        internal void UpdateAfterSimulation10()
        {
            ProfilerShort.Begin("Voxel Physics Prediction");
            UpdateRigidBodyShape();

            // Apply prediction based on movement of nearby entities.
            foreach (var entity in m_nearbyEntities)
            {
                Debug.Assert(m_bodiesInitialized, "Voxel map does not have physics!");

                bool lod0 = entity is MyCharacter;

                if (!lod0)
                {
                    var body = entity.Physics as MyPhysicsBody;

                    if (body != null && body.RigidBody != null &&
                        (body.RigidBody.Layer == MyPhysics.CollisionLayers.FloatingObjectCollisionLayer || body.RigidBody.Layer == MyPhysics.CollisionLayers.LightFloatingObjectCollisionLayer))
                    {
                        lod0 = true;
                    }
                }

                if (!(entity is MyCubeGrid) && !lod0)
                {
                    continue;
                }

                if (entity.MarkedForClose)
                {
                    continue;
                }

                if (entity.Physics == null || entity.Physics.LinearVelocity.Length() < 2f)
                {
                    continue;
                }

                BoundingBoxD aabb;
                GetPrediction(entity, out aabb);
                if (!aabb.Intersects(m_voxelMap.PositionComp.WorldAABB))
                {
                    continue;
                }

                int   lod     = lod0 ? 0 : 1;
                float lodSize = 1 << lod;

                Vector3I min, max;
                Vector3D localPositionMin, localPositionMax;

                aabb = aabb.Transform(m_voxelMap.PositionComp.WorldMatrixInvScaled);

                aabb.Translate(m_voxelMap.SizeInMetresHalf);

                localPositionMax = aabb.Max;
                localPositionMin = aabb.Min;



                MyVoxelCoordSystems.LocalPositionToVoxelCoord(ref localPositionMin, out min);
                MyVoxelCoordSystems.LocalPositionToVoxelCoord(ref localPositionMax, out max);
                m_voxelMap.Storage.ClampVoxelCoord(ref min);
                m_voxelMap.Storage.ClampVoxelCoord(ref max);
                MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref min, out min);
                MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref max, out max);
                min >>= lod;
                max >>= lod;

                {
                    var size = (max - min + 1).Size;
                    if (size >= m_cellsToGenerateBuffer.Length)
                    {
                        m_cellsToGenerateBuffer = new Vector3I[MathHelper.GetNearestBiggerPowerOfTwo(size)];
                    }
                }
                var shape = GetShape(lod);

                Debug.Assert(shape.Base.IsValid);
                int requiredCellsCount = shape.GetMissingCellsInRange(ref min, ref max, m_cellsToGenerateBuffer);

                if (requiredCellsCount == 0)
                {
                    continue;
                }

                var bb = new BoundingBox(min * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES * lodSize, (max + 1) * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES * lodSize);
                bb.Translate(m_voxelMap.StorageMin);
                ProfilerShort.Begin("Storage Intersect");
                if (requiredCellsCount > 0)
                {
                    if (m_voxelMap.Storage.Intersect(ref bb, false) == ContainmentType.Intersects)
                    {
                        ProfilerShort.BeginNextBlock("Set Empty Shapes");
                        for (int i = 0; i < requiredCellsCount; ++i)
                        {
                            var cell = m_cellsToGenerateBuffer[i];
                            m_workTracker.Cancel(new MyCellCoord(lod, cell));
                            shape.SetChild(cell.X, cell.Y, cell.Z, (HkBvCompressedMeshShape)HkShape.Empty, HkReferencePolicy.TakeOwnership);
                        }
                    }
                    else
                    {
                        /*if (MyVoxelDebugInputComponent.PhysicsComponent.Static != null)
                         *  MyVoxelDebugInputComponent.PhysicsComponent.Static.Add(m_voxelMap.WorldMatrix, bb, new Vector4I(m_cellsToGenerateBuffer[0], lod), m_voxelMap);*/

                        ProfilerShort.End();
                        continue;
                    }
                }

                ProfilerShort.BeginNextBlock("Start Jobs");
                for (int i = 0; i < requiredCellsCount; ++i)
                {
                    if (m_workTracker.Exists(new MyCellCoord(lod, m_cellsToGenerateBuffer[i])))
                    {
                        continue;
                    }

                    MyPrecalcJobPhysicsPrefetch.Start(new MyPrecalcJobPhysicsPrefetch.Args
                    {
                        TargetPhysics = this,
                        Tracker       = m_workTracker,
                        GeometryCell  = new MyCellCoord(lod, m_cellsToGenerateBuffer[i]),
                        Storage       = m_voxelMap.Storage
                    });
                }
                ProfilerShort.End();
            }

            if (m_bodiesInitialized)
            {
                CheckAndDiscardShapes();
            }
            ProfilerShort.End();
        }
Beispiel #27
0
        internal void RecordCommandLists(MyCullQuery processedCullQuery, Queue <CommandList> outCommandLists)
        {
            ProfilerShort.Begin("PrepareWork");

            ProfilerShort.Begin("Init");
            Debug.Assert(m_workList.Count == 0, "Work list not cleared after use!");

            foreach (List <MyRenderCullResultFlat> cullResults in m_passElements)
            {
                cullResults.Clear();
                m_sortListPool.Deallocate(cullResults);
            }
            m_passElements.Clear();
            m_passElements2.Clear();

            for (int renderPassIndex = 0; renderPassIndex < processedCullQuery.Size; ++renderPassIndex)
            {
                if (!MyRender11.DeferredContextsEnabled)
                {
                    processedCullQuery.RenderingPasses[renderPassIndex].SetImmediate(true);
                }

                m_passElements.Add(m_sortListPool.Allocate());
                m_passElements2.Add(null);
            }

            ProfilerShort.BeginNextBlock("Flatten");
            for (int i = 0; i < processedCullQuery.Size; ++i)
            {
                m_affectedQueueIds.SetSize(0);
                var frustumQuery = processedCullQuery.FrustumCullQueries[i];

                for (int renderPassIndex = 0; renderPassIndex < processedCullQuery.Size; renderPassIndex++)
                {
                    if ((processedCullQuery.RenderingPasses[renderPassIndex].ProcessingMask & frustumQuery.Bitmask) > 0)
                    {
                        m_affectedQueueIds.Add(renderPassIndex);
                    }
                }

                var cullProxies = frustumQuery.List;
                var queryType   = frustumQuery.Type;

                foreach (MyCullProxy cullProxy in cullProxies)
                {
                    var renderableProxies = cullProxy.RenderableProxies;
                    if (renderableProxies == null)
                    {
                        continue;
                    }

                    for (int proxyIndex = 0; proxyIndex < renderableProxies.Length; ++proxyIndex)
                    {
                        var flag = renderableProxies[proxyIndex].DrawSubmesh.Flags;
                        if (queryType == MyFrustumEnum.MainFrustum)
                        {
                            if ((flag & MyDrawSubmesh.MySubmeshFlags.Gbuffer) != MyDrawSubmesh.MySubmeshFlags.Gbuffer)
                            {
                                continue;
                            }
                        }
                        else if (queryType == MyFrustumEnum.ShadowCascade || queryType == MyFrustumEnum.ShadowProjection)
                        {
                            if ((flag & MyDrawSubmesh.MySubmeshFlags.Depth) != MyDrawSubmesh.MySubmeshFlags.Depth)
                            {
                                continue;
                            }
                        }

                        MyRenderableProxy renderableProxy = renderableProxies[proxyIndex];
                        ulong             sortKey         = cullProxy.SortingKeys[proxyIndex];

                        for (int queueIndex = 0; queueIndex < m_affectedQueueIds.Count; ++queueIndex)
                        {
                            var queueId = m_affectedQueueIds[queueIndex];
                            var item    = new MyRenderCullResultFlat
                            {
                                SortKey     = sortKey,
                                RenderProxy = renderableProxy,
                            };

                            m_passElements[queueId].Add(item);
                        }
                    }
                }

                // proxy 2
                var list2 = frustumQuery.List2;

                // flatten and sort
                m_flattenedKeys.SetSize(0);
                m_indirectionList.SetSize(0);
                m_location.SetSize(0);

                int indirectionCounter = 0;
                for (int list2Index = 0; list2Index < list2.Count; ++list2Index)
                {
                    for (int sortKeyIndex = 0; sortKeyIndex < list2[list2Index].SortingKeys.Length; sortKeyIndex++)
                    {
                        m_flattenedKeys.Add(list2[list2Index].SortingKeys[sortKeyIndex]);
                        m_indirectionList.Add(indirectionCounter++);
                        m_location.Add(MyTuple.Create(list2Index, sortKeyIndex));
                    }
                }

                MyRenderableProxy_2[] flattenedProxies = null;

                if (indirectionCounter > 0)
                {
                    flattenedProxies = new MyRenderableProxy_2[indirectionCounter];
                }

                m_sortingKeysComparer.Values = m_flattenedKeys;
                m_indirectionList.Sort(0, m_indirectionList.Count, m_sortingKeysComparer);

                if (flattenedProxies != null)
                {
                    for (int e = 0; e < indirectionCounter; e++)
                    {
                        var l = m_location[m_indirectionList[e]];
                        flattenedProxies[e] = list2[l.Item1].Proxies[l.Item2];
                    }
                }

                for (int l = 0; l < m_affectedQueueIds.Count; l++)
                {
                    m_passElements2[m_affectedQueueIds[l]] = flattenedProxies;
                }
            }
            ProfilerShort.BeginNextBlock("Sort");
            foreach (var flatCullResults in m_passElements)
            {
                foreach (MyRenderCullResultFlat element in flatCullResults)
                {
                    List <MyRenderCullResultFlat> sortList;
                    if (m_tmpSortListDictionary.TryGetValue(element.SortKey, out sortList))
                    {
                        sortList.Add(element);
                    }
                    else
                    {
                        sortList = m_sortListPool.Allocate();
                        sortList.Add(element);
                        m_tmpSortListDictionary.Add(element.SortKey, sortList);
                    }
                }
                flatCullResults.Clear();
                foreach (var sortList in m_tmpSortListDictionary.Values)
                {
                    flatCullResults.AddList(sortList);
                    sortList.SetSize(0);
                    m_sortListPool.Deallocate(sortList);
                }
                m_tmpSortListDictionary.Clear();
            }

            int jobsNum = GetRenderingThreadsNum();

            // always amortize this path
            ProfilerShort.BeginNextBlock("WorkAmortization");

            //passElements.RemoveAll(x => x.Count == 0);

            int workSum = 0;

            foreach (var list in m_passElements)
            {
                workSum += list.Count;
            }

            int batchWork = (workSum + jobsNum - 1) / jobsNum;

            Debug.Assert(m_subworks.Count == 0);

            int work = 0;

            for (int passElementIndex = 0; passElementIndex < m_passElements.Count; ++passElementIndex)
            {
                var flatCullResults = m_passElements[passElementIndex];
                if (flatCullResults.Count == 0)
                {
                    MyObjectPoolManager.Deallocate(processedCullQuery.RenderingPasses[passElementIndex]);
                    processedCullQuery.RenderingPasses[passElementIndex] = null;
                    if (m_passElements2[passElementIndex] == null || m_passElements2[passElementIndex].Length == 0)
                    {
                        continue;
                    }
                }

                if (processedCullQuery.RenderingPasses[passElementIndex] == null)
                {
                    continue;
                }

                int passBegin = 0;

                if (m_passElements2[passElementIndex] != null && m_passElements2[passElementIndex].Length > 0)
                {
                    m_subworks.Add(new MyRenderingWorkItem
                    {
                        Pass  = processedCullQuery.RenderingPasses[passElementIndex].Fork(),
                        List2 = m_passElements2[passElementIndex]
                    });
                }

                while (passBegin < flatCullResults.Count)
                {
                    int toTake = Math.Min(flatCullResults.Count - passBegin, batchWork - work);

                    var workItem = new MyRenderingWorkItem
                    {
                        Renderables = flatCullResults,
                        Begin       = passBegin,
                        End         = passBegin + toTake
                    };

                    if (toTake < flatCullResults.Count && workItem.End != workItem.Renderables.Count)
                    {
                        workItem.Pass = processedCullQuery.RenderingPasses[passElementIndex].Fork();
                    }
                    else
                    {
                        workItem.Pass = processedCullQuery.RenderingPasses[passElementIndex];
                        processedCullQuery.RenderingPasses[passElementIndex] = null;    // Consume the pass so it doesn't get cleaned up later with the cull query, but instead with the work item
                    }

                    m_subworks.Add(workItem);

                    passBegin += toTake;
                    work      += toTake;

                    Debug.Assert(work <= batchWork);
                    if (work != batchWork)
                    {
                        continue;
                    }

                    if (MyRender11.DeferredContextsEnabled)
                    {
                        var renderWork = MyObjectPoolManager.Allocate <MyRenderingWorkRecordCommands>();
                        renderWork.Init(MyRenderContextPool.AcquireRC(), m_subworks);
                        m_workList.Add(renderWork);
                    }
                    else
                    {
                        var renderWork = MyObjectPoolManager.Allocate <MyRenderingWorkRecordCommands>();
                        renderWork.Init(m_subworks);
                        m_workList.Add(renderWork);
                    }

                    work = 0;

                    m_subworks.Clear();
                }
            }
            if (m_subworks.Count > 0)
            {
                if (MyRender11.DeferredContextsEnabled)
                {
                    var renderWork = MyObjectPoolManager.Allocate <MyRenderingWorkRecordCommands>();
                    renderWork.Init(MyRenderContextPool.AcquireRC(), m_subworks);
                    m_workList.Add(renderWork);
                }
                else
                {
                    var renderWork = MyObjectPoolManager.Allocate <MyRenderingWorkRecordCommands>();
                    renderWork.Init(m_subworks);
                    m_workList.Add(renderWork);
                }
                m_subworks.Clear();
            }

            ProfilerShort.End();

            ProfilerShort.End();

            DoRecordingWork(outCommandLists);

            foreach (var renderWork in m_workList)
            {
                MyObjectPoolManager.Deallocate(renderWork);
            }
            m_workList.Clear();
        }