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); } } }
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); } } } } }
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; }
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); }
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); }
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)); }
/// <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(); }
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); }
/// <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); }
// 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; } }
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); }
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); }
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); }
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); }
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); }
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); }
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); } } } }
/* * 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); }
// 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); } } } } }
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); } } }