protected Vector3I.RangeIterator GetCellsIterator(BoundingBoxD bbox)
        {
            Vector3I min = Vector3I.Floor(bbox.Min / CELL_SIZE);
            Vector3I max = Vector3I.Floor(bbox.Max / CELL_SIZE);

            return(new Vector3I.RangeIterator(ref min, ref max));
        }
        protected void GenerateObjectSeeds(ref BoundingSphereD sphere)
        {
            ProfilerShort.Begin("GenerateObjectSeedsInBox");

            BoundingBoxD box = BoundingBoxD.CreateFromSphere(sphere);

            Vector3I cellId = Vector3I.Floor(box.Min / CELL_SIZE);

            for (var iter = GetCellsIterator(sphere); iter.IsValid(); iter.GetNext(out cellId))
            {
                if (m_cells.ContainsKey(cellId))
                {
                    continue;
                }

                var cellBox = new BoundingBoxD(cellId * CELL_SIZE, (cellId + 1) * CELL_SIZE);
                if (sphere.Contains(cellBox) == ContainmentType.Disjoint)
                {
                    continue;
                }

                var cell = GenerateProceduralCell(ref cellId);
                if (cell != null)
                {
                    m_cells.Add(cellId, cell);
                    var cellBBox = cell.BoundingVolume;
                    cell.proxyId = m_cellsTree.AddProxy(ref cellBBox, cell, 0);
                }
            }
            ProfilerShort.End();
        }
        public void MarkCellsDirty(BoundingSphereD toMark, BoundingSphereD?toExclude = null, bool scale = true)
        {
            BoundingSphereD toMarkScaled    = new BoundingSphereD(toMark.Center, toMark.Radius * (scale ? SCALE : 1));
            BoundingSphereD toExcludeScaled = new BoundingSphereD();

            if (toExclude.HasValue)
            {
                toExcludeScaled = toExclude.Value;
                if (scale)
                {
                    toExcludeScaled.Radius *= SCALE;
                }
            }
            ProfilerShort.Begin("Mark dirty cells");
            Vector3I cellId = Vector3I.Floor((toMarkScaled.Center - toMarkScaled.Radius) / CELL_SIZE);

            for (var iter = GetCellsIterator(toMarkScaled); iter.IsValid(); iter.GetNext(out cellId))
            {
                MyProceduralCell cell;
                if (m_cells.TryGetValue(cellId, out cell))
                {
                    if (!toExclude.HasValue || toExcludeScaled.Contains(cell.BoundingVolume) == ContainmentType.Disjoint)
                    {
                        m_dirtyCells.Add(cell);
                    }
                }
            }
            ProfilerShort.End();
        }
        /// <summary>
        /// Generates all Cells data that are within sphere, if they have not been generated.
        /// </summary>
        /// <param name="sphere">Bounding Sphere of the cells to generate</param>
        protected void GenerateObjectsData(ref BoundingSphereD sphere)
        {
            BoundingBoxD box = BoundingBoxD.CreateFromSphere(sphere);

            Vector3I cellId = Vector3I.Floor(box.Min / CELL_SIZE);

            for (var it = GetCellsIterator(sphere); it.IsValid(); it.GetNext(out cellId))
            {
                if (m_cells.ContainsKey(cellId))
                {
                    continue;
                }

                BoundingBoxD cellBounds = new BoundingBoxD(cellId * CELL_SIZE, (cellId + 1) * CELL_SIZE);
                if (!(sphere.Contains(cellBounds) != ContainmentType.Disjoint))
                {
                    continue;
                }

                MyProceduralCell cell = GenerateCell(ref cellId);
                if (cell != null)
                {
                    m_cells.Add(cellId, cell);

                    BoundingBoxD aabb = cell.BoundingVolume;
                    cell.proxyId = m_cellsTree.AddProxy(ref aabb, cell, 0u);
                }
            }
        }
예제 #5
0
        public static void GetExistingCubes(MyCubeGrid grid, Vector3I min, Vector3I max, BoundingSphere localSphere, bool checkDestroyed, List <IMySlimBlock> resultSet)
        {
            resultSet.Clear();
            Vector3I result1 = Vector3I.Floor((min - Vector3I.One) / 2f);
            Vector3I result2 = Vector3I.Ceiling((max - Vector3I.One) / 2f);
            var      gridMin = grid.Min;
            var      gridMax = grid.Max;

            Vector3I.Max(ref result1, ref gridMin, out result1);
            Vector3I.Min(ref result2, ref gridMax, out result2);
            Vector3I key;

            for (key.X = result1.X; key.X <= result2.X; ++key.X)
            {
                for (key.Y = result1.Y; key.Y <= result2.Y; ++key.Y)
                {
                    for (key.Z = result1.Z; key.Z <= result2.Z; ++key.Z)
                    {
                        MyCube myCube;
                        if (grid.TryGetCube(key, out myCube))
                        {
                            var block = (IMySlimBlock)myCube.CubeBlock;
                            if (checkDestroyed && block.IsDestroyed || !new BoundingBox(block.Min * grid.GridSize - grid.GridSizeHalf, block.Max * grid.GridSize + grid.GridSizeHalf).Intersects(localSphere))
                            {
                                continue;
                            }

                            resultSet.Add(block);
                        }
                    }
                }
            }
        }
예제 #6
0
        public static void GetExistingCubes(MyCubeGrid grid, Vector3I min, Vector3I max, List <IMySlimBlock> resultSet)
        {
            resultSet.Clear();
            Vector3I result1 = Vector3I.Floor((min - Vector3I.One) / 2f);
            Vector3I result2 = Vector3I.Ceiling((max - Vector3I.One) / 2f);
            var      gridMin = grid.Min;
            var      gridMax = grid.Max;

            Vector3I.Max(ref result1, ref gridMin, out result1);
            Vector3I.Min(ref result2, ref gridMax, out result2);
            Vector3I key;

            for (key.X = result1.X; key.X <= result2.X; ++key.X)
            {
                for (key.Y = result1.Y; key.Y <= result2.Y; ++key.Y)
                {
                    for (key.Z = result1.Z; key.Z <= result2.Z; ++key.Z)
                    {
                        MyCube myCube;
                        if (grid.TryGetCube(key, out myCube))
                        {
                            resultSet.Add(myCube.CubeBlock);
                        }
                    }
                }
            }
        }
        /// <summary> Determines whether any of the blocks that intersect the
        /// given bounding box satisfy the given condition. </summary>
        public bool TouchesAny(AABB bounds, Predicate <byte> condition)
        {
            Vector3I bbMin = Vector3I.Floor(bounds.Min);
            Vector3I bbMax = Vector3I.Floor(bounds.Max);

            // Order loops so that we minimise cache misses
            for (int y = bbMin.Y; y <= bbMax.Y; y++)
            {
                for (int z = bbMin.Z; z <= bbMax.Z; z++)
                {
                    for (int x = bbMin.X; x <= bbMax.X; x++)
                    {
                        if (!game.World.IsValidPos(x, y, z))
                        {
                            continue;
                        }
                        byte    block = game.World.GetBlock(x, y, z);
                        Vector3 min   = new Vector3(x, y, z) + info.MinBB[block];
                        Vector3 max   = new Vector3(x, y, z) + info.MaxBB[block];

                        AABB blockBB = new AABB(min, max);
                        if (!blockBB.Intersects(bounds))
                        {
                            continue;
                        }
                        if (condition(block))
                        {
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
        void CheckWeather(double deltaTime)
        {
            WorldEnv env    = game.World.Env;
            Vector3  pos    = game.CurrentCameraPos;
            Vector3I coords = Vector3I.Floor(pos);

            BlockID block   = game.World.SafeGetBlockAdj(coords);
            bool    outside = coords.X < 0 || coords.Y < 0 || coords.Z < 0 || coords.X >= game.World.Width || coords.Z >= game.World.Length;

            inTranslucent = BlockInfo.Draw[block] == DrawType.Translucent ||
                            (pos.Y < env.EdgeHeight && outside) ||
                            BlockInfo.Draw[block] == DrawType.Opaque;
            inLiquid = (block == Block.Lava || block == Block.StillLava) ||
                       (pos.Y < env.EdgeHeight && outside) ||
                       BlockInfo.Draw[block] == DrawType.Opaque;

            // If we are under water, render weather before to blend properly
            if (!inTranslucent || env.Weather == Weather.Sunny)
            {
                return;
            }
            game.Graphics.AlphaBlending = true;
            game.WeatherRenderer.Render(deltaTime);
            game.Graphics.AlphaBlending = false;
        }
예제 #9
0
        void DoRespawn()
        {
            if (!game.World.HasBlocks)
            {
                return;
            }
            LocalPlayer p     = (LocalPlayer)entity;
            Vector3     spawn = p.Spawn;

            if (game.World.IsValidPos(Vector3I.Floor(spawn)))
            {
                FindHighestFree(ref spawn);
            }

            spawn.Y += 2 / 16f;
            LocationUpdate update = LocationUpdate.MakePosAndOri(spawn, p.SpawnRotY, p.SpawnHeadX, false);

            entity.SetLocation(update, false);
            entity.Velocity = Vector3.Zero;

            // Update onGround, otherwise if 'respawn' then 'space' is pressed, you still jump into the air if onGround was true before
            AABB bb = entity.Bounds;

            bb.Min.Y       -= 0.01f; bb.Max.Y = bb.Min.Y;
            entity.onGround = entity.TouchesAny(bb, touchesAnySolid);
        }
예제 #10
0
        public void GenerateFloraGraphics(Vector3D pos)
        {
            Debug.Assert(m_planetEnvironmentSectors != null, "null environment sector");
            if (m_planetEnvironmentSectors == null)
            {
                return;
            }

            Vector3D gravity       = GetWorldGravityNormalized(ref pos);
            Vector3D perpedincular = MyUtils.GetRandomPerpendicularVector(ref gravity);
            Vector3D third         = Vector3D.Cross(gravity, perpedincular);

            perpedincular += third;

            Vector3I min = new Vector3I(-ENVIROMENT_EXTEND);
            Vector3I max = new Vector3I(ENVIROMENT_EXTEND);

            Vector3 offset = new Vector3(-MyPlanetEnvironmentSector.SECTOR_SIZE_METERS);

            for (var it = new Vector3I.RangeIterator(ref min, ref max); it.IsValid(); it.MoveNext())
            {
                Vector3D currentPos = pos + it.Current * offset * perpedincular;
                currentPos = PlaceToOrbit(currentPos, ref gravity);

                Vector3I newSector = Vector3I.Floor(currentPos / MyPlanetEnvironmentSector.SECTOR_SIZE_METERS);
                MyPlanetEnvironmentSector sector;
                if (true == m_planetEnvironmentSectors.TryGetValue(newSector, out sector) && sector.HasGraphics == false)
                {
                    sector.UpdateSectorGraphics();
                }
            }
        }
        internal static bool PosHasVoxel(MyVoxelBase voxel, Vector3D testPos)
        {
            var planet = voxel as MyPlanet;
            var map    = voxel as MyVoxelMap;
            var hit    = new VoxelHit();

            if (planet != null)
            {
                var      from          = testPos;
                var      localPosition = (Vector3)(from - planet.PositionLeftBottomCorner);
                var      v             = localPosition / 1f;
                Vector3I voxelCoord;
                Vector3I.Floor(ref v, out voxelCoord);
                planet.Storage.ExecuteOperationFast(ref hit, MyStorageDataTypeFlags.Content, ref voxelCoord, ref voxelCoord, notifyRangeChanged: false);
            }
            else if (map != null)
            {
                var      from          = testPos;
                var      localPosition = (Vector3)(from - map.PositionLeftBottomCorner);
                var      v             = localPosition / 1f;
                Vector3I voxelCoord;
                Vector3I.Floor(ref v, out voxelCoord);
                map.Storage.ExecuteOperationFast(ref hit, MyStorageDataTypeFlags.Content, ref voxelCoord, ref voxelCoord, notifyRangeChanged: false);
            }

            return(hit.HasHit);
        }
        void GetSound()
        {
            Vector3 pos    = p.interp.next.Pos;
            AABB    bounds = p.Bounds;

            sndType   = SoundType.None;
            anyNonAir = false;

            // first check surrounding liquids/gas for sounds
            p.TouchesAny(bounds, checkSoundNonSolid);
            if (sndType != SoundType.None)
            {
                return;
            }

            // then check block standing on
            pos.Y -= 0.01f;
            Vector3I feetPos    = Vector3I.Floor(pos);
            BlockID  blockUnder = game.World.SafeGetBlockAdj(feetPos);
            float    maxY       = feetPos.Y + BlockInfo.MaxBB[blockUnder].Y;

            byte typeUnder    = BlockInfo.StepSounds[blockUnder];
            byte collideUnder = BlockInfo.Collide[blockUnder];

            if (maxY >= pos.Y && collideUnder == CollideType.Solid && typeUnder != SoundType.None)
            {
                anyNonAir = true; sndType = typeUnder; return;
            }

            // then check all solid blocks at feet
            bounds.Max.Y = bounds.Min.Y = pos.Y;
            p.TouchesAny(bounds, checkSoundSolid);
        }
        private float SampleContent(float x, float y, float z)
        {
            var sample   = new Vector3(x, y, z);
            var minVoxel = Vector3I.Floor(sample);

            sample -= minVoxel;

            float s000 = m_cache.Content(minVoxel.X, minVoxel.Y, minVoxel.Z);
            float s100 = m_cache.Content(minVoxel.X + 1, minVoxel.Y, minVoxel.Z);
            float s010 = m_cache.Content(minVoxel.X, minVoxel.Y + 1, minVoxel.Z);
            float s110 = m_cache.Content(minVoxel.X + 1, minVoxel.Y + 1, minVoxel.Z);
            float s001 = m_cache.Content(minVoxel.X, minVoxel.Y, minVoxel.Z + 1);
            float s101 = m_cache.Content(minVoxel.X + 1, minVoxel.Y, minVoxel.Z + 1);
            float s011 = m_cache.Content(minVoxel.X, minVoxel.Y + 1, minVoxel.Z + 1);
            float s111 = m_cache.Content(minVoxel.X + 1, minVoxel.Y + 1, minVoxel.Z + 1);

            s000 += sample.X * (s100 - s000);
            s010 += sample.X * (s110 - s010);
            s001 += sample.X * (s101 - s001);
            s011 += sample.X * (s111 - s011);

            s000 += sample.Y * (s010 - s000);
            s001 += sample.Y * (s011 - s001);

            s000 += sample.Z * (s001 - s000);
            return(s000);
        }
예제 #14
0
        bool CanSlideThrough(ref AABB adjFinalBB)
        {
            Vector3I bbMin = Vector3I.Floor(adjFinalBB.Min);
            Vector3I bbMax = Vector3I.Floor(adjFinalBB.Max);

            for (int y = bbMin.Y; y <= bbMax.Y; y++)
            {
                for (int z = bbMin.Z; z <= bbMax.Z; z++)
                {
                    for (int x = bbMin.X; x <= bbMax.X; x++)
                    {
                        BlockID block = game.World.GetPhysicsBlock(x, y, z);
                        Vector3 min   = new Vector3(x, y, z) + BlockInfo.MinBB[block];
                        Vector3 max   = new Vector3(x, y, z) + BlockInfo.MaxBB[block];

                        AABB blockBB = new AABB(min, max);
                        if (!blockBB.Intersects(adjFinalBB))
                        {
                            continue;
                        }
                        if (BlockInfo.Collide[block] == CollideType.Solid)
                        {
                            return(false);
                        }
                    }
                }
            }
            return(true);
        }
        /// <summary>
        /// Gets an iterator for all Vector3I within the bounding box bbox
        /// </summary>
        /// <param name="bbox">Bounding box</param>
        /// <returns>Vector3I Iterator for all vectors inside bbox</returns>
        protected Vector3I_RangeIterator GetCellsIterator(BoundingBoxD bbox)
        {
            Vector3I min = Vector3I.Floor(bbox.Min / m_cellSize);
            Vector3I max = Vector3I.Floor(bbox.Max / m_cellSize);

            return(new Vector3I_RangeIterator(ref min, ref max));
        }
예제 #16
0
        /// <summary> Sets up the state for, then renders an entity model,
        /// based on the given entity's position and orientation. </summary>
        public void Render(Entity p)
        {
            index = 0;
            pos   = p.Position;
            if (Bobbing)
            {
                pos.Y += p.anim.bobbingModel;
            }

            Vector3I P = Vector3I.Floor(p.EyePosition);

            col    = game.World.IsValidPos(P) ? game.Lighting.LightCol(P.X, P.Y, P.Z) : game.Lighting.Outside;
            uScale = 1 / 64f; vScale = 1 / 32f;

            cols[0] = col;
            cols[1] = FastColour.ScalePacked(col, FastColour.ShadeYBottom);
            cols[2] = FastColour.ScalePacked(col, FastColour.ShadeZ); cols[3] = cols[2];
            cols[4] = FastColour.ScalePacked(col, FastColour.ShadeX); cols[5] = cols[4];

            float yawDelta = p.HeadY - p.RotY;

            cosHead = (float)Math.Cos(yawDelta * Utils.Deg2Rad);
            sinHead = (float)Math.Sin(yawDelta * Utils.Deg2Rad);

            game.Graphics.SetBatchFormat(VertexFormat.P3fT2fC4b);
            game.Graphics.PushMatrix();

            Matrix4 m = p.TransformMatrix(p.ModelScale, pos);

            game.Graphics.MultiplyMatrix(ref m);
            DrawModel(p);
            game.Graphics.PopMatrix();
        }
예제 #17
0
        void UpdateFog()
        {
            if (map.IsNotLoaded)
            {
                return;
            }
            FastColour adjFogCol = FastColour.White;
            BlockInfo  info      = game.BlockInfo;

            Vector3  pos     = game.CurrentCameraPos;
            Vector3I coords  = Vector3I.Floor(pos);
            byte     block   = game.World.SafeGetBlock(coords);
            AABB     blockBB = new AABB(
                (Vector3)coords + info.MinBB[block],
                (Vector3)coords + info.MaxBB[block]);

            if (blockBB.Contains(pos) && info.FogDensity[block] != 0)
            {
                graphics.SetFogMode(Fog.Exp);
                graphics.SetFogDensity(info.FogDensity[block]);
                adjFogCol = info.FogColour[block];
            }
            else
            {
                // Blend fog and sky together
                float blend = (float)BlendFactor(game.ViewDistance);
                adjFogCol = FastColour.Lerp(map.Env.FogCol, map.Env.SkyCol, blend);
                graphics.SetFogMode(Fog.Linear);
                graphics.SetFogEnd(game.ViewDistance);
            }
            graphics.ClearColour(adjFogCol);
            graphics.SetFogColour(adjFogCol);
        }
예제 #18
0
        /// <summary> Determines whether any of the blocks that intersect the
        /// given bounding box satisfy the given condition. </summary>
        public bool TouchesAny(AABB bounds, Predicate <BlockID> condition)
        {
            Vector3I min = Vector3I.Floor(bounds.Min);
            Vector3I max = Vector3I.Floor(bounds.Max);

            AABB    blockBB = default(AABB);
            Vector3 v;

            //min.X = min.X < 0 ? 0 : min.X; max.X = max.X > game.World.MaxX ? game.World.MaxX : max.X;
            //min.Y = min.Y < 0 ? 0 : min.Y; max.Y = max.Y > game.World.MaxY ? game.World.MaxY : max.Y;
            //min.Z = min.Z < 0 ? 0 : min.Z; max.Z = max.Z > game.World.MaxZ ? game.World.MaxZ : max.Z;

            for (int y = min.Y; y <= max.Y; y++)
            {
                v.Y = y;
                for (int z = min.Z; z <= max.Z; z++)
                {
                    v.Z = z;
                    for (int x = min.X; x <= max.X; x++)
                    {
                        v.X = x;

                        BlockID block    = game.World.GetBlockAdj(x, y, z);
                        Vector3 blockMin = BlockInfo.MinBB[block];
                        Vector3 blockMax = BlockInfo.MaxBB[block];
                                                #if ALPHA
                        byte data = game.World.ChunkHandler.GetDataAdjSafe(x, y, z);
                        if (block == Block.Ladder)
                        {
                            byte flip = 0;
                            if (data == 0x3)
                            {
                                flip = 2;
                            }
                            if (data == 0x4)
                            {
                                flip = 1;
                            }
                            if (data == 0x5)
                            {
                                flip = 3;
                            }
                            Utils.FlipBounds(blockMin, blockMax, out blockMin, out blockMax, flip);
                        }
                                                #endif
                        blockBB.Min = v + blockMin;
                        blockBB.Max = v + blockMax;
                        if (!blockBB.Intersects(bounds))
                        {
                            continue;
                        }
                        if (condition(block))
                        {
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
예제 #19
0
        // Algorithm source: http://minecraft.gamepedia.com/Explosion
        void Explode(float power, int x, int y, int z)
        {
            if (rayDirs == null)
            {
                InitExplosionCache();
            }

            game.UpdateBlock(x, y, z, 0);
            Vector3 basePos = new Vector3(x, y, z);

            for (int i = 0; i < rayDirs.Length; i++)
            {
                Vector3 dir       = rayDirs[i] * stepLen;
                Vector3 position  = basePos;
                float   intensity = (float)(0.7 + rnd.NextDouble() * 0.6) * power;
                while (intensity > 0)
                {
                    position  += dir;
                    intensity -= stepLen * 0.75f;
                    Vector3I blockPos = Vector3I.Floor(position);
                    if (!map.IsValidPos(blockPos))
                    {
                        break;
                    }

                    byte block = map.GetBlock(blockPos);
                    intensity -= (hardness[block] / 5 + 0.3f) * stepLen;
                    if (intensity > 0 && block != 0)
                    {
                        game.UpdateBlock(blockPos.X, blockPos.Y, blockPos.Z, 0);
                    }
                }
            }
        }
        public void AddPoint(ref Vector3D point, T data)
        {
            Vector3I binIndex = Vector3I.Floor(point * m_divisor);
            int      storagePtr;

            if (!m_bins.TryGetValue(binIndex, out storagePtr))
            {
                int newEntry = AddNewEntry(ref point, data);
                m_bins.Add(binIndex, newEntry);
            }
            else
            {
                Entry currentEntry = m_storage[storagePtr];
                int   nextEntryPtr = currentEntry.NextEntry;
                while (nextEntryPtr != -1)
                {
                    storagePtr   = nextEntryPtr;
                    currentEntry = m_storage[storagePtr];
                    nextEntryPtr = currentEntry.NextEntry;
                }

                int newEntry = AddNewEntry(ref point, data);
                currentEntry.NextEntry = newEntry;
                m_storage[storagePtr]  = currentEntry;
            }
        }
예제 #21
0
        void DrawPosition()
        {
            int     index = 0;
            Texture tex   = posAtlas.tex;

            tex.X1 = 2; tex.Width = (ushort)posAtlas.offset;
            IGraphicsApi.Make2DQuad(ref tex, FastColour.WhitePacked,
                                    game.ModelCache.vertices, ref index);

            Vector3I pos = Vector3I.Floor(game.LocalPlayer.Position);

            posAtlas.curX = posAtlas.offset + 2;
            VertexP3fT2fC4b[] vertices = game.ModelCache.vertices;

            posAtlas.Add(13, vertices, ref index);
            posAtlas.AddInt(pos.X, vertices, ref index);
            posAtlas.Add(11, vertices, ref index);
            posAtlas.AddInt(pos.Y, vertices, ref index);
            posAtlas.Add(11, vertices, ref index);
            posAtlas.AddInt(pos.Z, vertices, ref index);
            posAtlas.Add(14, vertices, ref index);

            gfx.BindTexture(posAtlas.tex.ID);
            gfx.UpdateDynamicVb_IndexedTris(game.ModelCache.vb, game.ModelCache.vertices, index);
        }
예제 #22
0
        protected BlockID BlockOn(out float fogDensity, out FastColour fogCol)
        {
            BlockInfo info   = game.BlockInfo;
            Vector3   pos    = game.CurrentCameraPos;
            Vector3I  coords = Vector3I.Floor(pos);

            BlockID block   = game.World.SafeGetBlock(coords);
            AABB    blockBB = new AABB(
                (Vector3)coords + info.MinBB[block],
                (Vector3)coords + info.MaxBB[block]);

            if (blockBB.Contains(pos) && info.FogDensity[block] != 0)
            {
                fogDensity = info.FogDensity[block];
                fogCol     = info.FogColour[block];
            }
            else
            {
                fogDensity = 0;
                // Blend fog and sky together
                float blend = (float)BlendFactor(game.ViewDistance);
                fogCol = FastColour.Lerp(map.Env.FogCol, map.Env.SkyCol, blend);
            }
            return(block);
        }
예제 #23
0
        bool CanSlideThrough(ref AABB adjFinalBB)
        {
            Vector3I bbMin = Vector3I.Floor(adjFinalBB.Min);
            Vector3I bbMax = Vector3I.Floor(adjFinalBB.Max);
            AABB     blockBB;

            Vector3 pos;

            for (int y = bbMin.Y; y <= bbMax.Y; y++)
            {
                for (int z = bbMin.Z; z <= bbMax.Z; z++)
                {
                    for (int x = bbMin.X; x <= bbMax.X; x++)
                    {
                        pos.X = x; pos.Y = y; pos.Z = z;
                        BlockID block = game.World.GetPhysicsBlock(x, y, z);
                        blockBB.Min = pos + BlockInfo.MinBB[block];
                        blockBB.Max = pos + BlockInfo.MaxBB[block];

                        if (!blockBB.Intersects(adjFinalBB))
                        {
                            continue;
                        }
                        if (BlockInfo.Collide[block] == CollideType.Solid)
                        {
                            return(false);
                        }
                    }
                }
            }
            return(true);
        }
예제 #24
0
        public static void WorldPositionToRenderCellCoord(Vector3D referenceVoxelMapPosition, ref Vector3D worldPosition, out Vector3I renderCellCoord)
        {
            Vector3D tmp;

            WorldPositionToLocalPosition(referenceVoxelMapPosition, ref worldPosition, out tmp);
            tmp /= MyVoxelConstants.RENDER_CELL_SIZE_IN_METRES;
            Vector3I.Floor(ref tmp, out renderCellCoord);
        }
예제 #25
0
        public static void WorldPositionToRenderCellCoord(int lod, Vector3D referenceVoxelMapPosition, ref Vector3D worldPosition, out Vector3I renderCellCoord)
        {
            Vector3D tmp;

            WorldPositionToLocalPosition(referenceVoxelMapPosition, ref worldPosition, out tmp);
            tmp /= RenderCellSizeInMeters(lod);
            Vector3I.Floor(ref tmp, out renderCellCoord);
        }
예제 #26
0
        private static bool IntersectsVoxelSurface(OrientedBoundingBoxD box)
        {
            var data = VoxelData;

            using (PoolManager.Get(out List <MyEntity> entities))
            {
                MyGamePruningStructure.GetTopmostEntitiesInBox(box.GetAABB(), entities, MyEntityQueryType.Static);
                foreach (var ent in entities)
                {
                    if (ent is MyVoxelBase voxel && !(ent is MyVoxelPhysics))
                    {
                        var invWorld      = voxel.PositionComp.WorldMatrixInvScaled;
                        var storageBounds = BoundingBoxD.CreateInvalid();
                        var voxelOffset   = (voxel.Size >> 1) + voxel.StorageMin;
                        var storageObb    = box;
                        storageObb.Transform(invWorld);
                        storageObb.HalfExtent /= voxel.VoxelSize;
                        storageObb.Center      = storageObb.Center / voxel.VoxelSize + voxelOffset;
                        storageBounds.Include(storageObb.GetAABB());

                        var storageMin = Vector3I.Max(Vector3I.Floor(storageBounds.Min), voxel.StorageMin);
                        var storageMax = Vector3I.Min(Vector3I.Ceiling(storageBounds.Max), voxel.StorageMax);
                        var localBox   = new BoundingBoxI(storageMin, storageMax);
                        localBox.Inflate(1);
                        var floatBox = new BoundingBox(localBox);
                        if (voxel.IntersectStorage(ref floatBox) == ContainmentType.Disjoint)
                        {
                            continue;
                        }
                        data.Resize(storageMin, storageMax);
                        voxel.Storage.ReadRange(data, MyStorageDataTypeFlags.Content, 0, storageMin, storageMax);
                        foreach (var pt in new BoundingBoxI(Vector3I.Zero, storageMax - storageMin).EnumeratePoints())
                        {
                            var voxelBox    = new BoundingBoxD(storageMin + pt, storageMin + pt + 1);
                            var containment = storageObb.Contains(ref voxelBox);
                            if (containment == ContainmentType.Disjoint)
                            {
                                continue;
                            }
                            var tmpPt   = pt;
                            var index   = data.ComputeLinear(ref tmpPt);
                            var content = data.Content(index);
                            if (containment == ContainmentType.Intersects && content >= 127)
                            {
                                return(true);
                            }
                            if (containment == ContainmentType.Contains && content > 0)
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
예제 #27
0
        void FindReachableBlocks(ref int count, out AABB entityBB,
                                 out AABB entityExtentBB)
        {
            Vector3 vel = entity.Velocity;

            entityBB = entity.CollisionBounds;

            // Exact maximum extent the entity can reach, and the equivalent map coordinates.
            entityExtentBB = new AABB(
                vel.X < 0 ? entityBB.Min.X + vel.X : entityBB.Min.X,
                vel.Y < 0 ? entityBB.Min.Y + vel.Y : entityBB.Min.Y,
                vel.Z < 0 ? entityBB.Min.Z + vel.Z : entityBB.Min.Z,
                vel.X > 0 ? entityBB.Max.X + vel.X : entityBB.Max.X,
                vel.Y > 0 ? entityBB.Max.Y + vel.Y : entityBB.Max.Y,
                vel.Z > 0 ? entityBB.Max.Z + vel.Z : entityBB.Max.Z
                );
            Vector3I min = Vector3I.Floor(entityExtentBB.Min);
            Vector3I max = Vector3I.Floor(entityExtentBB.Max);

            int elements = (max.X + 1 - min.X) * (max.Y + 1 - min.Y) * (max.Z + 1 - min.Z);

            if (elements > stateCache.Length)
            {
                stateCache = new State[elements];
            }

            AABB blockBB = default(AABB);

            // Order loops so that we minimise cache misses
            for (int y = min.Y; y <= max.Y; y++)
            {
                for (int z = min.Z; z <= max.Z; z++)
                {
                    for (int x = min.X; x <= max.X; x++)
                    {
                        byte blockId = GetPhysicsBlockId(x, y, z);
                        if (!GetBoundingBox(blockId, x, y, z, ref blockBB))
                        {
                            continue;
                        }
                        if (!entityExtentBB.Intersects(blockBB))
                        {
                            continue;                                                 // necessary for non whole blocks. (slabs)
                        }
                        float tx = 0, ty = 0, tz = 0;
                        CalcTime(ref vel, ref entityBB, ref blockBB, out tx, out ty, out tz);
                        if (tx > 1 || ty > 1 || tz > 1)
                        {
                            continue;
                        }
                        float tSquared = tx * tx + ty * ty + tz * tz;
                        stateCache[count++] = new State(x, y, z, blockId, tSquared);
                    }
                }
            }
        }
예제 #28
0
        /*
         * public static bool PosInVoxel(MyVoxelBase voxelBase, Vector3D pos, MyStorageData cache)
         * {
         *  if (voxelBase.Storage.Closed) return false;
         *  //cache.Clear(MyStorageDataTypeEnum.Content, 0);
         *  //cache.Resize(Vector3I.One);
         *  Vector3I voxelCoord;
         *  MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelBase.RootVoxel.PositionLeftBottomCorner, ref pos, out voxelCoord);
         *  var flag = MyVoxelRequestFlags.EmptyContent;
         *  voxelBase.RootVoxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, voxelCoord, voxelCoord, ref flag);
         *  if (cache.Content(ref Vector3I.Zero) != (byte)0)
         *  {
         *      return true;
         *  }
         *  return false;
         * }
         */

        public static bool VoxelContact(Vector3D[] physicsVerts, MyVoxelBase voxelBase)
        {
            try
            {
                if (voxelBase.RootVoxel.MarkedForClose || voxelBase.RootVoxel.Storage.Closed)
                {
                    return(false);
                }
                var planet = voxelBase as MyPlanet;
                var map    = voxelBase as MyVoxelMap;

                if (planet != null)
                {
                    for (int i = 0; i < 162; i++)
                    {
                        var      from          = physicsVerts[i];
                        var      localPosition = (Vector3)(from - planet.PositionLeftBottomCorner);
                        var      v             = localPosition / 1f;
                        Vector3I voxelCoord;
                        Vector3I.Floor(ref v, out voxelCoord);

                        var hit = new VoxelHit();
                        planet.Storage.ExecuteOperationFast(ref hit, MyStorageDataTypeFlags.Content, ref voxelCoord, ref voxelCoord, notifyRangeChanged: false);

                        if (hit.HasHit)
                        {
                            return(true);
                        }
                    }
                }
                else if (map != null)
                {
                    for (int i = 0; i < 162; i++)
                    {
                        var      from          = physicsVerts[i];
                        var      localPosition = (Vector3)(from - map.PositionLeftBottomCorner);
                        var      v             = localPosition / 1f;
                        Vector3I voxelCoord;
                        Vector3I.Floor(ref v, out voxelCoord);

                        var hit = new VoxelHit();
                        map.Storage.ExecuteOperationFast(ref hit, MyStorageDataTypeFlags.Content, ref voxelCoord, ref voxelCoord, notifyRangeChanged: false);

                        if (hit.HasHit)
                        {
                            return(true);
                        }
                    }
                }
            }
            catch (Exception ex) { Log.Line($"Exception in VoxelContact: {ex}"); }

            return(false);
        }
예제 #29
0
        // Algorithm source: http://minecraft.gamepedia.com/Explosion
        public void Explode(float power, int x, int y, int z)
        {
            if (rayDirs == null)
            {
                InitExplosionCache();
            }

            game.UpdateBlock(x, y, z, Block.Air);
            int index = (y * map.Length + z) * map.Width + x;

            physics.ActivateNeighbours(x, y, z, index);

            Vector3 basePos = new Vector3(x, y, z);

            for (int i = 0; i < rayDirs.Length; i++)
            {
                Vector3 dir       = rayDirs[i] * stepLen;
                Vector3 position  = basePos;
                float   intensity = (float)(0.7 + rnd.NextDouble() * 0.6) * power;
                while (intensity > 0)
                {
                    position  += dir;
                    intensity -= stepLen * 0.75f;
                    Vector3I P = Vector3I.Floor(position);
                    if (!map.IsValidPos(P))
                    {
                        break;
                    }

                    int  newX     = P.X;
                    int  newY     = P.Y;
                    int  newZ     = P.Z;
                    bool isTNT    = false;
                    int  newIndex = (newY * game.World.Length + newZ) * game.World.Width + newX;
                    if (map.blocks[newIndex] == Block.TNT)
                    {
                        isTNT = true;
                    }

                    BlockID block = map.GetBlock(P);
                    intensity -= (hardness[block] / 5 + 0.3f) * stepLen;
                    if (intensity > 0 && block != 0)
                    {
                        game.UpdateBlock(P.X, P.Y, P.Z, Block.Air);
                        index = (P.Y * map.Length + P.Z) * map.Width + P.X;
                        physics.ActivateNeighbours(P.X, P.Y, P.Z, index);
                        if (isTNT)
                        {
                            HandleTnt2(newIndex, block);
                        }
                    }
                }
            }
        }
예제 #30
0
        public void SpawnFlora(Vector3D pos)
        {
            if (m_planetEnvironmentSectors == null)
            {
                m_planetEnvironmentSectors = new Dictionary <Vector3I, MyPlanetEnvironmentSector>(500);
            }

            Vector3D gravity       = GetWorldGravityNormalized(ref pos);
            Vector3D perpedincular = MyUtils.GetRandomPerpendicularVector(ref gravity);
            Vector3D third         = Vector3D.Cross(gravity, perpedincular);

            perpedincular += third;

            Vector3I min = new Vector3I(-ENVIROMENT_EXTEND);
            Vector3I max = new Vector3I(ENVIROMENT_EXTEND);

            Vector3 offset = new Vector3(-MyPlanetEnvironmentSector.SECTOR_SIZE_METERS);

            for (var it = new Vector3I.RangeIterator(ref min, ref max); it.IsValid(); it.MoveNext())
            {
                Vector3D currentPos = pos + it.Current * offset * perpedincular;
                currentPos = PlaceToOrbit(currentPos, ref gravity);

                if (false == ChekPosition(currentPos))
                {
                    Vector3I newSector = Vector3I.Floor(currentPos / MyPlanetEnvironmentSector.SECTOR_SIZE_METERS);
                    if (m_planetSectorsPool == null)
                    {
                        m_planetSectorsPool = new MyDynamicObjectPool <MyPlanetEnvironmentSector>(400);
                    }


                    MyPlanetEnvironmentSector sector = m_planetSectorsPool.Allocate();

                    sector.Init(ref newSector, this);
                    m_planetEnvironmentSectors[newSector] = sector;
                    sector.PlaceItems();
                }
            }

            Vector3I sectorCoords = Vector3I.Floor(PlaceToOrbit(pos, ref gravity) / MyPlanetEnvironmentSector.SECTOR_SIZE_METERS);

            Vector3I keepMin = sectorCoords + new Vector3I(-ENVIROMENT_EXTEND_KEEP);
            Vector3I keepMax = sectorCoords + new Vector3I(ENVIROMENT_EXTEND_KEEP);

            foreach (var enviromentSector in m_planetEnvironmentSectors)
            {
                if (enviromentSector.Key.IsInsideInclusive(keepMin, keepMax))
                {
                    m_sectorsToKeep.Add(enviromentSector.Key);
                }
            }
        }