예제 #1
0
        internal void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged, int lod)
        {
            MyPrecalcComponent.AssertUpdateThread();

            // No physics there ever was so we don't care.
            if (!m_bodiesInitialized)
            {
                return;
            }

            if (m_queueInvalidation)
            {
                if (m_queuedRange.Max.X < 0)
                {
                    m_queuedRange = new BoundingBoxI(minVoxelChanged, maxVoxelChanged);
                }
                else
                {
                    var bb = new BoundingBoxI(minVoxelChanged, maxVoxelChanged);
                    m_queuedRange.Include(ref bb);
                }
                return;
            }

            ProfilerShort.Begin("MyVoxelPhysicsBody.InvalidateRange");
            minVoxelChanged -= 1; // MyPrecalcComponent.InvalidatedRangeInflate;
            maxVoxelChanged += 1; //MyPrecalcComponent.InvalidatedRangeInflate;
            m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged);
            m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged);

            Vector3I minCellChanged, maxCellChanged;

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCellChanged);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCellChanged);

            Vector3I minCellChangedVoxelMap, maxCellChangedVoxelMap;

            minCellChangedVoxelMap = (minCellChanged - m_cellsOffset) >> lod;
            maxCellChangedVoxelMap = (maxCellChanged - m_cellsOffset) >> lod;

            var maxCell = m_voxelMap.Size - 1;

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxCell, out maxCell);
            maxCell >>= lod;
            Vector3I.Min(ref maxCellChangedVoxelMap, ref maxCell, out maxCellChangedVoxelMap);

            Debug.Assert(RigidBody != null, "RigidBody in voxel physics is null! This must not happen.");

            var rb = GetRigidBody(lod);

            Debug.Assert(rb != null, "RigidBody in voxel physics is null! This must not happen.");

            if (rb != null)
            {
                HkUniformGridShape shape = (HkUniformGridShape)rb.GetShape();
                Debug.Assert(shape.Base.IsValid);


                var numCells = (maxCellChangedVoxelMap - minCellChangedVoxelMap + 1).Size;
                if (numCells >= m_cellsToGenerateBuffer.Length)
                {
                    m_cellsToGenerateBuffer = new Vector3I[MathHelper.GetNearestBiggerPowerOfTwo(numCells)];
                }

                var tmpBuffer    = m_cellsToGenerateBuffer;
                int invalidCount = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer);
                Debug.Assert(invalidCount <= tmpBuffer.Length);

                //if (numCells <= 8)
                //shape.InvalidateRangeImmediate(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap);

                Debug.Assert(invalidCount <= tmpBuffer.Length);
                for (int i = 0; i < invalidCount; i++)
                {
                    InvalidCells[lod].Add(tmpBuffer[i]);
                }

                if (RunningBatchTask[lod] == null && InvalidCells[lod].Count != 0)
                {
                    MyPrecalcComponent.PhysicsWithInvalidCells.Add(this);
                }
            }

            if (minCellChangedVoxelMap == Vector3I.Zero && maxCellChangedVoxelMap == maxCell)
            {
                m_workTracker.CancelAll();
            }
            else
            {
                var cell = minCellChanged;
                for (var it = new Vector3I_RangeIterator(ref minCellChanged, ref maxCellChanged);
                     it.IsValid(); it.GetNext(out cell))
                {
                    m_workTracker.Cancel(new MyCellCoord(lod, cell));
                }
            }

            m_needsShapeUpdate = true;

            ProfilerShort.End();

            m_voxelMap.RaisePhysicsChanged();
        }
        public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck = false)
        {
            // change range so normal can be computed at edges (expand by 1 in all directions)
            voxelStart -= 1;
            voxelEnd   += 1;

            if (storage == null)
            {
                return(null);
            }

            using (storage.Pin())
            {
                if (storage.Closed)
                {
                    return(null);
                }

                MyVoxelRequestFlags request = MyVoxelRequestFlags.ContentChecked; // | (doNotCheck ? MyVoxelRequestFlags.DoNotCheck : 0);

                bool readAmbient = false;

                if (generateMaterials && storage.DataProvider != null && storage.DataProvider.ProvidesAmbient)
                {
                    readAmbient = true;
                }

                m_cache.Resize(voxelStart, voxelEnd);
                if (readAmbient)
                {
                    m_cache.StoreOcclusion = true;
                }

                storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd, ref request);

                if (request.HasFlag(MyVoxelRequestFlags.EmptyContent) || request.HasFlag(MyVoxelRequestFlags.FullContent) ||
                    (!request.HasFlag(MyVoxelRequestFlags.ContentChecked) && !m_cache.ContainsIsoSurface()))
                {
                    return(null);
                }

                var    center           = (storage.Size / 2) * MyVoxelConstants.VOXEL_SIZE_IN_METRES;
                var    voxelSize        = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod);
                var    vertexCellOffset = voxelStart - AffectedRangeOffset;
                double numCellsHalf     = 0.5 * (m_cache.Size3D.X - 3);
                var    posOffset        = ((Vector3D)vertexCellOffset + numCellsHalf) * (double)voxelSize;

                if (generateMaterials)
                {
                    // 255 is the new black
                    m_cache.ClearMaterials(255);
                }

                if (readAmbient)
                {
                    m_cache.Clear(MyStorageDataTypeEnum.Occlusion, 0);
                }

                IsoMesher mesher = new IsoMesher();
                ProfilerShort.Begin("Dual Contouring");
                unsafe
                {
                    fixed(byte *content = m_cache[MyStorageDataTypeEnum.Content])
                    fixed(byte *material = m_cache[MyStorageDataTypeEnum.Material])
                    {
                        var size3d = m_cache.Size3D;

                        Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z);
                        mesher.Calculate(size3d.X, content, material, m_buffer, useAmbient, posOffset - center);
                    }
                }
                ProfilerShort.End();

                if (generateMaterials)
                {
                    request = 0;

                    request |= MyVoxelRequestFlags.SurfaceMaterial;
                    request |= MyVoxelRequestFlags.OneMaterial;

                    var req = readAmbient ? MyStorageDataTypeFlags.Material | MyStorageDataTypeFlags.Occlusion : MyStorageDataTypeFlags.Material;

                    storage.ReadRange(m_cache, req, lod, ref voxelStart, ref voxelEnd, ref request);

                    FixCacheMaterial(voxelStart, voxelEnd);
                    unsafe
                    {
                        fixed(byte *content = m_cache[MyStorageDataTypeEnum.Content])
                        fixed(byte *material = m_cache[MyStorageDataTypeEnum.Material])
                        {
                            int materialOverride = request.HasFlag(MyVoxelRequestFlags.OneMaterial) ? m_cache.Material(0) : -1;
                            var size3d           = m_cache.Size3D;

                            Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z);

                            if (readAmbient)
                                fixed(byte *ambient = m_cache[MyStorageDataTypeEnum.Occlusion])
                                mesher.CalculateMaterials(size3d.X, content, material, ambient, materialOverride);
                            else
                            {
                                mesher.CalculateMaterials(size3d.X, content, material, null, materialOverride);
                            }
                        }
                    }
                }
                else
                {
                    m_cache.ClearMaterials(0);
                }

                mesher.Finish(m_buffer);

                if (m_buffer.VerticesCount == 0 || m_buffer.Triangles.Count == 0)
                {
                    return(null);
                }

                ProfilerShort.Begin("Geometry post-processing");
                {
                    var positions   = m_buffer.Positions.GetInternalArray();
                    var vertexCells = m_buffer.Cells.GetInternalArray();
                    for (int i = 0; i < m_buffer.VerticesCount; i++)
                    {
                        Debug.Assert(positions[i].IsInsideInclusive(ref Vector3.MinusOne, ref Vector3.One));
                        vertexCells[i] += vertexCellOffset;
                        Debug.Assert(vertexCells[i].IsInsideInclusive(voxelStart + 1, voxelEnd - 1));
                    }

                    m_buffer.PositionOffset = posOffset;
                    m_buffer.PositionScale  = new Vector3((float)(numCellsHalf * voxelSize));
                    m_buffer.CellStart      = voxelStart + 1;
                    m_buffer.CellEnd        = voxelEnd - 1;
                }
                ProfilerShort.End();

                // Replace filled mesh with new one.
                // This way prevents allocation of meshes which then end up empty.
                var buffer = m_buffer;
                m_buffer = new MyIsoMesh();
                return(buffer);
            }
        }
        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 (!(block is MyThrust) && 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();
        }
        protected override void DoDetection(bool useHead)
        {
            ProfilerShort.Begin("DoDetection");
            if (Character == MySession.Static.ControlledEntity)
            {
                MyHud.SelectedObjectHighlight.RemoveHighlight();
            }

            var head    = Character.GetHeadMatrix(false);
            var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head)

            Vector3D from;
            Vector3D dir;

            if (!useHead)
            {
                //Ondrej version
                var cameraMatrix = MySector.MainCamera.WorldMatrix;
                dir  = cameraMatrix.Forward;
                from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir);
            }
            else
            {
                //Petr version
                dir  = head.Forward;
                from = headPos;
            }

            Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE;

            StartPosition = from;
            LineD intersectionLine = new LineD(from, to);

            // Processing of hit entities
            var  geometryHit  = MyEntities.GetIntersectionWithLine(ref intersectionLine, null, null, ignoreFloatingObjects: false);
            bool hasUseObject = false;

            if (geometryHit.HasValue)
            {
                var hitEntity = geometryHit.Value.Entity;

                // Cube Grids are special case
                var cubeGrid = hitEntity as MyCubeGrid;
                if (cubeGrid != null)
                {
                    // For hit cube grids get the fat hit fatblock instead.
                    var slimBlock = cubeGrid.GetTargetedBlock(geometryHit.Value.IntersectionPointInWorldSpace);
                    if (slimBlock != null && slimBlock.FatBlock != null)
                    {
                        hitEntity = slimBlock.FatBlock;
                    }
                }

                m_hitUseComponents.Clear();
                var hitUseObject = hitEntity as IMyUseObject;
                // Retrive all above use components from parent structure. (Because of subParts)
                GetUseComponentsFromParentStructure(hitEntity, m_hitUseComponents);
                // Check for UseObjects and entities with UseObjectComponentBase.
                // Assuming that entity cannot be IMyUseObject and have UseObjectComponentBase in hierarchy
                // at the same time.
                if (hitUseObject != null || m_hitUseComponents.Count > 0)
                {
                    if (m_hitUseComponents.Count > 0)
                    {
                        // Process the valid hit entity
                        var    closestDetectorDistance       = float.MaxValue;
                        double physicalHitDistance           = Vector3D.Distance(from, geometryHit.Value.IntersectionPointInWorldSpace);
                        MyUseObjectsComponentBase hitUseComp = null;
                        // Evaluate the set of found detectors and try to find the closest one
                        foreach (var hitUseComponent in m_hitUseComponents)
                        {
                            float detectorDistance;
                            var   interactive = hitUseComponent.RaycastDetectors(from, to, out detectorDistance);
                            detectorDistance *= MyConstants.DEFAULT_INTERACTIVE_DISTANCE;
                            if (Math.Abs(detectorDistance) < Math.Abs(closestDetectorDistance) &&
                                (detectorDistance < physicalHitDistance)) // Remove to fix the problem with picking through physic bodies,
                            {                                             // but will introduce new problem with detectors inside physic bodies.
                                closestDetectorDistance = detectorDistance;
                                hitUseComp   = hitUseComponent;
                                hitEntity    = hitUseComponent.Entity;
                                hitUseObject = interactive;
                            }
                        }

                        // Detector found
                        if (hitUseComp != null)
                        {
                            // Process successful hit with results
                            var detectorPhysics = hitUseComp.DetectorPhysics;
                            HitMaterial    = detectorPhysics.GetMaterialAt(HitPosition);
                            HitBody        = geometryHit.Value.Entity.Physics.RigidBody;
                            HitPosition    = geometryHit.Value.IntersectionPointInWorldSpace;
                            DetectedEntity = hitEntity;
                        }
                    }
                    else
                    {
                        // Case for hitting IMyUseObject already before even looking for UseComponent.
                        // Floating object case.
                        HitMaterial = hitEntity.Physics.GetMaterialAt(HitPosition);
                        HitBody     = hitEntity.Physics.RigidBody;
                    }

                    // General logic for processing both cases.
                    if (hitUseObject != null)
                    {
                        HitPosition    = geometryHit.Value.IntersectionPointInWorldSpace;
                        DetectedEntity = hitEntity;

                        if (UseObject != null && UseObject != hitEntity && UseObject != hitUseObject)
                        {
                            UseObject.OnSelectionLost();
                        }

                        if (Character == MySession.Static.ControlledEntity && hitUseObject.SupportedActions != UseActionEnum.None)
                        {
                            HandleInteractiveObject(hitUseObject);

                            UseObject    = hitUseObject;
                            hasUseObject = true;
                        }
                    }
                }
            }

            if (!hasUseObject)
            {
                if (UseObject != null)
                {
                    UseObject.OnSelectionLost();
                }

                UseObject = null;
            }

            ProfilerShort.End();
        }
        void IWork.DoWork(WorkData workData = null)
        {
            ProfilerShort.Begin("MyDepositQuery.DoWork");
            try
            {
                var cache = Cache;
                cache.Resize(new Vector3I(MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS));
                var min = m_args.Cell << MyOreDetectorComponent.CELL_SIZE_IN_VOXELS_BITS;
                var max = min + (MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS - 1);

                var storage = m_args.VoxelMap.Storage;
                if (storage == null || storage.Closed)
                {
                    return; // voxel map was probably closed in the meantime.
                }
                using (storage.Pin())
                {
                    storage.ReadRange(cache, MyStorageDataTypeFlags.Content, MyOreDetectorComponent.QUERY_LOD, ref min, ref max);
                    if (!cache.ContainsVoxelsAboveIsoLevel())
                    {
                        return;
                    }

                    storage.ReadRange(cache, MyStorageDataTypeFlags.Material, MyOreDetectorComponent.QUERY_LOD, ref min, ref max);
                }

                var      materialData = MaterialData;
                Vector3I c;
                for (c.Z = 0; c.Z < MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS; ++c.Z)
                {
                    for (c.Y = 0; c.Y < MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS; ++c.Y)
                    {
                        for (c.X = 0; c.X < MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS; ++c.X)
                        {
                            int i = cache.ComputeLinear(ref c);
                            if (cache.Content(i) > MyVoxelConstants.VOXEL_ISO_LEVEL)
                            {
                                const float VOXEL_SIZE      = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << MyOreDetectorComponent.QUERY_LOD);
                                const float VOXEL_SIZE_HALF = VOXEL_SIZE * 0.5f;
                                var         material        = cache.Material(i);
                                Vector3D    localPos        = (c + min) * VOXEL_SIZE + VOXEL_SIZE_HALF;
                                materialData[material].Sum   += localPos;
                                materialData[material].Count += 1;
                            }
                        }
                    }
                }

                for (int materialIdx = 0; materialIdx < materialData.Length; ++materialIdx)
                {
                    if (materialData[materialIdx].Count == 0)
                    {
                        continue;
                    }

                    var material = MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)materialIdx);
                    if (material.IsRare)
                    {
                        if (m_result == null)
                        {
                            m_result = new MyEntityOreDeposit(m_args.VoxelMap, m_args.Cell);
                        }

                        m_result.Materials.Add(new MyEntityOreDeposit.Data()
                        {
                            Material             = material,
                            AverageLocalPosition = Vector3D.Transform((materialData[materialIdx].Sum / materialData[materialIdx].Count - m_args.VoxelMap.SizeInMetresHalf), Quaternion.CreateFromRotationMatrix(m_args.VoxelMap.WorldMatrix)),
                        });
                    }
                }
                Array.Clear(materialData, 0, materialData.Length);
            }
            finally
            {
                ProfilerShort.End();
            }
        }
        internal static void Run(ISrvBindable depthRead)
        {
            // The maximum number of supported GPU particles
            ISrvBindable textureArraySrv;
            int          emitterCount = MyGPUEmitters.Gather(m_emitterData, out textureArraySrv);

            if (emitterCount == 0)
            {
                return;
            }

            // Unbind current targets while we run the compute stages of the system
            //RC.DeviceContext.OutputMerger.SetTargets(null);
            // global GPU particles setup
            RC.SetDepthStencilState(MyDepthStencilStateManager.DefaultDepthState);
            RC.SetRasterizerState(MyRasterizerStateManager.NocullRasterizerState);
            RC.SetInputLayout(null);
            RC.ComputeShader.SetConstantBuffer(MyCommon.FRAME_SLOT, MyCommon.FrameConstants);
            RC.ComputeShader.SetSamplers(0, MySamplerStateManager.StandardSamplers);
            RC.PixelShader.SetSamplers(0, MySamplerStateManager.StandardSamplers);
            RC.AllShaderStages.SetConstantBuffer(4, MyRender11.DynamicShadows.ShadowCascades.CascadeConstantBuffer);
            RC.VertexShader.SetSampler(MyCommon.SHADOW_SAMPLER_SLOT, MySamplerStateManager.Shadowmap);
            RC.VertexShader.SetSrv(MyCommon.CASCADES_SM_SLOT, MyRender11.DynamicShadows.ShadowCascades.CascadeShadowmapArray);
            RC.VertexShader.SetSamplers(0, MySamplerStateManager.StandardSamplers);

            // If we are resetting the particle system, then initialize the dead list
            if (m_resetSystem)
            {
                ResetInternal();
                m_resetSystem = false;
            }

            MyGpuProfiler.IC_BeginBlock("Emit");
            // Emit particles into the system
            Emit(emitterCount, m_emitterData);
            MyGpuProfiler.IC_EndBlock();

            // Run the simulation for this frame
            MyGpuProfiler.IC_BeginBlock("Simulate");
            Simulate(depthRead);
            MyGpuProfiler.IC_EndBlock();

            // Copy the atomic counter in the alive list UAV into a constant buffer for access by subsequent passes
            RC.CopyStructureCount(m_activeListConstantBuffer, 0, m_aliveIndexBuffer.m_uav);

            // Only read number of alive and dead particle back to the CPU in debug as we don't want to stall the GPU in release code

            ProfilerShort.Begin("Debug - ReadCounter");
            MyGpuProfiler.IC_BeginBlock("Debug - ReadCounter");
            int numActiveParticlesAfterSimulation = ReadCounter(m_aliveIndexBuffer);

            MyGpuProfiler.IC_EndBlock();
            ProfilerShort.End();

            MyGpuProfiler.IC_BeginBlock("Render");
            Render(textureArraySrv, depthRead);
            MyGpuProfiler.IC_EndBlock();

            RC.ComputeShader.SetSamplers(0, MySamplerStateManager.StandardSamplers);

            MyStatsDisplay.Write("GPU particles", "Live #", numActiveParticlesAfterSimulation);
        }
예제 #7
0
        internal CellData GetCell(ref MyCellCoord cell)
        {
            MyPrecalcComponent.AssertUpdateThread();

            bool     isEmpty;
            CellData data;

            if (TryGetCell(cell, out isEmpty, out data))
            {
                return(data);
            }

            MyIsoMesh mesh;

            if (!TryGetMesh(cell, out isEmpty, out mesh))
            {
                ProfilerShort.Begin("Cell precalc");
                if (true)
                {
                    var min = cell.CoordInLod << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
                    var max = min + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS;
                    // overlap to neighbor; introduces extra data but it makes logic for raycasts simpler (no need to check neighbor cells)
                    min -= 1;
                    max += 2;
                    mesh = MyPrecalcComponent.IsoMesher.Precalc(m_storage, 0, min, max, false);
                }
                else
                {
                    mesh = MyPrecalcComponent.IsoMesher.Precalc(new MyIsoMesherArgs()
                    {
                        Storage      = m_storage,
                        GeometryCell = cell,
                    });
                }
                ProfilerShort.End();
            }

            if (mesh != null)
            {
                data = new CellData();
                data.Init(
                    mesh.PositionOffset, mesh.PositionScale,
                    mesh.Positions.GetInternalArray(), mesh.VerticesCount,
                    mesh.Triangles.GetInternalArray(), mesh.TrianglesCount);
            }

            if (cell.Lod == 0)
            {
                using (m_lock.AcquireExclusiveUsing())
                {
                    if (data != null)
                    {
                        var key = cell.PackId64();
                        m_cellsByCoordinate[key] = data;
                    }
                    else
                    {
                        SetEmpty(ref cell, true);
                    }
                }
            }

            return(data);
        }
예제 #8
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(MyVoxelBase.OperationType.Cut, voxelMap, sphereShape);
                ProfilerShort.End();
            }

            ProfilerShort.End();
        }
예제 #9
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;

                        if (readMaterial)
                        {
                            voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(lin));
                        }

                        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.VoxelPathfinding.DebugLog.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(MyVoxelBase.OperationType.Cut, voxelMap, shape);
            }

            ProfilerShort.End();
        }
예제 #10
0
        //  Sends input (keyboard/mouse) to screen which has focus (top-most)
        public static void HandleInput()
        {
            ProfilerShort.Begin("MyScreenManager.HandleInput");
            try
            {
                //  Forward input to screens only if there are screens and if game has focus (is active)
                if (m_screens.Count <= 0)
                {
                    return;
                }

                //  Get screen from top of the stack - that one has focus
                MyGuiScreenBase screenWithFocus = GetScreenWithFocus();

                if (m_inputToNonFocusedScreens)
                {
                    bool inputIsShared = false;

                    for (int i = (m_screens.Count - 1); i >= 0; i--)
                    {
                        if (m_screens.Count <= i)
                        {
                            continue;
                        }
                        MyGuiScreenBase screen = m_screens[i];
                        ProfilerShort.Begin(screen.GetType().Name);
                        if (screen.CanShareInput())
                        {
                            screen.HandleInput(m_lastScreenWithFocus != screenWithFocus);
                            inputIsShared = true;
                        }
                        else if (!inputIsShared && screen == screenWithFocus)
                        {
                            screen.HandleInput(m_lastScreenWithFocus != screenWithFocus);
                        }
                        ProfilerShort.End();
                    }

                    m_inputToNonFocusedScreens &= inputIsShared;
                }
                else
                {
                    foreach (var screen in m_screens)
                    {
                        if (screen != screenWithFocus)
                        {
                            screen.InputLost();
                        }
                    }

                    if (screenWithFocus != null)
                    {
                        switch (screenWithFocus.State)
                        {
                        case MyGuiScreenState.OPENED:
                        case MyGuiScreenState.OPENING:
                        case MyGuiScreenState.UNHIDING:
                            ProfilerShort.Begin(screenWithFocus.GetType().Name);
                            screenWithFocus.HandleInput(m_lastScreenWithFocus != screenWithFocus);
                            ProfilerShort.End();
                            break;

                        case MyGuiScreenState.CLOSING:
                        case MyGuiScreenState.HIDING:
                            break;

                        default:
                            Debug.Fail(string.Format("Focused screen in state {0}.", screenWithFocus.State));
                            break;
                        }
                    }
                }

                m_lastScreenWithFocus = screenWithFocus;
            }
            finally { ProfilerShort.End(); }
        }
예제 #11
0
        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();
        }
예제 #12
0
        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 MyVoxelMap)
                    {
                        ProfilerShort.Begin("Drill voxel map");
                        var voxels = entity as MyVoxelMap;
                        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);
        }
예제 #13
0
        public void Update(int behaviorTicks)
        {
            m_stuckDetection.SetCurrentTicks(behaviorTicks);

            ProfilerShort.Begin("MyBotNavigation.Update");
            AssertIsValid();

            if (m_entity == null)
            {
                return;
            }

            ProfilerShort.Begin("UpdateMatrices");
            UpdateMatrices();
            ProfilerShort.End();

            m_gravityDirection = MyGravityProviderSystem.CalculateTotalGravityInPoint(m_entity.PositionComp.WorldMatrix.Translation);
            if (!Vector3.IsZero(m_gravityDirection, 0.01f))
            {
                m_gravityDirection = Vector3D.Normalize(m_gravityDirection);
            }

            if (MyPerGameSettings.NavmeshPresumesDownwardGravity)
            {
                m_upVector = Vector3.Up;
            }
            else
            {
                m_upVector = -m_gravityDirection;
            }

            if (!m_speed.IsValid())
            {
                m_forwardVector         = PositionAndOrientation.Forward;
                m_speed                 = 0.0f;
                m_rotationSpeedModifier = 1;
            }

            ProfilerShort.Begin("Steering update");
            foreach (var steering in m_steerings)
            {
                ProfilerShort.Begin(steering.GetName());
                steering.Update();
                ProfilerShort.End();
            }
            ProfilerShort.End();

            ProfilerShort.Begin("Aiming");
            m_aiming.Update();
            ProfilerShort.End();

            ProfilerShort.Begin("Steering accumulate correction");
            CorrectMovement(m_aiming.RotationHint);
            ProfilerShort.End();

            if (m_speed < 0.1f)// hotfix for flickering of animation from running left to running right
            {
                m_speed = 0;
            }

            ProfilerShort.Begin("MoveCharacter");
            MoveCharacter();
            ProfilerShort.End();

            AssertIsValid();
            ProfilerShort.End();
        }
예제 #14
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 && 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);
                    }
                    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();
        }
예제 #15
0
        public override void HandleInput()
        {
            ProfilerShort.Begin("MyToolbarComponent.HandleInput");
            try
            {
                var context       = MySession.Static.ControlledEntity != null ? MySession.Static.ControlledEntity.ControlContext : MyStringId.NullOrEmpty;
                var focusedScreen = MyScreenManager.GetScreenWithFocus();
                if ((focusedScreen == MyGuiScreenGamePlay.Static ||
                     IsToolbarControlShown) &&
                    CurrentToolbar != null)
                {
                    {
                        for (int i = 0; i < m_slotControls.Length; i++)
                        {
                            if (MyControllerHelper.IsControl(context, m_slotControls[i], MyControlStateType.NEW_PRESSED))
                            {
                                if (!MyInput.Static.IsAnyCtrlKeyPressed())
                                {
                                    if ((focusedScreen == MyGuiScreenGamePlay.Static ||
                                         (focusedScreen is MyGuiScreenCubeBuilder || focusedScreen is MyGuiScreenToolbarConfigBase) && ((MyGuiScreenToolbarConfigBase)focusedScreen).AllowToolbarKeys()) &&
                                        CurrentToolbar != null)
                                    {
                                        CurrentToolbar.ActivateItemAtSlot(i);
                                    }
                                }
                                else if (i < CurrentToolbar.PageCount)
                                {
                                    MyGuiAudio.PlaySound(MyGuiSounds.HudClick);
                                    CurrentToolbar.SwitchToPage(i);
                                }
                            }
                        }
                    }

                    if ((focusedScreen == MyGuiScreenGamePlay.Static ||
                         (focusedScreen is MyGuiScreenCubeBuilder || focusedScreen is MyGuiScreenToolbarConfigBase) && ((MyGuiScreenToolbarConfigBase)focusedScreen).AllowToolbarKeys()) &&
                        CurrentToolbar != null)
                    {
                        if (MyControllerHelper.IsControl(context, MyControlsSpace.TOOLBAR_NEXT_ITEM, MyControlStateType.NEW_PRESSED))
                        {
                            CurrentToolbar.SelectNextSlot();
                        }
                        else if (MyControllerHelper.IsControl(context, MyControlsSpace.TOOLBAR_PREV_ITEM, MyControlStateType.NEW_PRESSED))
                        {
                            CurrentToolbar.SelectPreviousSlot();
                        }
                        if (MyControllerHelper.IsControl(context, MyControlsSpace.TOOLBAR_UP, MyControlStateType.NEW_PRESSED))
                        {
                            MyGuiAudio.PlaySound(MyGuiSounds.HudClick);
                            CurrentToolbar.PageUp();
                        }
                        if (MyControllerHelper.IsControl(context, MyControlsSpace.TOOLBAR_DOWN, MyControlStateType.NEW_PRESSED))
                        {
                            MyGuiAudio.PlaySound(MyGuiSounds.HudClick);
                            CurrentToolbar.PageDown();
                        }
                    }
                }
            }
            finally
            {
                ProfilerShort.End();
            }

            base.HandleInput();
        }
        public bool Disconnect(MyCubeGrid grid, MySlimBlock testBlock = null, bool testDisconnect = false)
        {
            ProfilerShort.Begin("Collect+IsInVoxels");
            m_largestGroupWithPhysics = default(Group);
            m_groups.Clear();
            m_sortedBlocks.Clear();
            m_disconnectHelper.Clear();
            foreach (var block in grid.GetBlocks())
            {
                if (block == testBlock)
                {
                    continue;
                }

                m_disconnectHelper.Add(block);
            }
            ProfilerShort.End();

            ProfilerShort.Begin("GroupBy");
            while (m_disconnectHelper.Count > 0)
            {
                Group group = default(Group);
                group.FirstBlockIndex = m_sortedBlocks.Count;
                AddNeighbours(m_disconnectHelper.FirstElement(), out group.IsValid, testBlock);
                group.BlockCount = m_sortedBlocks.Count - group.FirstBlockIndex;

                if (group.IsValid && group.BlockCount > m_largestGroupWithPhysics.BlockCount)
                {
                    if (m_largestGroupWithPhysics.BlockCount > 0) // Is valid
                    {
                        // order matters, insert in correct place
                        int i = 0;
                        for (i = 0; i < m_groups.Count; i++)
                        {
                            if (m_groups[i].FirstBlockIndex > m_largestGroupWithPhysics.FirstBlockIndex)
                            {
                                m_groups.Insert(i, m_largestGroupWithPhysics);
                                break;
                            }
                        }

                        if (i == m_groups.Count)
                        {
                            m_groups.Add(m_largestGroupWithPhysics);
                        }
                    }

                    m_largestGroupWithPhysics = group;
                }
                else
                {
                    m_groups.Add(group);
                }
            }
            ProfilerShort.End();

            ProfilerShort.Begin("RemoveLargestGroup");
            m_sortedBlocks.RemoveRange(m_largestGroupWithPhysics.FirstBlockIndex, m_largestGroupWithPhysics.BlockCount);
            for (int i = 0; i < m_groups.Count; i++)
            {
                var g = m_groups[i];
                if (g.FirstBlockIndex > m_largestGroupWithPhysics.FirstBlockIndex)
                {
                    g.FirstBlockIndex -= m_largestGroupWithPhysics.BlockCount;
                    m_groups[i]        = g;
                }
            }
            ProfilerShort.End();

            ProfilerShort.Begin("CreateSplits");
            if (m_groups.Count > 0)
            {
                if (testDisconnect)
                {
                    m_groups.Clear();
                    m_sortedBlocks.Clear();
                    m_disconnectHelper.Clear();
                    ProfilerShort.End();
                    return(true);
                }
                MyCubeGrid.CreateSplits(grid, m_sortedBlocks, m_groups);
            }
            else
            {
                if (!MySession.Static.Settings.StationVoxelSupport)
                {
                    if (grid.IsStatic)
                    {
                        grid.TestDynamic = MyCubeGrid.MyTestDynamicReason.GridSplit;
                    }
                }
            }
            ProfilerShort.End();

            m_groups.Clear();
            m_sortedBlocks.Clear();
            m_disconnectHelper.Clear();
            return(false);
        }
예제 #17
0
        public override void Init(MyObjectBuilder_CubeBlock builder, MyCubeGrid cubeGrid)
        {
            base.Init(builder, cubeGrid);
            ProfilerShort.Begin("FP.Init");
            CheckConnectionAllowed = true;
            var ob = builder as MyObjectBuilder_FracturedBlock;

            if (ob.Shapes.Count == 0)
            {
                ProfilerShort.End();
                if (ob.CreatingFracturedBlock)
                {
                    return;
                }
                Debug.Fail("No relevant shape was found for fractured block. It was probably reexported and names changed.");
                throw new Exception("No relevant shape was found for fractured block. It was probably reexported and names changed.");
            }

            OriginalBlocks = new List <MyDefinitionId>();
            Orientations   = new List <MyBlockOrientation>();
            var lst = new List <HkdShapeInstanceInfo>();

            foreach (var def in ob.BlockDefinitions)
            {
                var blockDef = MyDefinitionManager.Static.GetCubeBlockDefinition(def);

                var model = blockDef.Model;
                if (VRage.Game.Models.MyModels.GetModelOnlyData(model).HavokBreakableShapes == null)
                {
                    MyDestructionData.Static.LoadModelDestruction(model, blockDef, Vector3.One);
                }
                var shape = VRage.Game.Models.MyModels.GetModelOnlyData(model).HavokBreakableShapes[0];
                var si    = new HkdShapeInstanceInfo(shape, null, null);
                lst.Add(si);
                m_children.Add(si);
                shape.GetChildren(m_children);
                if (blockDef.BuildProgressModels != null)
                {
                    foreach (var progress in blockDef.BuildProgressModels)
                    {
                        model = progress.File;
                        if (VRage.Game.Models.MyModels.GetModelOnlyData(model).HavokBreakableShapes == null)
                        {
                            MyDestructionData.Static.LoadModelDestruction(model, blockDef, Vector3.One);
                        }
                        shape = VRage.Game.Models.MyModels.GetModelOnlyData(model).HavokBreakableShapes[0];
                        si    = new HkdShapeInstanceInfo(shape, null, null);
                        lst.Add(si);
                        m_children.Add(si);
                        shape.GetChildren(m_children);
                    }
                }


                OriginalBlocks.Add(def);
            }

            foreach (var or in ob.BlockOrientations)
            {
                Orientations.Add(or);
            }

            if (ob.MultiBlocks.Count > 0)
            {
                MultiBlocks = new List <MultiBlockPartInfo>();
                foreach (var mbpart in ob.MultiBlocks)
                {
                    if (mbpart != null)
                    {
                        MultiBlocks.Add(new MultiBlockPartInfo()
                        {
                            MultiBlockDefinition = mbpart.MultiBlockDefinition, MultiBlockId = mbpart.MultiBlockId
                        });
                    }
                    else
                    {
                        MultiBlocks.Add(null);
                    }
                }
            }

            m_shapes.AddRange(ob.Shapes);
            for (int i = 0; i < m_children.Count; i++)
            {
                var child = m_children[i];
                Func <MyObjectBuilder_FracturedBlock.ShapeB, bool> x = s => s.Name == child.ShapeName;
                var result = m_shapes.Where(x);
                if (result.Count() > 0)
                {
                    var found = result.First();
                    var m     = Matrix.CreateFromQuaternion(found.Orientation);
                    m.Translation = child.GetTransform().Translation;
                    var si = new HkdShapeInstanceInfo(child.Shape.Clone(), m);
                    if (found.Fixed)
                    {
                        si.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED);
                    }
                    lst.Add(si);
                    m_shapeInfos.Add(si);
                    m_shapes.Remove(found);
                }
                else
                {
                    child.GetChildren(m_children);
                }
            }

            if (m_shapeInfos.Count == 0)
            {
                m_children.Clear();
                ProfilerShort.End();
                Debug.Fail("No relevant shape was found for fractured block. It was probably reexported and names changed.");
                throw new Exception("No relevant shape was found for fractured block. It was probably reexported and names changed.");
            }

            foreach (var shape in m_shapeInfos)
            {
                if (!string.IsNullOrEmpty(shape.Shape.Name))
                {
                    Render.AddPiece(shape.Shape.Name, Matrix.CreateFromQuaternion(Quaternion.CreateFromRotationMatrix(shape.GetTransform().GetOrientation())));
                }
            }

            if (CubeGrid.CreatePhysics)
            {
                HkdBreakableShape compound = new HkdCompoundBreakableShape(null, m_shapeInfos);
                ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren();
                Shape = compound;
                var mp = new HkMassProperties();
                compound.BuildMassProperties(ref mp);
                Shape = new HkdBreakableShape(compound.GetShape(), ref mp);
                compound.RemoveReference();
                foreach (var si in m_shapeInfos)
                {
                    var siRef = si;
                    Shape.AddShape(ref siRef);
                }
                Shape.SetStrenght(MyDestructionConstants.STRENGTH);
                CreateMountPoints();
            }
            m_children.Clear();
            foreach (var si in m_shapeInfos)
            {
                si.Shape.RemoveReference();
            }
            foreach (var si in lst)
            {
                si.RemoveReference();
            }
            m_shapeInfos.Clear();

            ProfilerShort.End();
        }
        private void FindAndCaculateFromStatic()
        {
            HashSet <Node> closedList = new HashSet <Node>();
            List <Node>    tmpNodes   = new List <Node>();

            var cmp = new NodeDistanceComparer();

            // For each dynamic block
            foreach (var stat in StaticBlocks)
            {
                // TODO: Clear nodes parent and is leaf
                closedList.Clear();
                tmpNodes.Clear();

                using (Stats.Timing.Measure("SI - Static.FindDistances", VRage.Stats.MyStatTypeEnum.Sum | VRage.Stats.MyStatTypeEnum.DontDisappearFlag))
                {
                    // Find shortest distance to each dynamic block
                    ProfilerShort.Begin("FindDistances");
                    FindDistances(stat, closedList, tmpNodes);
                    ProfilerShort.End();
                }

                tmpNodes.Clear();

                using (Stats.Timing.Measure("SI - Dynamic.Sort", VRage.Stats.MyStatTypeEnum.Sum | VRage.Stats.MyStatTypeEnum.DontDisappearFlag))
                {
                    foreach (var block in closedList)
                    {
                        if (!block.IsStatic)
                        {
                            // Reset transfer mass
                            block.Ratio        = 1.0f;
                            block.TransferMass = block.Mass;
                            tmpNodes.Add(block);
                        }
                    }

                    // Sort dynamic blocks in range by distance, biggest distance first
                    tmpNodes.Sort(cmp);
                }

                using (Stats.Timing.Measure("SI - Dynamic.Calculate", VRage.Stats.MyStatTypeEnum.Sum | VRage.Stats.MyStatTypeEnum.DontDisappearFlag))
                {
                    // For each dynamic block
                    foreach (var node in tmpNodes)
                    {
                        if (node.IsStatic)
                        {
                            continue;
                        }

                        node.PathCount++;
                        foreach (var parent in node.Parents)
                        {
                            var delta = parent.Pos - node.Pos; // Node to parent
                            int index, parentIndex;
                            if (delta.X + delta.Y + delta.Z > 0)
                            {
                                index       = delta.Y + delta.Z * 2; // UnitX = 0, UnitY = 1, UnitZ = 2
                                parentIndex = index + 3;
                            }
                            else
                            {
                                index       = -delta.X * 3 - delta.Y * 4 - delta.Z * 5; // // -UnitX = 3, -UnitY = 4, -UnitZ = 5
                                parentIndex = index - 3;
                            }

                            node.SupportingWeights[index]         -= node.TransferMass / node.Parents.Count;
                            parent.SupportingWeights[parentIndex] += node.TransferMass / node.Parents.Count;

                            parent.TransferMass += node.TransferMass / node.Parents.Count;
                        }
                    }
                }
            }
        }
예제 #19
0
        public static List <MyCubeBlockDefinition.MountPoint> AutogenerateMountpoints(HkShape[] shapes, float gridSize)
        {
            ProfilerShort.Begin("AutogenerateMountpoints");
            HkShapeCutterUtil cutter = new HkShapeCutterUtil();

            List <BoundingBox>[] aabbsPerDirection = new List <BoundingBox> [Base6Directions.EnumDirections.Length];

            var newMountPoints = new List <MyCubeBlockDefinition.MountPoint>();

            foreach (var directionEnum in Base6Directions.EnumDirections)
            {
                int dirEnum = (int)directionEnum;
                //int dirEnum = 2;
                Vector3 direction = Base6Directions.Directions[dirEnum];

                foreach (var shape in shapes)
                {
                    if (shape.ShapeType == HkShapeType.List)
                    {
                        var listShape = (HkListShape)shape;
                        var iterator  = listShape.GetIterator();
                        while (iterator.IsValid)
                        {
                            HkShape childShape = iterator.CurrentValue;

                            if (childShape.ShapeType == HkShapeType.ConvexTransform)
                            {
                                HkConvexTransformShape transformShape = (HkConvexTransformShape)childShape;

                                FindMountPoint(cutter, transformShape.Base, direction, gridSize, newMountPoints);
                            }
                            else
                            if (childShape.ShapeType == HkShapeType.ConvexTranslate)
                            {
                                HkConvexTranslateShape translateShape = (HkConvexTranslateShape)childShape;

                                FindMountPoint(cutter, translateShape.Base, direction, gridSize, newMountPoints);
                            }
                            else
                            {
                                FindMountPoint(cutter, childShape, direction, gridSize, newMountPoints);
                            }

                            iterator.Next();
                        }
                        break;
                    }
                    else
                    if (shape.ShapeType == HkShapeType.Mopp)
                    {
                        var compoundShape = (HkMoppBvTreeShape)shape;
                        for (int s = 0; s < compoundShape.ShapeCollection.ShapeCount; s++)
                        {
                            HkShape childShape = compoundShape.ShapeCollection.GetShape((uint)s, null);

                            if (childShape.ShapeType == HkShapeType.ConvexTranslate)
                            {
                                HkConvexTranslateShape translateShape = (HkConvexTranslateShape)childShape;

                                FindMountPoint(cutter, translateShape.Base, direction, gridSize, newMountPoints);
                            }
                        }
                        break;
                    }
                    else
                    {
                        FindMountPoint(cutter, shape, direction, gridSize, newMountPoints);
                    }
                }
            }
            ProfilerShort.End();
            return(newMountPoints);
        }
        private void FindAndCaculateFromDynamic()
        {
            HashSet <Node> closedList  = new HashSet <Node>();
            List <Node>    staticNodes = new List <Node>();
            Queue <Node>   tmpBranches = new Queue <Node>();

            // For each dynamic block
            foreach (var dyn in DynamicBlocks)
            {
                // TODO: Clear nodes parent and is leaf
                closedList.Clear();
                staticNodes.Clear();
                dyn.PathCount = 1;

                using (Stats.Timing.Measure("SI - Dynamic.FindDistances", VRage.Stats.MyStatTypeEnum.Sum | VRage.Stats.MyStatTypeEnum.DontDisappearFlag))
                {
                    // Find shortest distance to each static block
                    ProfilerShort.Begin("FindDistances");
                    FindDistances(dyn, closedList, staticNodes);
                    ProfilerShort.End();
                }
                int   numPaths     = staticNodes.Count;
                float contribution = dyn.Mass / numPaths;

                using (Stats.Timing.Measure("SI - Dynamic.Calculate", VRage.Stats.MyStatTypeEnum.Sum | VRage.Stats.MyStatTypeEnum.DontDisappearFlag))
                {
                    foreach (var s in staticNodes)
                    {
                        closedList.Clear();
                        tmpBranches.Clear();
                        s.Ratio       = 1.0f;
                        dyn.PathCount = 1;

                        tmpBranches.Enqueue(s);
                        while (tmpBranches.Count > 0)
                        {
                            var   node  = tmpBranches.Dequeue();
                            float ratio = node.Ratio / node.Parents.Count;

                            foreach (var parent in node.Parents)
                            {
                                var delta = parent.Pos - node.Pos; // Node to parent
                                int index, parentIndex;
                                if (delta.X + delta.Y + delta.Z > 0)
                                {
                                    index       = delta.Y + delta.Z * 2; // UnitX = 0, UnitY = 1, UnitZ = 2
                                    parentIndex = index + 3;
                                }
                                else
                                {
                                    index       = -delta.X * 3 - delta.Y * 4 - delta.Z * 5; // // -UnitX = 3, -UnitY = 4, -UnitZ = 5
                                    parentIndex = index - 3;
                                }

                                node.SupportingWeights[index]         -= contribution * ratio;
                                parent.SupportingWeights[parentIndex] += contribution * ratio;

                                if (closedList.Add(parent))
                                {
                                    parent.Ratio = ratio;
                                    tmpBranches.Enqueue(parent);
                                }
                                else
                                {
                                    parent.Ratio += ratio;
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #21
0
        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 -= MyEnvironment.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;
            }
        }
        internal void ReadContentRange(MyStorageData target, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod)
        {
            float          lodVoxelSizeHalf;
            BoundingBox    queryBox;
            BoundingSphere querySphere;

            SetupReading(lodIndex, ref minInLod, ref maxInLod, out lodVoxelSizeHalf, out queryBox, out querySphere);
            float lodVoxelSize = 2f * lodVoxelSizeHalf;

            ProfilerShort.Begin("Testing removed shapes");
            var overlappedRemovedShapes = OverlappedRemovedShapes;

            overlappedRemovedShapes.Clear();
            ContainmentType testRemove = ContainmentType.Disjoint;

            for (int i = 0; i < m_data.RemovedShapes.Length; ++i)
            {
                var test = m_data.RemovedShapes[i].Contains(ref queryBox, ref querySphere, lodVoxelSize);
                if (test == ContainmentType.Contains)
                {
                    testRemove = ContainmentType.Contains;
                    break; // completely empty so we can leave
                }
                else if (test == ContainmentType.Intersects)
                {
                    testRemove = ContainmentType.Intersects;
                    overlappedRemovedShapes.Add(m_data.RemovedShapes[i]);
                }
            }
            ProfilerShort.End();
            if (testRemove == ContainmentType.Contains)
            {
                ProfilerShort.Begin("target.BlockFillContent");
                target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_EMPTY);
                ProfilerShort.End();
                return;
            }

            ProfilerShort.Begin("Testing filled shapes");
            var overlappedFilledShapes = OverlappedFilledShapes;

            overlappedFilledShapes.Clear();
            ContainmentType testFill = ContainmentType.Disjoint;

            for (int i = 0; i < m_data.FilledShapes.Length; ++i)
            {
                var test = m_data.FilledShapes[i].Contains(ref queryBox, ref querySphere, lodVoxelSize);
                if (test == ContainmentType.Contains)
                {
                    overlappedFilledShapes.Clear();
                    testFill = ContainmentType.Contains;
                    break;
                }
                else if (test == ContainmentType.Intersects)
                {
                    overlappedFilledShapes.Add(m_data.FilledShapes[i]);
                    testFill = ContainmentType.Intersects;
                }
            }
            ProfilerShort.End();

            if (testFill == ContainmentType.Disjoint)
            {
                ProfilerShort.Begin("target.BlockFillContent");
                target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_EMPTY);
                ProfilerShort.End();
                return;
            }
            else if (testRemove == ContainmentType.Disjoint && testFill == ContainmentType.Contains)
            {
                ProfilerShort.Begin("target.BlockFillContent");
                target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_FULL);
                ProfilerShort.End();
                return;
            }

            ProfilerShort.Begin("Distance field computation");
            Vector3I v              = minInLod;
            Vector3  localPos       = v * lodVoxelSize;
            Vector3  localPosStart  = v * lodVoxelSize;
            var      writeOffsetLoc = writeOffset - minInLod;

            for (v.Z = minInLod.Z; v.Z <= maxInLod.Z; ++v.Z)
            {
                for (v.Y = minInLod.Y; v.Y <= maxInLod.Y; ++v.Y)
                {
                    v.X = minInLod.X;
                    var write2 = v + writeOffsetLoc;
                    var write  = target.ComputeLinear(ref write2);
                    for (; v.X <= maxInLod.X; ++v.X)
                    {
                        //Vector3 localPos = v * lodVoxelSize;

                        //ProfilerShort.Begin("Dist filled");
                        float distFill;
                        if (testFill == ContainmentType.Contains)
                        {
                            distFill = -1f;
                        }
                        else
                        {
                            //ProfilerShort.Begin("shape distances");
                            distFill = 1f;
                            foreach (var shape in overlappedFilledShapes)
                            {
                                distFill = Math.Min(distFill, shape.SignedDistance(ref localPos, lodVoxelSize, m_data.MacroModule, m_data.DetailModule));
                                if (distFill <= -1)
                                {
                                    break;
                                }
                            }
                            //ProfilerShort.End();
                        }

                        //ProfilerShort.BeginNextBlock("Dist removed");
                        float distRemoved = 1f;
                        if (testRemove != ContainmentType.Disjoint)
                        {
                            foreach (var shape in overlappedRemovedShapes)
                            {
                                distRemoved = Math.Min(distRemoved, shape.SignedDistance(ref localPos, lodVoxelSize, m_data.MacroModule, m_data.DetailModule));
                                if (distRemoved <= -1)
                                {
                                    break;
                                }
                            }
                        }
                        //ProfilerShort.BeginNextBlock("content");
                        float signedDist = MathHelper.Max(distFill, -distRemoved);

                        var  fillRatio = MathHelper.Clamp(-signedDist, -1f, 1f) * 0.5f + 0.5f;
                        byte content   = (byte)(fillRatio * MyVoxelConstants.VOXEL_CONTENT_FULL);
                        target.Content(write, content);
                        Debug.Assert(Math.Abs((((float)content) / MyVoxelConstants.VOXEL_CONTENT_FULL) - fillRatio) <= 0.5f);
                        //ProfilerShort.End();
                        write      += target.StepLinear;
                        localPos.X += lodVoxelSize;
                    }
                    localPos.Y += lodVoxelSize;
                    localPos.X  = localPosStart.X;
                }
                localPos.Z += lodVoxelSize;
                localPos.Y  = localPosStart.Y;
            }
            ProfilerShort.End();
        }
예제 #23
0
        //collisions
        //sphere vs voxel volumetric test
        // mk:TODO Remove. This is not very accurate.
        public override bool DoOverlapSphereTest(float sphereRadius, Vector3D spherePos)
        {
            ProfilerShort.Begin("MyVoxelMap.DoOverlapSphereTest");
            Vector3D        body0Pos = spherePos; // sphere pos
            BoundingSphereD newSphere;

            newSphere.Center = body0Pos;
            newSphere.Radius = sphereRadius;

            //  We will iterate only voxels contained in the bounding box of new sphere, so here we get min/max corned in voxel units
            Vector3I minCorner, maxCorner;

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

            minCorner += StorageMin;
            maxCorner += StorageMin;

            Storage.ClampVoxelCoord(ref minCorner);
            Storage.ClampVoxelCoord(ref maxCorner);
            m_storageCache.Resize(minCorner, maxCorner);
            Storage.ReadRange(m_storageCache, MyStorageDataTypeFlags.Content, 0, ref minCorner, ref maxCorner);

            Vector3I tempVoxelCoord, cache;

            for (tempVoxelCoord.Z = minCorner.Z, cache.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, cache.Z++)
            {
                for (tempVoxelCoord.Y = minCorner.Y, cache.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, cache.Y++)
                {
                    for (tempVoxelCoord.X = minCorner.X, cache.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, cache.X++)
                    {
                        byte voxelContent = m_storageCache.Content(ref cache);

                        //  Ignore voxels bellow the ISO value (empty, partialy empty...)
                        if (voxelContent < MyVoxelConstants.VOXEL_ISO_LEVEL)
                        {
                            continue;
                        }

                        Vector3D voxelPosition;
                        MyVoxelCoordSystems.VoxelCoordToWorldPosition(PositionLeftBottomCorner - StorageMin * MyVoxelConstants.VOXEL_SIZE_IN_METRES, ref tempVoxelCoord, out voxelPosition);

                        float voxelSize = (voxelContent / MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT) * MyVoxelConstants.VOXEL_RADIUS;

                        //  If distance to voxel border is less than sphere radius, we have a collision
                        //  So now we calculate normal vector and penetration depth but on OLD sphere
                        float newDistanceToVoxel = Vector3.Distance(voxelPosition, newSphere.Center) - voxelSize;
                        if (newDistanceToVoxel < (newSphere.Radius))
                        {
                            ProfilerShort.End();
                            return(true);
                        }
                    }
                }
            }
            ProfilerShort.End();
            return(false);
        }
        internal void ReadMaterialRange(MyStorageData target, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod)
        {
            float          lodVoxelSizeHalf;
            BoundingBox    queryBox;
            BoundingSphere querySphere;

            SetupReading(lodIndex, ref minInLod, ref maxInLod, out lodVoxelSizeHalf, out queryBox, out querySphere);
            float lodVoxelSize = 2f * lodVoxelSizeHalf;

            var overlappedDeposits = OverlappedDeposits;

            {
                ProfilerShort.Begin("Testing deposit shapes");
                overlappedDeposits.Clear();
                ContainmentType testDeposits = ContainmentType.Disjoint;
                for (int i = 0; i < m_data.Deposits.Length; ++i)
                {
                    var test = m_data.Deposits[i].Shape.Contains(ref queryBox, ref querySphere, lodVoxelSize);
                    if (test != ContainmentType.Disjoint)
                    {
                        overlappedDeposits.Add(m_data.Deposits[i]);
                        testDeposits = ContainmentType.Intersects;
                    }
                }
                ProfilerShort.End();

                if (testDeposits == ContainmentType.Disjoint)
                {
                    ProfilerShort.Begin("target.BlockFillMaterial");
                    target.BlockFillMaterial(writeOffset, writeOffset + (maxInLod - minInLod), m_data.DefaultMaterial.Index);
                    ProfilerShort.End();
                    return;
                }
            }


            ProfilerShort.Begin("Material computation");

            Vector3I v;

            for (v.Z = minInLod.Z; v.Z <= maxInLod.Z; ++v.Z)
            {
                for (v.Y = minInLod.Y; v.Y <= maxInLod.Y; ++v.Y)
                {
                    for (v.X = minInLod.X; v.X <= maxInLod.X; ++v.X)
                    {
                        Vector3 localPos = v * lodVoxelSize;

                        float closestDistance    = 1f;
                        byte  closestMaterialIdx = m_data.DefaultMaterial.Index;
                        if (!MyFakes.DISABLE_COMPOSITE_MATERIAL)
                        {
                            foreach (var deposit in overlappedDeposits)
                            {
                                float distance = deposit.Shape.SignedDistance(ref localPos, MyVoxelConstants.VOXEL_SIZE_IN_METRES, m_data.MacroModule, m_data.DetailModule);
                                if (distance < 0f && distance <= closestDistance)
                                {
                                    closestDistance = distance;
                                    // DA: Pass default material to the layered deposit so only that does these if-s.
                                    var materialDef = deposit.GetMaterialForPosition(ref localPos, lodVoxelSize);
                                    closestMaterialIdx = materialDef == null ? m_data.DefaultMaterial.Index : materialDef.Index;
                                }
                            }
                        }

                        var write = v - minInLod + writeOffset;
                        target.Material(ref write, closestMaterialIdx);
                    }
                }
            }
            ProfilerShort.End();
        }
예제 #25
0
        public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck, bool adviceCache = false)
        {
            m_resultVerticesCounter  = 0;
            m_resultTrianglesCounter = 0;
            m_edgeVertexCalcCounter++;
            m_temporaryVoxelsCounter++;

            CalcPolygCubeSize(lod, storage.Size);

            m_voxelStart = voxelStart;
            //voxelStart = voxelStart;
            //voxelEnd = voxelEnd;
            var ssize = storage.Size;

            m_cache.Resize(voxelStart, voxelEnd);

            // Load content first, check it if it contains isosurface, early exit if it doesn't.
            storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd);

            if (!m_cache.ContainsIsoSurface())
            {
                return(null);
            }

            storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, lod, ref voxelStart, ref voxelEnd);

            ProfilerShort.Begin("Marching cubes");
            {
                //  Size of voxel or cell (in meters) and size of voxel map / voxel cells
                ComputeSizeAndOrigin(lod, storage.Size);


                var      start  = Vector3I.Zero;
                var      end    = voxelEnd - voxelStart - 3;
                Vector3I coord0 = start;


                for (var it = new Vector3I_RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out coord0))
                {
                    int cubeIndex = 0;
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 1;
                    }
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 2;
                    }
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 4;
                    }
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 8;
                    }
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 16;
                    }
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 32;
                    }
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 64;
                    }
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 128;
                    }

                    //  Cube is entirely in/out of the surface
                    if (MyMarchingCubesConstants.EdgeTable[cubeIndex] == 0)
                    {
                        continue;
                    }

                    //  We can get this voxel content right from cache (not using GetVoxelContent method), because after CopyVoxelContents these array must be filled. But only content, not material, normal, etc.
                    Vector3I tempVoxelCoord0 = ComputeTemporaryVoxelData(m_cache, ref coord0, cubeIndex, lod);

                    //  Create the triangles
                    CreateTriangles(ref coord0, cubeIndex, ref tempVoxelCoord0);
                }
            }
            ProfilerShort.End();


            double numCellsHalf     = 0.5f * (m_cache.Size3D.X);
            var    voxelSize        = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod);
            var    vertexCellOffset = voxelStart - AffectedRangeOffset;

            IMyIsoMesherOutputBuffer isomesh = new MyIsoMesh();


            for (int i = 0; i < m_resultVerticesCounter; i++)
            {
                var pos = (m_resultVertices[i].Position - (Vector3)storage.Size / 2) / storage.Size;
                m_resultVertices[i].Position      = pos;
                m_resultVertices[i].PositionMorph = pos;
                m_resultVertices[i].NormalMorph   = m_resultVertices[i].Normal;
                m_resultVertices[i].MaterialMorph = m_resultVertices[i].Material;
                m_resultVertices[i].AmbientMorph  = m_resultVertices[i].Ambient;
            }

            for (int i = 0; i < m_resultVerticesCounter; i++)
            {
                isomesh.WriteVertex(ref m_resultVertices[i].Cell, ref m_resultVertices[i].Position, ref m_resultVertices[i].Normal, (byte)m_resultVertices[i].Material, m_resultVertices[i].Ambient);
            }

            for (int i = 0; i < m_resultTrianglesCounter; i++)
            {
                isomesh.WriteTriangle(m_resultTriangles[i].VertexIndex0, m_resultTriangles[i].VertexIndex1, m_resultTriangles[i].VertexIndex2);
            }

            var mIsoMesh = (MyIsoMesh)isomesh;

            mIsoMesh.PositionOffset = storage.Size / 2;
            mIsoMesh.PositionScale  = storage.Size;
            mIsoMesh.CellStart      = voxelStart;
            mIsoMesh.CellEnd        = voxelEnd;

            var vertexCells = mIsoMesh.Cells.GetInternalArray();

            for (int i = 0; i < mIsoMesh.VerticesCount; i++)
            {
                vertexCells[i] += vertexCellOffset;
            }

            return((MyIsoMesh)isomesh);
        }
예제 #26
0
        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)
                {
                    bool enqueued = m_pendingChunksToWrite.Count > 0;

                    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);
                                    }
                                }
                            }
                        }
                    }

                    if (!enqueued)
                    {
                        OperationsComponent.Add(this);
                    }
                }
                else
                {
                    using (m_storageLock.AcquireExclusiveUsing())
                        WriteRangeInternal(source, dataToWrite, ref voxelRangeMin, ref voxelRangeMax);
                }

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

                OnRangeChanged(voxelRangeMin, voxelRangeMax, dataToWrite);
            }
            finally
            {
                ProfilerShort.End();
            }
        }
        private void UpdateRenderInstanceData(Dictionary <ModelId, Tuple <List <MyCubeInstanceMergedData>, MyInstanceInfo> > instanceParts, RenderFlags renderFlags)
        {
            if (m_parentCullObject == MyRenderProxy.RENDER_ID_UNASSIGNED)
            {
                m_parentCullObject = MyRenderProxy.CreateManualCullObject(m_gridRenderComponent.Container.Entity.GetFriendlyName() + " " + m_gridRenderComponent.Container.Entity.EntityId.ToString() + ", cull object", m_gridRenderComponent.Container.Entity.PositionComp.WorldMatrix);
                AddRenderObjectId(m_parentCullObject, true);
            }

            if (m_instanceBufferId == MyRenderProxy.RENDER_ID_UNASSIGNED)
            {
                m_instanceBufferId = MyRenderProxy.CreateRenderInstanceBuffer(
                    m_gridRenderComponent.Container.Entity.GetFriendlyName() + " "
                    + m_gridRenderComponent.Container.Entity.EntityId.ToString()
                    + ", instance buffer " + DebugName, MyRenderInstanceBufferType.Cube,
                    m_gridRenderComponent.GetRenderObjectID());
                AddRenderObjectId(m_instanceBufferId, false);
            }

            ProfilerShort.Begin("Merge render parts");

            // Merge data into one buffer
            Debug.Assert(InstanceData.Count == 0, "Instance data is not cleared");
            m_instanceInfo.Clear();
            m_tmpDecalData.Clear();
            int instaceDataIndex = -1;

            foreach (var pair in instanceParts)
            {
                var modeId = pair.Key;
                var tuple  = pair.Value;
                m_instanceInfo.Add(modeId, new MyRenderInstanceInfo(m_instanceBufferId, InstanceData.Count, tuple.Item1.Count, tuple.Item2.MaxViewDistance, tuple.Item2.Flags));

                var instaceDatas = tuple.Item1;
                for (int it1 = 0; it1 < instaceDatas.Count; it1++)
                {
                    instaceDataIndex++;
                    InstanceData.Add(instaceDatas[it1].CubeInstanceData);

                    var decals = instaceDatas[it1].Decals;
                    if (decals == null)
                    {
                        continue;
                    }

                    for (int it2 = 0; it2 < decals.Count; it2++)
                    {
                        m_tmpDecalData.Add(new MyCubeInstanceDecalData()
                        {
                            DecalId = decals[it2], InstanceIndex = instaceDataIndex
                        });
                    }
                }
            }
            ProfilerShort.End();

            if (InstanceData.Count > 0)
            {
                ProfilerShort.Begin("Update instance buffer");

                MyRenderProxy.UpdateRenderCubeInstanceBuffer(m_instanceBufferId, InstanceData, (int)(InstanceData.Count * 1.2f), m_tmpDecalData);
                ProfilerShort.End();
            }
            InstanceData.Clear();

            ProfilerShort.Begin("Update instance entitites");
            UpdateRenderEntitiesInstanceData(renderFlags, m_parentCullObject);
            ProfilerShort.End();
        }
예제 #28
0
        public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags)
        {
            ProfilerShort.Begin(GetType().Name + ".ReadRange");

            if ((dataToRead & MyStorageDataTypeFlags.Content) != 0)
            {
                target.ClearContent(0);
            }

            if (requestFlags.HasFlags(MyVoxelRequestFlags.AdviseCache) && lodIndex == 0 && CachedWrites)
            {
                ReadRangeAdviseCache(target, dataToRead, ref lodVoxelRangeMin, ref lodVoxelRangeMax);
                ProfilerShort.End();
                return;
            }

            if (CachedWrites && lodIndex <= VoxelChunk.SizeBits && m_cachedChunks.Count > 0)
            {
                // read occlusion separate
                if (dataToRead.Requests(MyStorageDataTypeEnum.Occlusion))
                {
                    using (m_storageLock.AcquireSharedUsing())
                        ReadRangeInternal(target, ref Vector3I.Zero, MyStorageDataTypeFlags.Occlusion, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);

                    dataToRead ^= MyStorageDataTypeFlags.Occlusion;
                }

                if (m_tmpChunks == null)
                {
                    m_tmpChunks = new List <VoxelChunk>();
                }

                var lodDiff = VoxelChunk.SizeBits - lodIndex;

                // We fetch which chunks overlap our current range from the chunk tree, then we read all data from storage and apply those changes
                var querybb = new BoundingBox(lodVoxelRangeMin << lodIndex, lodVoxelRangeMax << lodIndex);

                using (m_cacheLock.AcquireSharedUsing())
                    m_cacheMap.OverlapAllBoundingBox(ref querybb, m_tmpChunks, 0, false);

                if (m_tmpChunks.Count > 0)
                {
                    var chunkMin = lodVoxelRangeMin >> lodDiff;
                    var chunkMax = lodVoxelRangeMax >> lodDiff;

                    bool readFromStorage = false;

                    if ((chunkMax - chunkMin + 1).Size > m_tmpChunks.Count)
                    {
                        using (m_storageLock.AcquireSharedUsing())
                            ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);
                        readFromStorage = true;
                    }

                    for (int i = 0; i < m_tmpChunks.Count; ++i)
                    {
                        var chunk = m_tmpChunks[i];
                        var pos   = chunk.Coords;

                        var celPos = pos << lodDiff;

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

                        var targetOffset = lodCkStart - lodVoxelRangeMin;

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

                        lodCkStart -= celPos;
                        lodCkEnd   -= celPos;

                        if ((chunk.Cached & dataToRead) != dataToRead && !readFromStorage)
                        {
                            using (m_storageLock.AcquireSharedUsing())
                                using (chunk.Lock.AcquireExclusiveUsing())
                                    if ((chunk.Cached & dataToRead) != dataToRead)
                                    {
                                        ReadDatForChunk(chunk, dataToRead);
                                    }
                        }

                        using (chunk.Lock.AcquireSharedUsing())
                            chunk.ReadLod(target, !readFromStorage ? dataToRead : dataToRead & chunk.Cached, ref targetOffset, lodIndex, ref lodCkStart, ref lodCkEnd);
                    }

                    m_tmpChunks.Clear();
                    ProfilerShort.End();
                    return;
                }
            }

            // all else
            using (m_storageLock.AcquireSharedUsing())
                ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);

            ProfilerShort.End();
        }
예제 #29
0
        private static void ProcessDrawMessage(MyRenderMessageBase drawMessage)
        {
            switch (drawMessage.MessageType)
            {
            case MyRenderMessageEnum.SpriteScissorPush:
            {
                var msg = drawMessage as MyRenderMessageSpriteScissorPush;

                MySpritesRenderer.ScissorStackPush(msg.ScreenRectangle);

                break;
            }

            case MyRenderMessageEnum.SpriteScissorPop:
            {
                MySpritesRenderer.ScissorStackPop();

                break;
            }

            case MyRenderMessageEnum.DrawSprite:
            {
                MyRenderMessageDrawSprite sprite = (MyRenderMessageDrawSprite)drawMessage;

                MySpritesRenderer.AddSingleSprite(MyTextures.GetTexture(sprite.Texture, MyTextureEnum.GUI, waitTillLoaded: sprite.WaitTillLoaded), sprite.Color, sprite.Origin, sprite.RightVector, sprite.SourceRectangle, sprite.DestinationRectangle);

                break;
            }

            case MyRenderMessageEnum.DrawSpriteNormalized:
            {
                MyRenderMessageDrawSpriteNormalized sprite = (MyRenderMessageDrawSpriteNormalized)drawMessage;

                var rotation = sprite.Rotation;
                if (sprite.RotationSpeed != 0)
                {
                    rotation += sprite.RotationSpeed * (float)(MyRender11.CurrentDrawTime - MyRender11.CurrentUpdateTime).Seconds;
                }

                Vector2 rightVector = rotation != 0f ? new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)) : sprite.RightVector;

                int safeGuiSizeY = MyRender11.ResolutionI.Y;
                int safeGuiSizeX = (int)(safeGuiSizeY * 1.3333f);             //  This will mantain same aspect ratio for GUI elements

                var   safeGuiRectangle = new VRageMath.Rectangle(MyRender11.ResolutionI.X / 2 - safeGuiSizeX / 2, 0, safeGuiSizeX, safeGuiSizeY);
                var   safeScreenScale  = (float)safeGuiSizeY / MyRenderGuiConstants.REFERENCE_SCREEN_HEIGHT;
                float fixedScale       = sprite.Scale * safeScreenScale;

                var tex = MyTextures.GetTexture(sprite.Texture, MyTextureEnum.GUI, true);

                var normalizedCoord = sprite.NormalizedCoord;
                var screenCoord     = new Vector2(safeGuiRectangle.Left + safeGuiRectangle.Width * normalizedCoord.X,
                                                  safeGuiRectangle.Top + safeGuiRectangle.Height * normalizedCoord.Y);

                var sizeInPixels       = MyTextures.GetSize(tex);
                var sizeInPixelsScaled = sizeInPixels * fixedScale;

                Vector2 alignedScreenCoord = screenCoord;
                var     drawAlign          = sprite.DrawAlign;

                if (drawAlign == MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_TOP)
                {
                    //  Nothing to do as position is already at this point
                }
                else if (drawAlign == MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER)
                {
                    //  Move position to the texture center
                    alignedScreenCoord -= sizeInPixelsScaled / 2.0f;
                }
                else if (drawAlign == MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_TOP)
                {
                    alignedScreenCoord.X -= sizeInPixelsScaled.X / 2.0f;
                }
                else if (drawAlign == MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_BOTTOM)
                {
                    alignedScreenCoord.X -= sizeInPixelsScaled.X / 2.0f;
                    alignedScreenCoord.Y -= sizeInPixelsScaled.Y;
                }
                else if (drawAlign == MyGuiDrawAlignEnum.HORISONTAL_RIGHT_AND_VERTICAL_BOTTOM)
                {
                    alignedScreenCoord -= sizeInPixelsScaled;
                }
                else if (drawAlign == MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_CENTER)
                {
                    alignedScreenCoord.Y -= sizeInPixelsScaled.Y / 2.0f;
                }
                else if (drawAlign == MyGuiDrawAlignEnum.HORISONTAL_RIGHT_AND_VERTICAL_CENTER)
                {
                    alignedScreenCoord.X -= sizeInPixelsScaled.X;
                    alignedScreenCoord.Y -= sizeInPixelsScaled.Y / 2.0f;
                }
                else if (drawAlign == MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_BOTTOM)
                {
                    alignedScreenCoord.Y -= sizeInPixelsScaled.Y;        // *0.75f;
                }
                else if (drawAlign == MyGuiDrawAlignEnum.HORISONTAL_RIGHT_AND_VERTICAL_TOP)
                {
                    alignedScreenCoord.X -= sizeInPixelsScaled.X;
                }

                screenCoord = alignedScreenCoord;

                var     rect = new RectangleF(screenCoord.X, screenCoord.Y, fixedScale * sizeInPixels.X, fixedScale * sizeInPixels.Y);
                Vector2 origin;
                if (sprite.OriginNormalized.HasValue)
                {
                    origin = sprite.OriginNormalized.Value * sizeInPixels;
                }
                else
                {
                    origin = sizeInPixels / 2;
                }

                sprite.OriginNormalized = sprite.OriginNormalized ?? new Vector2(0.5f);

                MySpritesRenderer.AddSingleSprite(MyTextures.GetTexture(sprite.Texture, MyTextureEnum.GUI, waitTillLoaded: sprite.WaitTillLoaded), sprite.Color, origin, rightVector, null, rect);

                break;
            }


            case MyRenderMessageEnum.DrawSpriteAtlas:
            {
                MyRenderMessageDrawSpriteAtlas sprite = (MyRenderMessageDrawSpriteAtlas)drawMessage;

                var tex         = MyTextures.GetTexture(sprite.Texture, MyTextureEnum.GUI, true);
                var textureSize = MyTextures.GetSize(tex);

                Rectangle?sourceRect = new Rectangle(
                    (int)(textureSize.X * sprite.TextureOffset.X),
                    (int)(textureSize.Y * sprite.TextureOffset.Y),
                    (int)(textureSize.X * sprite.TextureSize.X),
                    (int)(textureSize.Y * sprite.TextureSize.Y));

                VRageMath.RectangleF destRect = new VRageMath.RectangleF(
                    (sprite.Position.X) * sprite.Scale.X,
                    (sprite.Position.Y) * sprite.Scale.Y,
                    sprite.HalfSize.X * sprite.Scale.X * 2,
                    sprite.HalfSize.Y * sprite.Scale.Y * 2);

                Vector2 origin = new Vector2(textureSize.X * sprite.TextureSize.X * 0.5f, textureSize.Y * sprite.TextureSize.Y * 0.5f);

                MySpritesRenderer.AddSingleSprite(MyTextures.GetTexture(sprite.Texture, MyTextureEnum.GUI, true), sprite.Color, origin, sprite.RightVector, sourceRect, destRect);

                break;
            }

            case MyRenderMessageEnum.DrawString:
            {
                var message = drawMessage as MyRenderMessageDrawString;

                var font = MyRender11.GetFont(message.FontIndex);
                font.DrawString(
                    message.ScreenCoord,
                    message.ColorMask,
                    message.Text,
                    message.ScreenScale,
                    message.ScreenMaxWidth);

                break;
            }

            case MyRenderMessageEnum.DrawScene:
            {
                UpdateSceneFrame();

                ProfilerShort.Begin("DrawScene");
                DrawGameScene(Backbuffer);
                ProfilerShort.Begin("TransferPerformanceStats");
                TransferPerformanceStats();
                ProfilerShort.End();
                ProfilerShort.End();

                ProfilerShort.Begin("Draw scene debug");
                MyGpuProfiler.IC_BeginBlock("Draw scene debug");
                DrawSceneDebug();
                MyGpuProfiler.IC_EndBlock();
                ProfilerShort.End();

                ProfilerShort.Begin("ProcessDebugMessages");
                ProcessDebugMessages();
                ProfilerShort.End();

                ProfilerShort.Begin("MyDebugRenderer.Draw");
                MyGpuProfiler.IC_BeginBlock("MyDebugRenderer.Draw");
                MyDebugRenderer.Draw(MyRender11.Backbuffer);
                MyGpuProfiler.IC_EndBlock();
                ProfilerShort.End();

                var testingDepth = MyRender11.MultisamplingEnabled ? MyScreenDependants.m_resolvedDepth : MyGBuffer.Main.DepthStencil;

                ProfilerShort.Begin("MyPrimitivesRenderer.Draw");
                MyGpuProfiler.IC_BeginBlock("MyPrimitivesRenderer.Draw");
                MyPrimitivesRenderer.Draw(MyRender11.Backbuffer, testingDepth);
                MyGpuProfiler.IC_EndBlock();
                ProfilerShort.End();

                ProfilerShort.Begin("MyLinesRenderer.Draw");
                MyGpuProfiler.IC_BeginBlock("MyLinesRenderer.Draw");
                MyLinesRenderer.Draw(MyRender11.Backbuffer, testingDepth);
                MyGpuProfiler.IC_EndBlock();
                ProfilerShort.End();

                if (m_screenshot.HasValue && m_screenshot.Value.IgnoreSprites)
                {
                    if (m_screenshot.Value.SizeMult == Vector2.One)
                    {
                        SaveScreenshotFromResource(Backbuffer.m_resource);
                    }
                    else
                    {
                        TakeCustomSizedScreenshot(m_screenshot.Value.SizeMult);
                    }
                }

                ProfilerShort.Begin("MySpritesRenderer.Draw");
                MyGpuProfiler.IC_BeginBlock("MySpritesRenderer.Draw");
                MySpritesRenderer.Draw(MyRender11.Backbuffer.m_RTV, new MyViewport(MyRender11.ViewportResolution.X, MyRender11.ViewportResolution.Y));
                MyGpuProfiler.IC_EndBlock();
                ProfilerShort.End();

                if (MyRenderProxy.DRAW_RENDER_STATS)
                {
                    MyRender11.GetRenderProfiler().StartProfilingBlock("MyRenderStatsDraw.Draw");
                    MyRenderStatsDraw.Draw(MyRenderStats.m_stats, 0.6f, VRageMath.Color.Yellow);
                    ProfilerShort.End();
                }

                break;
            }
            }
        }
예제 #30
0
        private void CreateRigidBodies()
        {
            if (Entity.MarkedForClose)
            {
                return;
            }

            ProfilerShort.Begin("MyVoxelPhysicsBody::CreateRigidBodies()");
            try
            {
                if (m_bodiesInitialized)
                {
                    Debug.Fail("Double rigid body intialization for voxel map!");
                    return;
                }

                Vector3I numCels = m_voxelMap.Size >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;

                HkUniformGridShape shape;
                HkRigidBody        lod1rb = null;
                if (MyFakes.USE_LOD1_VOXEL_PHYSICS)
                {
                    shape = new HkUniformGridShape(
                        new HkUniformGridShapeArgs
                    {
                        CellsCount = numCels >> 1,
                        CellSize   = MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES * 2,
                        CellOffset = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF,
                        CellExpand = MyVoxelConstants.VOXEL_SIZE_IN_METRES
                    });
                    shape.SetShapeRequestHandler(RequestShapeBlockingLod1, QueryEmptyOrFull);

                    CreateFromCollisionObject(shape, -m_voxelMap.SizeInMetresHalf, m_voxelMap.WorldMatrix, collisionFilter: MyPhysics.CollisionLayers.VoxelLod1CollisionLayer);
                    shape.Base.RemoveReference();
                    lod1rb    = RigidBody;
                    RigidBody = null;
                }

                shape = new HkUniformGridShape(
                    new HkUniformGridShapeArgs
                {
                    CellsCount = numCels,
                    CellSize   = MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES,
                    CellOffset = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF,
                    CellExpand = MyVoxelConstants.VOXEL_SIZE_IN_METRES
                });
                shape.SetShapeRequestHandler(RequestShapeBlocking, QueryEmptyOrFull);

                CreateFromCollisionObject(shape, -m_voxelMap.SizeInMetresHalf, m_voxelMap.WorldMatrix, collisionFilter: MyPhysics.CollisionLayers.VoxelCollisionLayer);
                shape.Base.RemoveReference();
                if (MyFakes.USE_LOD1_VOXEL_PHYSICS)
                {
                    RigidBody2 = lod1rb;
                }

                if (MyFakes.ENABLE_PHYSICS_HIGH_FRICTION)
                {
                    Friction = 0.65f;
                }

                m_bodiesInitialized = true;

                // When doing the enable disable roundtrip we can mess up the ClusterTree because Activate() can end up calling this
                // if the phantom is immediatelly intersecting something.
                if (Enabled)
                {
                    var matrix = GetRigidBodyMatrix();

                    RigidBody.SetWorldMatrix(matrix);
                    m_world.AddRigidBody(RigidBody);

                    if (MyFakes.USE_LOD1_VOXEL_PHYSICS)
                    {
                        RigidBody2.SetWorldMatrix(matrix);
                        m_world.AddRigidBody(RigidBody2);
                    }
                }
            }
            finally
            {
                ProfilerShort.End();
            }
        }