public BlockUpdate( Player origin, Vector3I coord, Block blockType ) { Origin = origin; X = (short)coord.X; Y = (short)coord.Y; Z = (short)coord.Z; BlockType = blockType; }
public override bool Prepare(Vector3I[] marks) { a = marks[0]; c = marks[1]; b = marks[2]; d = new Vector3I(a.X + c.X - b.X, a.Y + c.Y - b.Y, a.Z + c.Z - b.Z); Bounds = new BoundingBox( Math.Min(Math.Min(a.X, b.X), Math.Min(c.X, d.X)), Math.Min(Math.Min(a.Y, b.Y), Math.Min(c.Y, d.Y)), Math.Min(Math.Min(a.Z, b.Z), Math.Min(c.Z, d.Z)), Math.Max(Math.Max(a.X, b.X), Math.Max(c.X, d.X)), Math.Max(Math.Max(a.Y, b.Y), Math.Max(c.Y, d.Y)), Math.Max(Math.Max(a.Z, b.Z), Math.Max(c.Z, d.Z)) ); Coords = Bounds.MinVertex; if (!base.Prepare(marks)) return false; normal = (b - a).Cross(c - a); normalF = normal.Normalize(); BlocksTotalEstimate = GetBlockTotalEstimate(); s1 = normal.Cross(a - b).Normalize(); s2 = normal.Cross(b - c).Normalize(); s3 = normal.Cross(c - d).Normalize(); s4 = normal.Cross(d - a).Normalize(); return true; }
public VoxelChunk(Vector3I coords) { Coords = coords; Material = new byte[TotalVolume]; Content = new byte[TotalVolume]; }
public static void Plant( [NotNull] ForesterArgs args, Vector3I treeCoordinate ) { List<Tree> treeList = new List<Tree> { new Tree { Args = args, Height = args.Height, Pos = treeCoordinate } }; switch( args.Shape ) { case TreeShape.Rainforest: PlantRainForestTrees( args, treeList ); break; case TreeShape.Mangrove: PlantMangroves( args, treeList ); break; default: PlantTrees( args, treeList ); break; } ProcessTrees( args, treeList ); if( args.Foliage ) { foreach( Tree tree in treeList ) { tree.MakeFoliage(); } } if( args.Wood ) { foreach( Tree tree in treeList ) { tree.MakeTrunk(); } } }
public override bool Prepare( Vector3I[] marks ) { if( Player.World == null ) PlayerOpException.ThrowNoWorld( Player ); if( !base.Prepare( marks ) ) return false; BlocksTotalEstimate = Bounds.Volume; Coords = Bounds.MinVertex; // remember dimensions and orientation CopyState copyInfo = new CopyState( marks[0], marks[1] ); for( int x = Bounds.XMin; x <= Bounds.XMax; x++ ) { for( int y = Bounds.YMin; y <= Bounds.YMax; y++ ) { for( int z = Bounds.ZMin; z <= Bounds.ZMax; z++ ) { copyInfo.Buffer[x - Bounds.XMin, y - Bounds.YMin, z - Bounds.ZMin] = Map.GetBlock( x, y, z ); } } } copyInfo.OriginWorld = Player.World.Name; copyInfo.CopyTime = DateTime.UtcNow; Player.SetCopyInformation( copyInfo ); Player.Message( "{0} blocks cut into slot #{1}. You can now &H/Paste", Bounds.Volume, Player.CopySlot + 1 ); Player.Message( "Origin at {0} {1}{2} corner.", (copyInfo.Orientation.X == 1 ? "bottom" : "top"), (copyInfo.Orientation.Y == 1 ? "south" : "north"), (copyInfo.Orientation.Z == 1 ? "east" : "west") ); Context |= BlockChangeContext.Cut; return true; }
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); }
public void BreakBlockEffect( Vector3I position, byte block ) { Vector3 startPos = new Vector3( position.X, position.Y, position.Z ); int texLoc = game.BlockInfo.GetTextureLoc( block, TileSide.Left ); TextureRec rec = game.TerrainAtlas.GetTexRec( texLoc ); float invSize = TerrainAtlas2D.invElementSize; int cellsCountX = (int)( 0.25f / invSize ); int cellsCountY = (int)( 0.25f / invSize ); float elementXSize = invSize * 0.25f; float elementYSize = invSize * 0.25f; Random rnd = new Random(); for( int i = 0; i < 25; i++ ) { double velX = ( rnd.NextDouble() * 0.8/*5*/ ) - 0.4/*0.25*/; double velZ = ( rnd.NextDouble() * 0.8/*5*/ ) - 0.4/*0.25*/; double velY = ( rnd.NextDouble() + 0.25 ) * game.BlockInfo.Height[block]; Vector3 velocity = new Vector3( (float)velX, (float)velY, (float)velZ ); double xOffset = rnd.NextDouble() - 0.125; double yOffset = rnd.NextDouble() - 0.125; double zOffset = rnd.NextDouble() - 0.125; Vector3 pos = startPos + new Vector3( (float)xOffset, (float)yOffset, (float)zOffset ); TextureRec particleRec = rec; particleRec.U1 = (float)( rec.U1 + rnd.Next( 0, cellsCountX ) * elementXSize ); particleRec.V1 = (float)( rec.V1 + rnd.Next( 0, cellsCountY ) * elementYSize ); particleRec.U2 = particleRec.U1 + elementXSize; particleRec.V2 = particleRec.V1 + elementYSize; double life = 1.5 - rnd.NextDouble(); particles.Add( new TerrainParticle( game, pos, velocity, life, particleRec ) ); } }
public override bool Prepare( Vector3I[] marks ) { if( !base.Prepare( marks ) ) return false; double rx = Bounds.Width / 2d; double ry = Bounds.Length / 2d; double rz = Bounds.Height / 2d; radius.X = (float)(1 / (rx * rx)); radius.Y = (float)(1 / (ry * ry)); radius.Z = (float)(1 / (rz * rz)); center.X = (Bounds.XMin + Bounds.XMax) / 2f; center.Y = (Bounds.YMin + Bounds.YMax) / 2f; center.Z = (Bounds.ZMin + Bounds.ZMax) / 2f; fillInner = Brush.AlternateBlocks > 1 && Bounds.Width > 2 && Bounds.Length > 2 && Bounds.Height > 2; Coords = Bounds.MinVertex; if( fillInner ) { BlocksTotalEstimate = (int)(4 / 3d * Math.PI * rx * ry * rz); } else { // rougher estimation than the non-hollow form, a voxelized surface is a bit funky BlocksTotalEstimate = (int)(4 / 3d * Math.PI * ((rx + .5) * (ry + .5) * (rz + .5) - (rx - .5) * (ry - .5) * (rz - .5)) * 0.85); } return true; }
public CopyState( Vector3I mark1, Vector3I mark2 ) { BoundingBox box = new BoundingBox( mark1, mark2 ); Orientation = new Vector3I( mark1.X <= mark2.X ? 1 : -1, mark1.Y <= mark2.Y ? 1 : -1, mark1.Z <= mark2.Z ? 1 : -1 ); Buffer = new Block[box.Width, box.Length, box.Height]; }
protected override void Init(MyObjectBuilder_DefinitionBase builder) { base.Init(builder); var ob = builder as MyObjectBuilder_MultiBlockDefinition; MyDebug.AssertDebug(ob != null); if (ob.BlockDefinitions != null && ob.BlockDefinitions.Length > 0) { MinPosition = Vector3I.MaxValue; MaxPosition = Vector3I.MinValue; BlockDefinitions = new MyMultiBlockPartDefinition[ob.BlockDefinitions.Length]; for (int i = 0; i < ob.BlockDefinitions.Length; ++i) { BlockDefinitions[i] = new MyMultiBlockPartDefinition(); var obBlockDef = ob.BlockDefinitions[i]; BlockDefinitions[i].Id = obBlockDef.Id; BlockDefinitions[i].Position = obBlockDef.Position; BlockDefinitions[i].Forward = obBlockDef.Orientation.Forward; BlockDefinitions[i].Up = obBlockDef.Orientation.Up; MinPosition = Vector3I.Min(MinPosition, obBlockDef.Position); MaxPosition = Vector3I.Max(MaxPosition, obBlockDef.Position); } } }
/// <summary> /// Copies part of skeleton to other skeleton, both positions are inclusive /// </summary> public void CopyTo(MyGridSkeleton target, Vector3I fromGridPosition, Vector3I toGridPosition) { Vector3I baseBonePos = fromGridPosition * BoneDensity; Vector3I max = (toGridPosition - fromGridPosition + Vector3I.One) * BoneDensity; Vector3I boneOffset; for (boneOffset.X = 0; boneOffset.X <= max.X; boneOffset.X++) { for (boneOffset.Y = 0; boneOffset.Y <= max.Y; boneOffset.Y++) { for (boneOffset.Z = 0; boneOffset.Z <= max.Z; boneOffset.Z++) { Vector3I bonePos = baseBonePos + boneOffset; Vector3 bone; if (Bones.TryGetValue(bonePos, out bone)) { target.Bones[bonePos] = bone; } else { target.Bones.Remove(bonePos); } } } } }
public static Direction GetDirection(Vector3I[] marks) { if (Math.Abs(marks[1].X - marks[0].X) > Math.Abs(marks[1].Y - marks[0].Y)) { if (marks[0].X < marks[1].X) { return Direction.one; } else { return Direction.two; } } else if (Math.Abs(marks[1].X - marks[0].X) < Math.Abs(marks[1].Y - marks[0].Y)) { if (marks[0].Y < marks[1].Y) { return Direction.three; } else { return Direction.four; } } else return Direction.Null; }
public override bool Prepare( Vector3I[] marks ) { if ( !base.Prepare( marks ) ) return false; // center of the torus center = marks[0]; Vector3I radiusVector = ( marks[1] - center ).Abs(); // tube radius is figured out from Z component of the mark vector tubeR = radiusVector.Z; // torus radius is figured out from length of vector's X-Y components bigR = Math.Sqrt( radiusVector.X * radiusVector.X + radiusVector.Y * radiusVector.Y + .5 ); // tube + torus radius, rounded up. This will be the maximum extend of the torus. int combinedRadius = ( int )Math.Ceiling( bigR + tubeR ); // vector from center of torus to the furthest-away point of the bounding box Vector3I combinedRadiusVector = new Vector3I( combinedRadius, combinedRadius, tubeR + 1 ); // adjusted bounding box Bounds = new BoundingBox( center - combinedRadiusVector, center + combinedRadiusVector ); BlocksTotalEstimate = ( int )( 2 * Math.PI * Math.PI * bigR * ( tubeR * tubeR + Bias ) ); coordEnumerator = BlockEnumerator().GetEnumerator(); return true; }
internal MyVoxelPhysicsBody(MyVoxelBase voxelMap, float phantomExtend, float predictionSize = 3.0f, bool lazyPhysics = false) : base(voxelMap, RigidBodyFlag.RBF_STATIC) { ProfilerShort.Begin("MyVoxelPhysicsBody("); InvalidCells = new HashSet<Vector3I>[2]; InvalidCells[0] = new HashSet<Vector3I>(); InvalidCells[1] = new HashSet<Vector3I>(); m_predictionSize = predictionSize; m_phantomExtend = phantomExtend; m_voxelMap = voxelMap; Vector3I storageSize = m_voxelMap.Size; Vector3I numCels = storageSize >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; m_cellsOffset = m_voxelMap.StorageMin >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; if (!MyFakes.ENABLE_LAZY_VOXEL_PHYSICS || !lazyPhysics || !ENABLE_AABB_PHANTOM) { CreateRigidBodies(); } ProfilerShort.End(); MaterialType = MyMaterialType.ROCK; }
private void AssertRangeIsInside(int lodIndex, ref Vector3I globalMin, ref Vector3I globalMax) { var leafMinInLod = m_leafMin >> lodIndex; var leafMaxInLod = m_leafMax >> lodIndex; Debug.Assert(globalMin.IsInsideInclusive(ref leafMinInLod, ref leafMaxInLod)); Debug.Assert(globalMax.IsInsideInclusive(ref leafMinInLod, ref leafMaxInLod)); }
public MyProviderLeaf(IMyStorageDataProvider provider, MyStorageDataTypeEnum dataType, ref Vector3I leafMin, ref Vector3I leafMax) { m_provider = provider; m_dataType = dataType; m_leafMin = leafMin; m_leafMax = leafMax; }
void ModAPI.Interfaces.IMyStorage.ReadRange(MyStorageDataCache target, MyStorageDataTypeFlags dataToRead, int lodIndex, Vector3I lodVoxelRangeMin, Vector3I lodVoxelRangeMax) { if ((uint)lodIndex >= (uint)MyCellCoord.MAX_LOD_COUNT) return; ReadRange(target, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax); }
public UndoBlock( Vector3I coord, Block block ) { X = (short)coord.X; Y = (short)coord.Y; Z = (short)coord.Z; Block = block; }
public SandTask( World world, Vector3I position, Block Type ) : base(world) { _pos = position; _nextPos = position.Z - 1; _type = Type; }
internal MyVoxelPhysicsBody(MyVoxelMap voxelMap): base(voxelMap, RigidBodyFlag.RBF_STATIC) { m_voxelMap = voxelMap; Vector3I storageSize = m_voxelMap.Size; Vector3I numCels = storageSize >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; m_cellsOffset = m_voxelMap.StorageMin >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; HkUniformGridShape 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); CreateFromCollisionObject(shape, -m_voxelMap.SizeInMetresHalf, m_voxelMap.WorldMatrix, collisionFilter: MyPhysics.StaticCollisionLayer); shape.Base.RemoveReference(); if (ENABLE_AABB_PHANTOM) { m_aabbPhantom = new Havok.HkpAabbPhantom(new BoundingBox(Vector3.Zero, m_voxelMap.SizeInMetres), 0); m_aabbPhantom.CollidableAdded = AabbPhantom_CollidableAdded; m_aabbPhantom.CollidableRemoved = AabbPhantom_CollidableRemoved; } if (MyFakes.ENABLE_PHYSICS_HIGH_FRICTION) Friction = 0.65f; MaterialType = Sandbox.Common.MyMaterialType.ROCK; }
public FireworkParticle(World world, Vector3I pos, Block block) : base(world) { _startingPos = pos; _nextZ = pos.Z - 1; _block = block; }
static DeformationTable CreateTable(Vector3I normal) { DeformationTable result = new DeformationTable(); result.Normal = normal; Vector3I centerBone = new Vector3I(1, 1, 1); var absNormal = Vector3I.Abs(normal); var mask = new Vector3I(1, 1, 1) - absNormal; mask *= 2; for (int x = -mask.X; x <= mask.X; x++) { for (int y = -mask.Y; y <= mask.Y; y++) { for (int z = -mask.Z; z <= mask.Z; z++) { var offset = new Vector3I(x, y, z); float maxOffset = Math.Max(Math.Abs(z), Math.Max(Math.Abs(x), Math.Abs(y))); float ratio = 1; if (maxOffset > 1) ratio = 0.3f; float moveDist = ratio * MyGridConstants.DEFORMATION_TABLE_BASE_MOVE_DIST; Vector3I offsetA = centerBone + new Vector3I(x, y, z) + normal; result.OffsetTable.Add(offsetA, -normal * moveDist); result.MinOffset = Vector3I.Min(result.MinOffset, offset); result.MaxOffset = Vector3I.Max(result.MaxOffset, offset); } } } return result; }
public override void ReadMaterialRange(MyStorageDataCache target, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod, float lodVoxelSizeHalf) { float lodVoxelSize = 2f * lodVoxelSizeHalf; byte defaultMaterial = m_material.Index; Vector3I v = new Vector3I(); 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) { var write = v - minInLod + writeOffset; byte slope = target.Material(ref write); if (slope == 0) continue; Vector3 localPos = v * lodVoxelSize; var mat = GetMaterialForPosition(ref localPos, lodVoxelSize); target.Material(ref write, mat.Index); } } } }
public override void Unregister(MyEntity entity, Vector3I forwardVector) { base.Unregister(entity, forwardVector); var thrust = entity as MyThrust; if (thrust == null) return; thrust.EnabledChanged -= thrust_EnabledChanged; thrust.SlimBlock.ComponentStack.IsFunctionalChanged -= ComponentStack_IsFunctionalChanged; // Need to recalculate the slowdown factor. Maybe save different levels of the factors and just revert back to previous one SlowdownFactor = 0f; foreach (var direction in Base6Directions.IntDirections) { foreach (var dataByType in m_dataByFuelType) { foreach (var entityInDirection in dataByType.ThrustsByDirection[direction]) { var thrustInDirection = entityInDirection as MyThrust; if (thrustInDirection == null) continue; SlowdownFactor = Math.Max(thrustInDirection.BlockDefinition.SlowdownFactor, SlowdownFactor); } } } }
public BlockFloat(World world, Vector3I position, Block Type) : base(world) { _pos = position; _nextPos = position.Z + 1; type = Type; }
public override bool Prepare( Vector3I[] marks ) { if( !base.Prepare( marks ) ) return false; BlocksTotalEstimate = Bounds.Volume; Coords = Bounds.MinVertex; return true; }
public void AddSelection( byte id, Vector3I p1, Vector3I p2, FastColour col ) { RemoveSelection( id ); SelectionBox selection = new SelectionBox( p1, p2, col ); selection.ID = id; selections.Add( selection ); }
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); }
/// <summary> /// Executes the drawer on a separate thread. The bool is there if the user finds a need to stop the drawing. /// (This happens when CancelDrawer() is called.) /// </summary> public void Start(ClassicBot main, ref bool Aborted, Vector3I[] points, byte blocktype, ref int sleeptime) { Vector3I Coords = Vector3I.Min(points[0], points[1]); Vector3I MinVertex = Vector3I.Min(points[0], points[1]); Vector3I MaxVertex = Vector3I.Max(points[0], points[1]); double rx = (MaxVertex.X - MinVertex.X + 1) / 2d; double ry = (MaxVertex.Y - MinVertex.Y + 1) / 2d; double rz = (MaxVertex.Z - MinVertex.Z + 1) / 2d; radius.X = (float)(1 / (rx * rx)); radius.Y = (float)(1 / (ry * ry)); radius.Z = (float)(1 / (rz * rz)); // find center points center.X = (float)((MinVertex.X + MaxVertex.X) / 2d); center.Y = (float)((MinVertex.Y + MaxVertex.Y) / 2d); center.Z = (float)((MinVertex.Z + MaxVertex.Z) / 2d); Coords = MinVertex; main.SendPositionPacket((short)Coords.X, (short)Coords.Y, (short)Coords.Z); IEnumerator<Vector3I> coordEnumerator = BlockEnumerator(MinVertex, MaxVertex).GetEnumerator(); while(coordEnumerator.MoveNext()) { if (Aborted == true) { return; } Thread.Sleep(sleeptime); Coords = coordEnumerator.Current; main.SendPositionPacket((short)Coords.X, (short)Coords.Y, (short)Coords.Z); main.SendBlockPacket((short)Coords.X, (short)Coords.Y, (short)Coords.Z, 1, blocktype); } main.SetDrawerToNull(); }
IEnumerable<Vector3I> BlockEnumerator(Vector3I min, Vector3I max) { for( int x = min.X; x <= max.X; x++ ) { for( int y = min.Y; y <= max.Y; y++ ) { yield return new Vector3I( x, y, min.Z ); if( min.Z != max.Z ) { yield return new Vector3I( x, y, max.Z ); } } } if((max.Z - min.Z + 1) > 2) { for( int x = min.X; x <= max.X; x++ ) { for( int z = min.Z + 1; z < max.Z; z++ ) { yield return new Vector3I( x, min.Y, z ); if( min.Y != max.Y ) { yield return new Vector3I( x, max.Y, z ); } } } for( int y = min.Y + 1; y < max.Y; y++ ) { for( int z = min.Z + 1; z < max.Z; z++ ) { yield return new Vector3I( min.X, y, z ); if( min.X != max.X ) { yield return new Vector3I( max.X, y, z ); } } } } }
/// <summary> /// Adds environment item to internal collections. Creates render and physics data. /// </summary> /// <returns>True if successfully added, otherwise false.</returns> private bool AddItem(MyEnvironmentItemDefinition itemDefinition, ref MatrixD worldMatrix, ref BoundingBoxD aabbWorld, HkStaticCompoundShape sectorRootShape, Dictionary <MyStringId, HkShape> subtypeIdToShape) { if (!MyFakes.ENABLE_ENVIRONMENT_ITEMS) { return(true); } Debug.Assert(m_definition.ContainsItemDefinition(itemDefinition), String.Format("Environment item with definition '{0}' not found in class '{1}'", itemDefinition.Id, m_definition.Id)); if (!m_definition.ContainsItemDefinition(itemDefinition)) { return(false); } //MyDefinitionId defId = new MyDefinitionId(envItemObjectBuilderType, subtypeId.ToString()); MyModel model = MyModels.GetModelOnlyData(itemDefinition.Model); if (model == null) { //Debug.Fail(String.Format("Environment item model of '{0}' not found, skipping the item...", itemDefinition.Id)); return(false); } int localId = worldMatrix.Translation.GetHashCode(); MyEnvironmentItemData data = new MyEnvironmentItemData() { Id = localId, SubtypeId = itemDefinition.Id.SubtypeId, Transform = new MyTransformD(ref worldMatrix), Enabled = true, SectorInstanceId = -1 }; //Preload split planes //VRageRender.MyRenderProxy.PreloadMaterials(model.AssetName); aabbWorld.Include(model.BoundingBox.Transform(worldMatrix)); CheckModelConsistency(itemDefinition); MatrixD transform = data.Transform.TransformMatrix; Vector3I sectorId = MyEnvironmentSector.GetSectorId(transform.Translation, m_definition.SectorSize); MyEnvironmentSector sector; if (!m_sectors.TryGetValue(sectorId, out sector)) { sector = new MyEnvironmentSector(sectorId); m_sectors.Add(sectorId, sector); } // Adds instance of the given model. Local matrix specified might be changed internally in renderer. Matrix transformL = (Matrix)transform; data.SectorInstanceId = sector.AddInstance(itemDefinition.Id.SubtypeId, ref transformL, model.BoundingBox, m_instanceFlags, m_definition.MaxViewDistance); int physicsShapeInstanceId; if (AddPhysicsShape(data.SubtypeId, model, ref transform, sectorId, sectorRootShape, subtypeIdToShape, out physicsShapeInstanceId)) { // Map to data index - note that itemData is added after this to its list! m_physicsShapeInstanceIdToLocalId[physicsShapeInstanceId] = localId; m_localIdToPhysicsShapeInstanceId[localId] = physicsShapeInstanceId; } data.Transform = new MyTransformD(transform); if (m_itemsData.ContainsKey(localId)) { Debug.Fail("More items on same place! " + transform.Translation.ToString()); } else { m_itemsData.Add(localId, data); } return(true); }
public bool CanPlaceTile(Entity entity, Vector3I location, Tile tile, TileAccessFlags accessFlags) { return(true); }
public bool AddMaterial(int materialId, int amount, Vector3I globalPosition) { bool success = false; if (amount > 0) { Vector3I chunkPosition = CalculateChunkPosition(globalPosition); Vector3I voxelPosition = CalculateVoxelPositionInChunk(globalPosition, chunkPosition); bool existsBefore = _chunks[chunkPosition][voxelPosition].Exists; if (_chunks[chunkPosition][voxelPosition].Amount + amount <= Constant.MaxMaterialAmount) { IList <(Vector3I ChunkPosition, Vector3I VoxelPosition)> positions = CalculateVoxelPositions(globalPosition); if (_chunks[chunkPosition][voxelPosition].MaterialId == Constant.MaterialAir) { foreach ((Vector3I ChunkPosition, Vector3I VoxelPosition)position in positions) { _chunks[position.ChunkPosition][position.VoxelPosition].MaterialId = materialId; } } if (_chunks[chunkPosition][voxelPosition].MaterialId == materialId) { foreach ((Vector3I ChunkPosition, Vector3I VoxelPosition)position in positions) { _chunks[position.ChunkPosition][position.VoxelPosition].AddMaterial(amount); if (!_updatedChunkCoordinates.Contains(position.ChunkPosition)) { _updatedChunkCoordinates.Add(position.ChunkPosition); } } //Update NeighborChunk if neccessairy foreach (Vector3I neighborPosition in GetNeighbors(globalPosition)) { if (PositionIsInsideWorld(neighborPosition)) { IList <(Vector3I ChunkPosition, Vector3I VoxelPosition)> neighborPositions = CalculateVoxelPositions(neighborPosition); foreach ((Vector3I ChunkPosition, Vector3I VoxelPosition)position in neighborPositions) { if (!_updatedChunkCoordinates.Contains(position.ChunkPosition)) { _updatedChunkCoordinates.Add(position.ChunkPosition); } } } } success = true; } } if (!existsBefore && _chunks[chunkPosition][voxelPosition].Exists) { _chunks[chunkPosition].UsedVoxelAmount++; DecrementNeighborsEmptyNeighborCount(globalPosition); } } return(success); }
private Vector3I CalculateVoxelPositionInChunk(Vector3I globalPosition, Vector3I chunkPosition) { Vector3I voxelInChunkPosition = globalPosition - (chunkPosition * Constant.ChunkSize); return(voxelInChunkPosition); }
private IList <(Vector3I ChunkPosition, Vector3I VoxelPosition)> CalculateVoxelPositions(Vector3I globalPosition) { List <(Vector3I ChunkPosition, Vector3I VoxelPosition)> positions = new List <(Vector3I ChunkPosition, Vector3I VoxelPosition)>(); Vector3I chunkPosition = CalculateChunkPosition(globalPosition); Vector3I voxelPosition = CalculateVoxelPositionInChunk(globalPosition, chunkPosition); positions.Add((chunkPosition, voxelPosition)); Vector3I afterChunkPosition; Vector3I afterVoxelPosition; if (voxelPosition.X == 0 && ChunkIsInsideWorld((chunkPosition - new Vector3I(1, 0, 0)))) { foreach ((Vector3I ChunkPosition, Vector3I VoxelPosition)position in positions.ToArray()) { afterChunkPosition = position.ChunkPosition - new Vector3I(1, 0, 0); afterVoxelPosition = position.VoxelPosition; afterVoxelPosition.X = Constant.ChunkSizeX; positions.Add((afterChunkPosition, afterVoxelPosition)); } } if (voxelPosition.Y == 0 && ChunkIsInsideWorld((chunkPosition - new Vector3I(0, 1, 0)))) { foreach ((Vector3I ChunkPosition, Vector3I VoxelPosition)position in positions.ToArray()) { afterChunkPosition = position.ChunkPosition - new Vector3I(0, 1, 0); afterVoxelPosition = position.VoxelPosition; afterVoxelPosition.Y = Constant.ChunkSizeY; positions.Add((afterChunkPosition, afterVoxelPosition)); } } if (voxelPosition.Z == 0 && ChunkIsInsideWorld((chunkPosition - new Vector3I(0, 0, 1)))) { foreach ((Vector3I ChunkPosition, Vector3I VoxelPosition)position in positions.ToArray()) { afterChunkPosition = position.ChunkPosition - new Vector3I(0, 0, 1); afterVoxelPosition = position.VoxelPosition; afterVoxelPosition.Z = Constant.ChunkSizeZ; positions.Add((afterChunkPosition, afterVoxelPosition)); } } return(positions); }
public bool RaytraceEmptyOnFilledVoxel(Vector3 rayPosition, Vector3 rayDirection, out Vector3I voxelPosition) { bool success = _voxelMarcher.InitializeStartPosition(rayPosition, rayDirection); voxelPosition = new Vector3I(-1); bool emptySet = false; while (success && !PositionIsUnderWorld(_voxelMarcher.VoxelPosition) && GetVoxel(_voxelMarcher.VoxelPosition).IsEmpty) { emptySet = true; voxelPosition = _voxelMarcher.VoxelPosition; success = _voxelMarcher.CalculateNextPosition(); } if (!(success && emptySet && (PositionIsUnderWorld(_voxelMarcher.VoxelPosition) || !GetVoxel(_voxelMarcher.VoxelPosition).IsEmpty))) { success = false; } return(success); }
/// <summary> /// Adds item physics shape to rootShape and returns instance id of added shape instance. /// </summary> /// <returns>true if ite physics shape has been added, otherwise false.</returns> private bool AddPhysicsShape(MyStringId subtypeId, MyModel model, ref MatrixD worldMatrix, Vector3I sectorId, HkStaticCompoundShape sectorRootShape, Dictionary <MyStringId, HkShape> subtypeIdToShape, out int physicsShapeInstanceId) { physicsShapeInstanceId = 0; HkShape physicsShape; if (!subtypeIdToShape.TryGetValue(subtypeId, out physicsShape)) { HkShape[] shapes = model.HavokCollisionShapes; if (shapes == null || shapes.Length == 0) { return(false); } Debug.Assert(shapes.Length == 1); //List<HkShape> listShapes = new List<HkShape>(); //for (int i = 0; i < shapes.Length; i++) //{ // listShapes.Add(shapes[i]); // HkShape.SetUserData(shapes[i], shapes[i].UserData | (int)HkShapeUserDataFlags.EnvironmentItem); //} //physicsShape = new HkListShape(listShapes.GetInternalArray(), listShapes.Count, HkReferencePolicy.None); //HkShape.SetUserData(physicsShape, physicsShape.UserData | (int)HkShapeUserDataFlags.EnvironmentItem); physicsShape = shapes[0]; physicsShape.AddReference(); subtypeIdToShape[subtypeId] = physicsShape; } physicsShapeInstanceId = sectorRootShape.AddInstance(physicsShape, worldMatrix); Debug.Assert(physicsShapeInstanceId >= 0 && physicsShapeInstanceId < int.MaxValue, "Shape key space overflow"); return(true); }
private string NameOf(Vector3I pos) { return($"region{pos.X:+0;-#}{pos.Y:+0;-#}{pos.Z:+0;-#}.vgz"); }
public void SetTile(TileData tile) { var offset = new Vector3I(tile._indexX, tile._indexY, tile._indexZ) - Region * RegionSize; tiles[(offset.Z * RegionSize + offset.Y) * RegionSize + offset.X] = tile; }
internal MyClipmapHandler(uint id, MyClipmapScaleEnum scaleGroup, MatrixD worldMatrix, Vector3I sizeLod0, Vector3D massiveCenter, float massiveRadius, bool spherize, RenderFlags additionalFlags, VRage.Voxels.MyClipmap.PruningFunc prunningFunc) { m_clipmapBase = new MyClipmap(id, scaleGroup, worldMatrix, sizeLod0, this, massiveCenter, massiveRadius, prunningFunc); m_massiveCenter = massiveCenter; m_renderFlags = additionalFlags; m_mergeHandler = null; if (spherize) { m_massiveRadius = massiveRadius; } if (MyLodMeshMergeHandler.ShouldAllocate(m_mergeHandler)) { m_mergeHandler = AllocateMergeHandler(); } MyClipmap.AddToUpdate(MyRender11.Environment.CameraPosition, Base); }
public MyVoxelFile(MyMwcVoxelFilesEnum voxelFileEnum, Vector3I sizeInVoxels, string voxelName) { VoxelFileEnum = voxelFileEnum; SizeInVoxels = sizeInVoxels; VoxelName = voxelName; }
internal ForesterBlockPlacingEventArgs(Vector3I coordinate, Block block) { Coordinate = coordinate; Block = block; }
public MyObjectBuilder_EntityBase BuildEntity() { var asteroidCenter = new VRageMath.Vector3D(); var asteroidSize = new Vector3I(); string originalFile = null; if (IsStockVoxel) { var stockfile = StockVoxel.SourceFilename; if (StockMaterial == null || StockMaterial.Value == null) { SourceFile = stockfile; originalFile = SourceFile; var asteroid = new MyVoxelMap(); asteroid.Load(stockfile, SpaceEngineersCore.Resources.GetDefaultMaterialName(), false); asteroidCenter = asteroid.BoundingContent.Center; asteroidSize = asteroid.BoundingContent.SizeInt() + 1; // Content size } else { var asteroid = new MyVoxelMap(); asteroid.Load(stockfile, StockMaterial.Value); asteroid.ForceBaseMaterial(SpaceEngineersCore.Resources.GetDefaultMaterialName(), StockMaterial.Value); SourceFile = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension); asteroid.Save(SourceFile); originalFile = StockVoxel.SourceFilename; asteroidCenter = asteroid.BoundingContent.Center; asteroidSize = asteroid.BoundingContent.SizeInt() + 1; // Content size } } else if (IsFileVoxel) { originalFile = SourceFile; var asteroid = new MyVoxelMap(); asteroid.Load(SourceFile, SpaceEngineersCore.Resources.GetDefaultMaterialName(), false); asteroidCenter = asteroid.BoundingContent.Center; asteroidSize = asteroid.BoundingContent.SizeInt() + 1; // Content size if (StockMaterial != null && StockMaterial.Value != null) { asteroid.ForceBaseMaterial(SpaceEngineersCore.Resources.GetDefaultMaterialName(), StockMaterial.Value); SourceFile = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension); asteroid.Save(SourceFile); } } else if (IsSphere) { string material; if (StockMaterial != null && StockMaterial.Value != null) { material = StockMaterial.Value; } else { material = SpaceEngineersCore.Resources.GetDefaultMaterialName(); } originalFile = string.Format("sphere_{0}_{1}_{2}{3}", material.ToLowerInvariant(), SphereRadius, SphereShellRadius, MyVoxelMap.V2FileExtension); var asteroid = MyVoxelBuilder.BuildAsteroidSphere(SphereRadius > 32, SphereRadius, material, material, SphereShellRadius != 0, SphereShellRadius); // TODO: progress bar. asteroidCenter = asteroid.BoundingContent.Center; asteroidSize = asteroid.BoundingContent.SizeInt() + 1; // Content size SourceFile = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension); asteroid.Save(SourceFile); } // automatically number all files, and check for duplicate filenames. Filename = MainViewModel.CreateUniqueVoxelStorageName(originalFile); // Figure out where the Character is facing, and plant the new constrcut right in front. // Calculate the hypotenuse, as it will be the safest distance to place in front. double distance = Math.Sqrt(Math.Pow(asteroidSize.X, 2) + Math.Pow(asteroidSize.Y, 2) + Math.Pow(asteroidSize.Z, 2)) / 2; var vector = new BindableVector3DModel(_dataModel.CharacterPosition.Forward).Vector3D; vector.Normalize(); vector = System.Windows.Media.Media3D.Vector3D.Multiply(vector, distance); Position = new BindablePoint3DModel(Point3D.Add(new BindablePoint3DModel(_dataModel.CharacterPosition.Position).Point3D, vector)); //Forward = new BindableVector3DModel(_dataModel.CharacterPosition.Forward); //Up = new BindableVector3DModel(_dataModel.CharacterPosition.Up); Forward = new BindableVector3DModel(Vector3.Forward); // Asteroids currently don't have any orientation. Up = new BindableVector3DModel(Vector3.Up); var entity = new MyObjectBuilder_VoxelMap { EntityId = SpaceEngineersApi.GenerateEntityId(IDType.ASTEROID), PersistentFlags = MyPersistentEntityFlags2.CastShadows | MyPersistentEntityFlags2.InScene, StorageName = Path.GetFileNameWithoutExtension(Filename), PositionAndOrientation = new MyPositionAndOrientation { Position = Position.ToVector3D() - asteroidCenter, Forward = Forward.ToVector3(), Up = Up.ToVector3() } }; return(entity); }
private RegionData LoadRegionFile(string name, Vector3I region) { RegionData data = null; lock (dataCache) { foreach (var rgn in dataCache) { if (rgn.Region == region) { data = rgn; break; } } if (data != null) { dataCache.Remove(data); dataCache.Add(data); while (dataCache.Count > 5) { dataCache.RemoveAt(0); } return(data); } data = new RegionData() { Region = region }; dataCache.Add(data); while (dataCache.Count > 5) { dataCache.RemoveAt(0); } } lock (data) { var formatter = new BinaryFormatter(); var path = Path.Combine(SaveFolder.FullName, name); if (File.Exists(path)) { byte[] mdata; using (var gzs = new GZipStream(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read), CompressionMode.Decompress)) { using (var mems = new MemoryStream()) { gzs.CopyTo(mems); mems.Close(); mdata = mems.ToArray(); } } using (var sw = new RiffFile(new MemoryStream(mdata))) { foreach (var chunk in sw.Chunks) { switch (chunk.ChunkId) { case "RMTA": // Region file meta { var version = chunk.ReadByte(); if (version != 1) { throw new NotImplementedException(); } } break; case "LIST": { var list = chunk.ToList(); switch (list.ListId) { case "TILS": foreach (var chunk2 in list.Chunks) { switch (chunk2.ChunkId) { case "LIST": { var list2 = chunk2.ToList(); switch (list2.ListId) { case "TILE": { var tileData = new RegionData.TileData(); foreach (var chunk3 in list2.Chunks) { switch (chunk3.ChunkId) { case "TMTA": tileData._indexX = chunk3.ReadInt32(); tileData._indexY = chunk3.ReadInt32(); tileData._indexZ = chunk3.ReadInt32(); tileData._generationState = chunk3.ReadInt32(); data.SetTile(tileData); break; case "HMAP": { var a = (int[])formatter.Deserialize(chunk); Array.Copy(a, tileData._heightmap, a.Length); } break; case "BLKS": { var a = (ushort[])formatter.Deserialize(chunk); Array.Copy(a, tileData._gridBlock, a.Length); } break; case "LIST": { var list3 = chunk3.ToList(); switch (list3.ListId) { case "TXTA": break; case "ENTS": break; } } break; } } } break; } } break; } } break; } } break; } // // Block Extra Data // using (var extraData = tileList.CreateList("TXTA")) // { // foreach (var byteArray in tile._gridExtra) // { // using (var blockExtra = extraData.CreateChunk("BXTA")) // { // formatter.Serialize(blockExtra, byteArray); // } // } // } // // Entities // using (var entityData = tileList.CreateList("ENTS")) // { // foreach (var byteArray in tile._gridEntities) // { // using (var blockExtra = entityData.CreateChunk("ENTY")) // { // formatter.Serialize(blockExtra, byteArray); // } // } // } } } } return(data); } }
// For a 1024 cubed asteroid, it takes approximately 6.5Gb of system memory. public static MyVoxelMap ReadModelAsteroidVolmetic(Model3DGroup model, IList <MyMeshModel> mappedMesh, ScaleTransform3D scale, Transform3D rotateTransform, TraceType traceType, TraceCount traceCount, TraceDirection traceDirection, Action <double, double> resetProgress, Action incrementProgress, Func <bool> checkCancel, Action complete) { var traceDirectionCount = 0; var materials = new List <byte>(); var faceMaterials = new List <byte>(); foreach (var mesh in mappedMesh) { if (string.IsNullOrEmpty(mesh.Material)) { materials.Add(0xff); // represent empty materials. } else { materials.Add(SpaceEngineersCore.Resources.GetMaterialIndex(mesh.Material)); } if (string.IsNullOrEmpty(mesh.FaceMaterial)) { faceMaterials.Add(0xff); // represent empty materials. } else { faceMaterials.Add(SpaceEngineersCore.Resources.GetMaterialIndex(mesh.FaceMaterial)); } } // How far to check in from the proposed Volumetric edge. // This number is just made up, but small enough that it still represents the corner edge of the Volumetric space. // But still large enough that it isn't the exact corner. const double offset = 0.0000045f; if (scale.ScaleX > 0 && scale.ScaleY > 0 && scale.ScaleZ > 0 && scale.ScaleX != 1.0f && scale.ScaleY != 1.0f && scale.ScaleZ != 1.0f) { model.TransformScale(scale.ScaleX, scale.ScaleY, scale.ScaleZ); } // Attempt to offset the model, so it's only caulated from zero (0) and up, instead of using zero (0) as origin. //model.Transform = new TranslateTransform3D(-model.Bounds.X, -model.Bounds.Y, -model.Bounds.Z); var tbounds = model.Bounds; Matrix3D?rotate = null; if (rotateTransform != null) { rotate = rotateTransform.Value; tbounds = rotateTransform.TransformBounds(tbounds); } //model.Transform = new TranslateTransform3D(-tbounds.X, -tbounds.Y, -tbounds.Z); // Add 2 to either side, to allow for material padding to expose internal materials. var xMin = (int)Math.Floor(tbounds.X) - 2; var yMin = (int)Math.Floor(tbounds.Y) - 2; var zMin = (int)Math.Floor(tbounds.Z) - 2; var xMax = (int)Math.Ceiling(tbounds.X + tbounds.SizeX) + 2; var yMax = (int)Math.Ceiling(tbounds.Y + tbounds.SizeY) + 2; var zMax = (int)Math.Ceiling(tbounds.Z + tbounds.SizeZ) + 2; var xCount = (xMax - xMin).RoundUpToNearest(64); var yCount = (yMax - yMin).RoundUpToNearest(64); var zCount = (zMax - zMin).RoundUpToNearest(64); Debug.WriteLine("Approximate Size: {0}x{1}x{2}", Math.Ceiling(tbounds.X + tbounds.SizeX) - Math.Floor(tbounds.X), Math.Ceiling(tbounds.Y + tbounds.SizeY) - Math.Floor(tbounds.Y), Math.Ceiling(tbounds.Z + tbounds.SizeZ) - Math.Floor(tbounds.Z)); Debug.WriteLine("Bounds Size: {0}x{1}x{2}", xCount, yCount, zCount); var finalCubic = ArrayHelper.Create <byte>(xCount, yCount, zCount); var finalMater = ArrayHelper.Create <byte>(xCount, yCount, zCount); if (resetProgress != null) { long triangles = (from GeometryModel3D gm in model.Children select gm.Geometry as MeshGeometry3D).Aggregate <MeshGeometry3D, long>(0, (current, g) => current + (g.TriangleIndices.Count / 3)); long rays = 0; if ((traceDirection & TraceDirection.X) == TraceDirection.X) { rays += ((yMax - yMin) * (zMax - zMin)); } if ((traceDirection & TraceDirection.Y) == TraceDirection.Y) { rays += ((xMax - xMin) * (zMax - zMin)); } if ((traceDirection & TraceDirection.Z) == TraceDirection.Z) { rays += ((xMax - xMin) * (yMax - yMin)); } resetProgress.Invoke(0, rays * triangles); } if (checkCancel != null && checkCancel.Invoke()) { if (complete != null) { complete.Invoke(); } return(null); } #region basic ray trace of every individual triangle. // Start from the last mesh, which represents the bottom of the UI stack, and overlay each other mesh on top of it. for (var modelIdx = mappedMesh.Count - 1; modelIdx >= 0; modelIdx--) { Debug.WriteLine("Model {0}", modelIdx); var modelCubic = new byte[xCount][][]; var modelMater = new byte[xCount][][]; for (var x = 0; x < xCount; x++) { modelCubic[x] = new byte[yCount][]; modelMater[x] = new byte[yCount][]; for (var y = 0; y < yCount; y++) { modelCubic[x][y] = new byte[zCount]; modelMater[x][y] = new byte[zCount]; } } var meshes = mappedMesh[modelIdx]; var threadCounter = 0; var geometries = new GeometeryDetail[meshes.Geometery.Length]; for (var i = 0; i < meshes.Geometery.Length; i++) { geometries[i] = new GeometeryDetail(meshes.Geometery[i]); } var startOffset = 0.5f; var endOffset = 0.5f; var volumeOffset = 0.5f; Func <double, int> roundFunc = null; if (traceType == TraceType.Odd) { startOffset = 0.5f; endOffset = 0.5f; volumeOffset = 0.5f; roundFunc = delegate(double d) { return((int)Math.Round(d, 0)); }; } else if (traceType == TraceType.Even) { startOffset = 0.0f; endOffset = 1.0f; volumeOffset = 1.0f; roundFunc = delegate(double d) { return((int)Math.Floor(d)); }; } #region X ray trace if ((traceDirection & TraceDirection.X) == TraceDirection.X) { Debug.WriteLine("X Rays"); traceDirectionCount++; threadCounter = (yMax - yMin) * (zMax - zMin); for (var y = yMin; y < yMax; y++) { for (var z = zMin; z < zMax; z++) { if (checkCancel != null && checkCancel.Invoke()) { if (complete != null) { complete.Invoke(); } return(null); } List <Point3D[]> testRays = null; if (traceType == TraceType.Odd) { testRays = new List <Point3D[]> { new [] { new Point3D(xMin, y + offset, z + offset), new Point3D(xMax, y + offset, z + offset) }, new [] { new Point3D(xMin, y - 0.5f + offset, z - 0.5f + offset), new Point3D(xMax, y - 0.5f + offset, z - 0.5f + offset) }, new [] { new Point3D(xMin, y + 0.5f - offset, z - 0.5f + offset), new Point3D(xMax, y + 0.5f - offset, z - 0.5f + offset) }, new [] { new Point3D(xMin, y - 0.5f + offset, z + 0.5f - offset), new Point3D(xMax, y - 0.5f + offset, z + 0.5f - offset) }, new [] { new Point3D(xMin, y + 0.5f - offset, z + 0.5f - offset), new Point3D(xMax, y + 0.5f - offset, z + 0.5f - offset) } } } ; else if (traceType == TraceType.Even) { testRays = new List <Point3D[]> { new [] { new Point3D(xMin, y + 0.5f - offset, z + 0.5f - offset), new Point3D(xMax, y + 0.5f - offset, z + 0.5f - offset) }, new [] { new Point3D(xMin, y + offset, z + offset), new Point3D(xMax, y + offset, z + offset) }, new [] { new Point3D(xMin, y + 1.0f - offset, z + offset), new Point3D(xMax, y + 1.0f - offset, z + offset) }, new [] { new Point3D(xMin, y + offset, z + 1.0f - offset), new Point3D(xMax, y + offset, z + 1.0f - offset) }, new [] { new Point3D(xMin, y + 1.0f - offset, z + 1.0f - offset), new Point3D(xMax, y + 1.0f - offset, z + 1.0f - offset) } } } ; var task = new Task(obj => { var bgw = (RayTracerTaskWorker)obj; var tracers = new List <Trace>(); foreach (var geometery in geometries) { for (var t = 0; t < geometery.Triangles.Length; t += 3) { if (checkCancel != null && checkCancel.Invoke()) { return; } if (incrementProgress != null) { lock (Locker) { incrementProgress.Invoke(); } } var p1 = geometery.Positions[geometery.Triangles[t]]; var p2 = geometery.Positions[geometery.Triangles[t + 1]]; var p3 = geometery.Positions[geometery.Triangles[t + 2]]; if (rotate.HasValue) { p1 = rotate.Value.Transform(p1); p2 = rotate.Value.Transform(p2); p3 = rotate.Value.Transform(p3); } foreach (var ray in testRays) { if ((p1.Y < ray[0].Y && p2.Y < ray[0].Y && p3.Y < ray[0].Y) || (p1.Y > ray[0].Y && p2.Y > ray[0].Y && p3.Y > ray[0].Y) || (p1.Z < ray[0].Z && p2.Z < ray[0].Z && p3.Z < ray[0].Z) || (p1.Z > ray[0].Z && p2.Z > ray[0].Z && p3.Z > ray[0].Z)) { continue; } Point3D intersect; int normal; if (MeshHelper.RayIntersetTriangleRound(p1, p2, p3, ray[0], ray[1], out intersect, out normal)) { tracers.Add(new Trace(intersect, normal)); } } } } if (tracers.Count > 1) { var order = tracers.GroupBy(t => new { t.Point, t.Face }).Select(g => g.First()).OrderBy(k => k.Point.X).ToArray(); var startCoord = roundFunc(order[0].Point.X); var endCoord = roundFunc(order[order.Length - 1].Point.X); var surfaces = 0; for (var x = startCoord; x <= endCoord; x++) { var points = order.Where(p => p.Point.X > x - startOffset && p.Point.X < x + endOffset).ToArray(); var volume = (byte)(0xff / testRays.Count * surfaces); foreach (var point in points) { if (point.Face == MeshFace.Farside) { volume += (byte)(Math.Round(Math.Abs(x + volumeOffset - point.Point.X) * 255 / testRays.Count, 0)); surfaces++; } else if (point.Face == MeshFace.Nearside) { volume -= (byte)(Math.Round(Math.Abs(x + volumeOffset - point.Point.X) * 255 / testRays.Count, 0)); surfaces--; } } // TODO: retest detailed model export. //volume = volume.RoundUpToNearest(8); modelCubic[x - xMin][bgw.Y - yMin][bgw.Z - zMin] = volume; modelMater[x - xMin][bgw.Y - yMin][bgw.Z - zMin] = materials[bgw.ModelIdx]; } if (faceMaterials[bgw.ModelIdx] != 0xff) { for (var i = 1; i < 6; i++) { if (xMin < startCoord - i && modelCubic[startCoord - i - xMin][bgw.Y - yMin][bgw.Z - zMin] == 0) { modelMater[startCoord - i - xMin][bgw.Y - yMin][bgw.Z - zMin] = faceMaterials[bgw.ModelIdx]; } if (endCoord + i < xMax && modelCubic[endCoord + i - xMin][bgw.Y - yMin][bgw.Z - zMin] == 0) { modelMater[endCoord + i - xMin][bgw.Y - yMin][bgw.Z - zMin] = faceMaterials[bgw.ModelIdx]; } } } } lock (Locker) { threadCounter--; } }, new RayTracerTaskWorker(modelIdx, 0, y, z)); task.Start(); } } // Wait for Multithread parts to finish. while (threadCounter > 0) { System.Windows.Forms.Application.DoEvents(); if (checkCancel != null && checkCancel.Invoke()) { break; } } GC.Collect(); } #endregion #region Y rays trace if ((traceDirection & TraceDirection.Y) == TraceDirection.Y) { Debug.WriteLine("Y Rays"); traceDirectionCount++; threadCounter = (xMax - xMin) * (zMax - zMin); for (var x = xMin; x < xMax; x++) { for (var z = zMin; z < zMax; z++) { if (checkCancel != null && checkCancel.Invoke()) { if (complete != null) { complete.Invoke(); } return(null); } List <Point3D[]> testRays = null; if (traceType == TraceType.Odd) { testRays = new List <Point3D[]> { new [] { new Point3D(x + offset, yMin, z + offset), new Point3D(x + offset, yMax, z + offset) }, new [] { new Point3D(x - 0.5f + offset, yMin, z - 0.5f + offset), new Point3D(x - 0.5f + offset, yMax, z - 0.5f + offset) }, new [] { new Point3D(x + 0.5f - offset, yMin, z - 0.5f + offset), new Point3D(x + 0.5f - offset, yMax, z - 0.5f + offset) }, new [] { new Point3D(x - 0.5f + offset, yMin, z + 0.5f - offset), new Point3D(x - 0.5f + offset, yMax, z + 0.5f - offset) }, new [] { new Point3D(x + 0.5f - offset, yMin, z + 0.5f - offset), new Point3D(x + 0.5f - offset, yMax, z + 0.5f - offset) } } } ; else if (traceType == TraceType.Even) { testRays = new List <Point3D[]> { new [] { new Point3D(x + 0.5f - offset, yMin, z + 0.5f - offset), new Point3D(x + 0.5f - offset, yMax, z + 0.5f - offset) }, new [] { new Point3D(x + offset, yMin, z + offset), new Point3D(x + offset, yMax, z + offset) }, new [] { new Point3D(x + 1.0f - offset, yMin, z + offset), new Point3D(x + 1.0f - offset, yMax, z + offset) }, new [] { new Point3D(x + offset, yMin, z + 1.0f - offset), new Point3D(x + offset, yMax, z + 1.0f - offset) }, new [] { new Point3D(x + 1.0f - offset, yMin, z + 1.0f - offset), new Point3D(x + 1.0f - offset, yMax, z + 1.0f - offset) } } } ; var task = new Task(obj => { var bgw = (RayTracerTaskWorker)obj; var tracers = new List <Trace>(); foreach (var geometery in geometries) { for (var t = 0; t < geometery.Triangles.Length; t += 3) { if (checkCancel != null && checkCancel.Invoke()) { return; } if (incrementProgress != null) { lock (Locker) { incrementProgress.Invoke(); } } var p1 = geometery.Positions[geometery.Triangles[t]]; var p2 = geometery.Positions[geometery.Triangles[t + 1]]; var p3 = geometery.Positions[geometery.Triangles[t + 2]]; if (rotate.HasValue) { p1 = rotate.Value.Transform(p1); p2 = rotate.Value.Transform(p2); p3 = rotate.Value.Transform(p3); } foreach (var ray in testRays) { if ((p1.X < ray[0].X && p2.X < ray[0].X && p3.X < ray[0].X) || (p1.X > ray[0].X && p2.X > ray[0].X && p3.X > ray[0].X) || (p1.Z < ray[0].Z && p2.Z < ray[0].Z && p3.Z < ray[0].Z) || (p1.Z > ray[0].Z && p2.Z > ray[0].Z && p3.Z > ray[0].Z)) { continue; } Point3D intersect; int normal; if (MeshHelper.RayIntersetTriangleRound(p1, p2, p3, ray[0], ray[1], out intersect, out normal)) { tracers.Add(new Trace(intersect, normal)); } } } } if (tracers.Count > 1) { var order = tracers.GroupBy(t => new { t.Point, t.Face }).Select(g => g.First()).OrderBy(k => k.Point.Y).ToArray(); var startCoord = roundFunc(order[0].Point.Y); var endCoord = roundFunc(order[order.Length - 1].Point.Y); var surfaces = 0; for (var y = startCoord; y <= endCoord; y++) { var points = order.Where(p => p.Point.Y > y - startOffset && p.Point.Y < y + endOffset).ToArray(); var volume = (byte)(0xff / testRays.Count * surfaces); foreach (var point in points) { if (point.Face == MeshFace.Farside) { volume += (byte)(Math.Round(Math.Abs(y + volumeOffset - point.Point.Y) * 255 / testRays.Count, 0)); surfaces++; } else if (point.Face == MeshFace.Nearside) { volume -= (byte)(Math.Round(Math.Abs(y + volumeOffset - point.Point.Y) * 255 / testRays.Count, 0)); surfaces--; } } if (traceDirectionCount > 1) { var prevolumme = modelCubic[bgw.X - xMin][y - yMin][bgw.Z - zMin]; if (prevolumme != 0) { // average with the pre-existing X volume. volume = (byte)Math.Round(((float)prevolumme + (float)volume) / (float)traceDirectionCount, 0); } } //volume = volume.RoundUpToNearest(8); modelCubic[bgw.X - xMin][y - yMin][bgw.Z - zMin] = volume; modelMater[bgw.X - xMin][y - yMin][bgw.Z - zMin] = materials[bgw.ModelIdx]; } if (faceMaterials[bgw.ModelIdx] != 0xff) { for (var i = 1; i < 6; i++) { if (yMin < startCoord - i && modelCubic[bgw.X - xMin][startCoord - i - yMin][bgw.Z - zMin] == 0) { modelMater[bgw.X - xMin][startCoord - i - yMin][bgw.Z - zMin] = faceMaterials[bgw.ModelIdx]; } if (endCoord + i < yMax && modelCubic[bgw.X - xMin][endCoord + i - yMin][bgw.Z - zMin] == 0) { modelMater[bgw.X - xMin][endCoord + i - yMin][bgw.Z - zMin] = faceMaterials[bgw.ModelIdx]; } } } } lock (Locker) { threadCounter--; } }, new RayTracerTaskWorker(modelIdx, x, 0, z)); task.Start(); } } // Wait for Multithread parts to finish. while (threadCounter > 0) { System.Windows.Forms.Application.DoEvents(); if (checkCancel != null && checkCancel.Invoke()) { break; } } GC.Collect(); } #endregion #region Z ray trace if ((traceDirection & TraceDirection.Z) == TraceDirection.Z) { Debug.WriteLine("Z Rays"); traceDirectionCount++; threadCounter = (xMax - xMin) * (yMax - yMin); for (var x = xMin; x < xMax; x++) { for (var y = yMin; y < yMax; y++) { if (checkCancel != null && checkCancel.Invoke()) { if (complete != null) { complete.Invoke(); } return(null); } List <Point3D[]> testRays = null; if (traceType == TraceType.Odd) { testRays = new List <Point3D[]> { new [] { new Point3D(x + offset, y + offset, zMin), new Point3D(x + offset, y + offset, zMax) }, new [] { new Point3D(x - 0.5f + offset, y - 0.5f + offset, zMin), new Point3D(x - 0.5f + offset, y - 0.5f + offset, zMax) }, new [] { new Point3D(x + 0.5f - offset, y - 0.5f + offset, zMin), new Point3D(x + 0.5f - offset, y - 0.5f + offset, zMax) }, new [] { new Point3D(x - 0.5f + offset, y + 0.5f - offset, zMin), new Point3D(x - 0.5f + offset, y + 0.5f - offset, zMax) }, new [] { new Point3D(x + 0.5f - offset, y + 0.5f - offset, zMin), new Point3D(x + 0.5f - offset, y + 0.5f - offset, zMax) } } } ; else if (traceType == TraceType.Even) { testRays = new List <Point3D[]> { new [] { new Point3D(x + 0.5f - offset, y + 0.5f - offset, zMin), new Point3D(x + 0.5f - offset, y + 0.5f - offset, zMax) }, new [] { new Point3D(x + offset, y + offset, zMin), new Point3D(x + offset, y + offset, zMax) }, new [] { new Point3D(x + 1.0f - offset, y + offset, zMin), new Point3D(x + 1.0f - offset, y + offset, zMax) }, new [] { new Point3D(x + offset, y + 1.0f - offset, zMin), new Point3D(x + offset, y + 1.0f - offset, zMax) }, new [] { new Point3D(x + 1.0f - offset, y + 1.0f - offset, zMin), new Point3D(x + 1.0f - offset, y + 1.0f - offset, zMax) } } } ; var task = new Task(obj => { var bgw = (RayTracerTaskWorker)obj; var tracers = new List <Trace>(); foreach (var geometery in geometries) { for (var t = 0; t < geometery.Triangles.Length; t += 3) { if (checkCancel != null && checkCancel.Invoke()) { return; } if (incrementProgress != null) { lock (Locker) { incrementProgress.Invoke(); } } var p1 = geometery.Positions[geometery.Triangles[t]]; var p2 = geometery.Positions[geometery.Triangles[t + 1]]; var p3 = geometery.Positions[geometery.Triangles[t + 2]]; if (rotate.HasValue) { p1 = rotate.Value.Transform(p1); p2 = rotate.Value.Transform(p2); p3 = rotate.Value.Transform(p3); } foreach (var ray in testRays) { if ((p1.X < ray[0].X && p2.X < ray[0].X && p3.X < ray[0].X) || (p1.X > ray[0].X && p2.X > ray[0].X && p3.X > ray[0].X) || (p1.Y < ray[0].Y && p2.Y < ray[0].Y && p3.Y < ray[0].Y) || (p1.Y > ray[0].Y && p2.Y > ray[0].Y && p3.Y > ray[0].Y)) { continue; } Point3D intersect; int normal; if (MeshHelper.RayIntersetTriangleRound(p1, p2, p3, ray[0], ray[1], out intersect, out normal)) { tracers.Add(new Trace(intersect, normal)); } } } } if (tracers.Count > 1) { var order = tracers.GroupBy(t => new { t.Point, t.Face }).Select(g => g.First()).OrderBy(k => k.Point.Z).ToArray(); var startCoord = roundFunc(order[0].Point.Z); var endCoord = roundFunc(order[order.Length - 1].Point.Z); var surfaces = 0; for (var z = startCoord; z <= endCoord; z++) { var points = order.Where(p => p.Point.Z > z - startOffset && p.Point.Z < z + endOffset).ToArray(); var volume = (byte)(0xff / testRays.Count * surfaces); foreach (var point in points) { if (point.Face == MeshFace.Farside) { volume += (byte)(Math.Round(Math.Abs(z + volumeOffset - point.Point.Z) * 255 / testRays.Count, 0)); surfaces++; } else if (point.Face == MeshFace.Nearside) { volume -= (byte)(Math.Round(Math.Abs(z + volumeOffset - point.Point.Z) * 255 / testRays.Count, 0)); surfaces--; } } if (traceDirectionCount > 1) { var prevolumme = modelCubic[bgw.X - xMin][bgw.Y - yMin][z - zMin]; if (prevolumme != 0) { // average with the pre-existing X and Y volumes. volume = (byte)Math.Round((((float)prevolumme * (traceDirectionCount - 1)) + (float)volume) / (float)traceDirectionCount, 0); } } //volume = volume.RoundUpToNearest(8); modelCubic[bgw.X - xMin][bgw.Y - yMin][z - zMin] = volume; modelMater[bgw.X - xMin][bgw.Y - yMin][z - zMin] = materials[bgw.ModelIdx]; } if (faceMaterials[bgw.ModelIdx] != 0xff) { for (var i = 1; i < 6; i++) { if (zMin < startCoord - i && modelCubic[bgw.X - xMin][bgw.Y - yMin][startCoord - i - zMin] == 0) { modelMater[bgw.X - xMin][bgw.Y - yMin][startCoord - i - zMin] = faceMaterials[bgw.ModelIdx]; } if (endCoord + i < zMax && modelCubic[bgw.X - xMin][bgw.Y - yMin][endCoord + i - zMin] == 0) { modelMater[bgw.X - xMin][bgw.Y - yMin][endCoord + i - zMin] = faceMaterials[bgw.ModelIdx]; } } } } lock (Locker) { threadCounter--; } }, new RayTracerTaskWorker(modelIdx, x, y, 0)); task.Start(); } } // Wait for Multithread parts to finish. while (threadCounter > 0) { System.Windows.Forms.Application.DoEvents(); if (checkCancel != null && checkCancel.Invoke()) { break; } } GC.Collect(); } #endregion if (checkCancel != null && checkCancel.Invoke()) { if (complete != null) { complete.Invoke(); } return(null); } #region merge individual model results into final for (var x = 0; x < xCount; x++) { for (var y = 0; y < yCount; y++) { for (var z = 0; z < zCount; z++) { if (modelMater[x][y][z] == 0xff && modelCubic[x][y][z] != 0) { finalCubic[x][y][z] = (byte)Math.Max(finalCubic[x][y][z] - modelCubic[x][y][z], 0); } else if (modelCubic[x][y][z] != 0) { finalCubic[x][y][z] = Math.Max(finalCubic[x][y][z], modelCubic[x][y][z]); finalMater[x][y][z] = modelMater[x][y][z]; } else if (finalCubic[x][y][z] == 0 && finalMater[x][y][z] == 0 && modelMater[x][y][z] != 0xff) { finalMater[x][y][z] = modelMater[x][y][z]; } } } } #endregion } // end models #endregion if (checkCancel != null && checkCancel.Invoke()) { if (complete != null) { complete.Invoke(); } return(null); } var size = new Vector3I(xCount, yCount, zCount); // TODO: at the moment the Mesh list is not complete, so the faceMaterial setting is kind of vague. var defaultMaterial = mappedMesh[0].Material; // Use the FaceMaterial from the first Mesh in the object list. var faceMaterial = mappedMesh[0].FaceMaterial; // Use the FaceMaterial from the first Mesh in the object list. var action = (Action <MyVoxelBuilderArgs>) delegate(MyVoxelBuilderArgs e) { e.Volume = finalCubic[e.CoordinatePoint.X][e.CoordinatePoint.Y][e.CoordinatePoint.Z]; e.Material = SpaceEngineersCore.Resources.GetMaterialName(finalMater[e.CoordinatePoint.X][e.CoordinatePoint.Y][e.CoordinatePoint.Z]); }; var voxelMap = MyVoxelBuilder.BuildAsteroid(true, size, defaultMaterial, faceMaterial, action); if (complete != null) { complete.Invoke(); } return(voxelMap); }
static void Add(MyMwcVoxelFilesEnum voxelFileEnum, Vector3I sizeInVoxels, string filename) { DefaultVoxelFiles[(int)voxelFileEnum] = new MyVoxelFile(voxelFileEnum, sizeInVoxels, filename); }
bool CanPlace(Vector3I coords) { return((Map.GetBlock(coords) == SourceBlock) && Player.CanPlace(Map, coords, ReplacementBlock, Context) == CanPlaceResult.Allowed); }
public void TestVoxelNavmeshTriangle(ref Vector3D a, ref Vector3D b, ref Vector3D c, List <MyCubeGrid> gridsToTest, List <MyGridPathfinding.CubeId> linkCandidatesOutput, out bool intersecting) { Vector3D point = ((a + b) + c) / 3.0; if (this.m_obstacles.IsInObstacle(point)) { intersecting = true; return; } Vector3D zero = Vector3D.Zero; if (MyPerGameSettings.NavmeshPresumesDownwardGravity) { zero = Vector3.Down * 2f; } m_tmpLinkCandidates.Clear(); intersecting = false; using (List <MyCubeGrid> .Enumerator enumerator = gridsToTest.GetEnumerator()) { goto TR_0016; TR_0008: if (intersecting) { goto TR_0006; } TR_0016: while (true) { if (enumerator.MoveNext()) { Vector3D vectord2; Vector3D vectord3; Vector3D vectord4; Vector3D vectord5; MyCubeGrid current = enumerator.Current; MatrixD worldMatrixNormalizedInv = current.PositionComp.WorldMatrixNormalizedInv; Vector3D.Transform(ref a, ref worldMatrixNormalizedInv, out vectord2); Vector3D.Transform(ref b, ref worldMatrixNormalizedInv, out vectord3); Vector3D.Transform(ref c, ref worldMatrixNormalizedInv, out vectord4); Vector3D.TransformNormal(ref zero, ref worldMatrixNormalizedInv, out vectord5); BoundingBoxD xd = new BoundingBoxD(Vector3D.MaxValue, Vector3D.MinValue); xd.Include(ref vectord2, ref vectord3, ref vectord4); Vector3I vectori = current.LocalToGridInteger((Vector3)xd.Min); Vector3I vectori2 = current.LocalToGridInteger((Vector3)xd.Max); Vector3I start = vectori - Vector3I.One; Vector3I end = (Vector3I)(vectori2 + Vector3I.One); Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref start, ref end); while (iterator.IsValid()) { if (current.GetCubeBlock(start) != null) { Vector3 min = (Vector3)((start - Vector3.One) * current.GridSize); Vector3 max = (start + Vector3.One) * current.GridSize; Vector3 vector3 = (Vector3)((start - Vector3.Half) * current.GridSize); Vector3 vector4 = (start + Vector3.Half) * current.GridSize; BoundingBoxD xd3 = new BoundingBoxD(min, max); BoundingBoxD xd4 = new BoundingBoxD(vector3, vector4); xd3.Include(min + vectord5); xd3.Include(max + vectord5); xd4.Include(vector3 + vectord5); xd4.Include(vector4 + vectord5); if (xd3.IntersectsTriangle(ref vectord2, ref vectord3, ref vectord4)) { if (xd4.IntersectsTriangle(ref vectord2, ref vectord3, ref vectord4)) { intersecting = true; break; } int num3 = Math.Min(Math.Abs((int)(vectori.Z - start.Z)), Math.Abs((int)(vectori2.Z - start.Z))); if (((Math.Min(Math.Abs((int)(vectori.X - start.X)), Math.Abs((int)(vectori2.X - start.X))) + Math.Min(Math.Abs((int)(vectori.Y - start.Y)), Math.Abs((int)(vectori2.Y - start.Y)))) + num3) < 3) { MyGridPathfinding.CubeId item = new MyGridPathfinding.CubeId { Grid = current, Coords = start }; m_tmpLinkCandidates.Add(item); } } } iterator.GetNext(out start); } } else { goto TR_0006; } break; } goto TR_0008; } TR_0006: if (!intersecting) { for (int i = 0; i < m_tmpLinkCandidates.Count; i++) { linkCandidatesOutput.Add(m_tmpLinkCandidates[i]); } } m_tmpLinkCandidates.Clear(); }
private static double[,] InterpolateResult(double[,] dataNoises, Vector3I NoiseSampledSteps, Vector3I StepsCount) { int nbrNoises = dataNoises.GetLength(1); //Create a new array with expended size double[,] result = new double[StepsCount.X * StepsCount.Y * StepsCount.Z, nbrNoises]; int dataNoisesXSize = NoiseSampledSteps.X + 1; int dataNoisesYSize = NoiseSampledSteps.Y + 1; int dataNoisesZSize = NoiseSampledSteps.Z + 1; int XPointLerpedCount = StepsCount.X / NoiseSampledSteps.X; int ZPointLerpedCount = StepsCount.Z / NoiseSampledSteps.Z; int YPointLerpedCount = StepsCount.Y / NoiseSampledSteps.Y; //Loop against the generated noise values int noiseGeneratedResultIndex = 0; for (int noiseId = 0; noiseId < nbrNoises; noiseId++) { for (int SampledpointX = 0; SampledpointX < NoiseSampledSteps.X; SampledpointX++) { for (int SampledpointZ = 0; SampledpointZ < NoiseSampledSteps.Z; SampledpointZ++) { for (int SampledpointY = 0; SampledpointY < NoiseSampledSteps.Y; SampledpointY++) { double NoiseX0Z0Y0 = dataNoises[((SampledpointX + 0) * dataNoisesZSize + (SampledpointZ + 0)) * dataNoisesYSize + (SampledpointY + 0), noiseId]; double NoiseX0Z1Y0 = dataNoises[((SampledpointX + 0) * dataNoisesZSize + (SampledpointZ + 1)) * dataNoisesYSize + (SampledpointY + 0), noiseId]; double NoiseX1Z0Y0 = dataNoises[((SampledpointX + 1) * dataNoisesZSize + (SampledpointZ + 0)) * dataNoisesYSize + (SampledpointY + 0), noiseId]; double NoiseX1Z1Y0 = dataNoises[((SampledpointX + 1) * dataNoisesZSize + (SampledpointZ + 1)) * dataNoisesYSize + (SampledpointY + 0), noiseId]; double DeltaX0Z0 = (dataNoises[((SampledpointX + 0) * dataNoisesZSize + (SampledpointZ + 0)) * dataNoisesYSize + (SampledpointY + 1), noiseId] - NoiseX0Z0Y0) / YPointLerpedCount; // 128 / 16 = 8 points need to be lerped 4 times ! double DeltaX0Z1 = (dataNoises[((SampledpointX + 0) * dataNoisesZSize + (SampledpointZ + 1)) * dataNoisesYSize + (SampledpointY + 1), noiseId] - NoiseX0Z1Y0) / YPointLerpedCount; // 128 / 16 = 8 points need to be lerped 4 times ! double DeltaX1Z0 = (dataNoises[((SampledpointX + 1) * dataNoisesZSize + (SampledpointZ + 0)) * dataNoisesYSize + (SampledpointY + 1), noiseId] - NoiseX1Z0Y0) / YPointLerpedCount; // 128 / 16 = 8 points need to be lerped 4 times ! double DeltaX1Z1 = (dataNoises[((SampledpointX + 1) * dataNoisesZSize + (SampledpointZ + 1)) * dataNoisesYSize + (SampledpointY + 1), noiseId] - NoiseX1Z1Y0) / YPointLerpedCount; // 128 / 16 = 8 points need to be lerped 4 times ! for (int Y = 0; Y < YPointLerpedCount; Y++) { double NoiseZ0 = NoiseX0Z0Y0; double NoiseZ1 = NoiseX1Z0Y0; double DeltaZ0 = (NoiseX0Z1Y0 - NoiseX0Z0Y0) / ZPointLerpedCount; // Chunk X length = 16 / 4 = 4 points needs to be lerped Twice! double DeltaZ1 = (NoiseX1Z1Y0 - NoiseX1Z0Y0) / ZPointLerpedCount; int nY = (SampledpointY * YPointLerpedCount) + Y; for (int Z = 0; Z < ZPointLerpedCount; Z++) { double NoiseFinalValue = NoiseZ0; double DeltaX = (NoiseZ1 - NoiseZ0) / XPointLerpedCount; // Chunk Z length = 16 / 4 = 4 points needs to be lerped Once! int nZ = (SampledpointZ * ZPointLerpedCount) + Z; for (int X = 0; X < XPointLerpedCount; X++) { int nX = (SampledpointX * XPointLerpedCount) + X; result[nX * StepsCount.Z * StepsCount.Y + nZ * StepsCount.Y + nY, noiseId] = NoiseFinalValue; noiseGeneratedResultIndex++; NoiseFinalValue += DeltaX; } NoiseZ0 += DeltaZ0; NoiseZ1 += DeltaZ1; } NoiseX0Z0Y0 += DeltaX0Z0; NoiseX0Z1Y0 += DeltaX0Z1; NoiseX1Z0Y0 += DeltaX1Z0; NoiseX1Z1Y0 += DeltaX1Z1; } } } } } return(result); }
public override bool Prepare(Vector3I[] marks) { if (marks == null) { throw new ArgumentNullException("marks"); } if (marks.Length < 1) { throw new ArgumentException("At least one mark needed.", "marks"); } if (ReplacementBlock == Block.None) { if (Player.LastUsedBlockType == Block.None) { Player.Message("Cannot deduce desired replacement block. Click a block or type out the block name."); return(false); } else { ReplacementBlock = Player.GetBind(Player.LastUsedBlockType); } } Marks = marks; Origin = marks[0]; SourceBlock = Map.GetBlock(Origin); Vector3I playerCoords = Player.Position.ToBlockCoords(); Vector3I lookVector = (Origin - playerCoords); Axis = lookVector.LongestAxis; Vector3I maxDelta; maxFillExtent = Player.Info.Rank.FillLimit; if (maxFillExtent < 1 || maxFillExtent > 2048) { maxFillExtent = 2048; } switch (Axis) { case Axis.X: maxDelta = new Vector3I(0, maxFillExtent, maxFillExtent); coordEnumerator = BlockEnumeratorX().GetEnumerator(); break; case Axis.Y: maxDelta = new Vector3I(maxFillExtent, 0, maxFillExtent); coordEnumerator = BlockEnumeratorY().GetEnumerator(); break; default: // Z maxDelta = new Vector3I(maxFillExtent, maxFillExtent, 0); coordEnumerator = BlockEnumeratorZ().GetEnumerator(); break; } if (SourceBlock == ReplacementBlock) { Bounds = new BoundingBox(Origin, Origin); } else { Bounds = new BoundingBox(Origin - maxDelta, Origin + maxDelta); } // Clip bounds to the map, used to limit fill extent Bounds = Bounds.GetIntersection(Map.Bounds); // Set everything up for filling Brush = this; Coords = Origin; StartTime = DateTime.UtcNow; Context = BlockChangeContext.Drawn | BlockChangeContext.Filled; BlocksTotalEstimate = Bounds.Volume; return(true); }
private static void GetCellCorners(ref Vector3I minCorner, ref Vector3I maxCorner, ref Vector3I_RangeIterator it, out Vector3I cellMinCorner, out Vector3I cellMaxCorner) { cellMinCorner = new Vector3I(minCorner.X + it.Current.X * CELL_SIZE, minCorner.Y + it.Current.Y * CELL_SIZE, minCorner.Z + it.Current.Z * CELL_SIZE); cellMaxCorner = new Vector3I(Math.Min(maxCorner.X, cellMinCorner.X + CELL_SIZE), Math.Min(maxCorner.Y, cellMinCorner.Y + CELL_SIZE), Math.Min(maxCorner.Z, cellMinCorner.Z + CELL_SIZE)); }
/// <summary> /// Will present the result of the noise inside a single Array[] /// The 3dimension are present inside this array in this order : X, Z and then Y /// It means to compute the array indice, use this formula : X * Zlength * Ylength + Z * Ylength + Y /// </summary> /// <param name="noiseFct">The Noise function</param> /// <param name="NoiseSampledSteps">The qt of steps that will be evaluated into by the noise fct, if qt below StepsCountX, the remaining Steps will be interpolated !! SampledSteps values MUST be a multiple of StepsCountn</param> /// <param name="FromX">Low X sampling Range</param> /// <param name="ToX">High X sampling Range</param> /// <param name="StepsCountX">Nbr of step sampled at equal distance from FromX to ToX</param> /// <param name="FromY">Low Y sampling Range</param> /// <param name="ToY">High Y sampling Range</param> /// <param name="StepsCountY">Nbr of step sampled at equal distance from FromY to ToY</param> /// <param name="FromZ">Low Z sampling Range</param> /// <param name="ToZ">High Z sampling Range</param> /// <param name="StepsCountZ">Nbr of step sampled at equal distance from FromZ to ToZ</param> /// <returns>Signle dimension array with the noise result</returns> public static double[,] NoiseSampling(Vector3I NoiseSampledSteps, double FromX, double ToX, int StepsCountX, double FromY, double ToY, int StepsCountY, double FromZ, double ToZ, int StepsCountZ, params INoise3[] noiseFcts) { bool needInterpolation = false; if (NoiseSampledSteps.X != StepsCountX || NoiseSampledSteps.Y != StepsCountY || NoiseSampledSteps.Z != StepsCountZ) { if (StepsCountX % NoiseSampledSteps.X != 0 || StepsCountY % NoiseSampledSteps.Y != 0 || StepsCountZ % NoiseSampledSteps.Z != 0) { throw new Exception("NoiseSampling using NoiseSampledSteps that are not a multiple of StepsCount"); } //CHECK for NoiseSampledSteps validity ! needInterpolation = true; } int sampledStepCountX = NoiseSampledSteps.X; int sampledStepCountY = NoiseSampledSteps.Y; int sampledStepCountZ = NoiseSampledSteps.Z; if (needInterpolation) { sampledStepCountX++; // +1 If in Lerping Mode sampledStepCountY++; // +1 If in Lerping Mode sampledStepCountZ++; // +1 If in Lerping Mode } int NbrNoisesToParse = noiseFcts.Length; double[,] result = new double[(sampledStepCountX) * (sampledStepCountY) * (sampledStepCountZ), NbrNoisesToParse]; double samplingStepDeltaX = (ToX - FromX) / (sampledStepCountX - 1); double samplingStepDeltaY = (ToY - FromY) / (sampledStepCountY - 1); double samplingStepDeltaZ = (ToZ - FromZ) / (sampledStepCountZ - 1); int generatedNoise = 0; double valX, valY, valZ; //Sampled the Noise valX = FromX; for (int X = 0; X < sampledStepCountX; X++) { valZ = FromZ; for (int Z = 0; Z < sampledStepCountZ; Z++) { valY = FromY; for (int Y = 0; Y < sampledStepCountY; Y++) { for (int noiseId = 0; noiseId < NbrNoisesToParse; noiseId++) { result[generatedNoise, noiseId] = noiseFcts[noiseId].Get(valX, valY, valZ); } generatedNoise++; valY += samplingStepDeltaY; } valZ += samplingStepDeltaZ; } valX += samplingStepDeltaX; } if (needInterpolation) { result = InterpolateResult(result, NoiseSampledSteps, new Vector3I(StepsCountX, StepsCountY, StepsCountZ)); } return(result); }
private static void ComputeShapeBounds(IMyVoxelBase voxelMap, ref BoundingBoxD shapeAabb, Vector3D voxelMapMinCorner, Vector3I storageSize, out Vector3I voxelMin, out Vector3I voxelMax) { MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMapMinCorner, ref shapeAabb.Min, out voxelMin); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMapMinCorner, ref shapeAabb.Max, out voxelMax); MyVoxelBase voxelBase = voxelMap as MyVoxelBase; voxelMin += voxelBase.StorageMin; voxelMax += voxelBase.StorageMin + 1; storageSize -= 1; Vector3I.Clamp(ref voxelMin, ref Vector3I.Zero, ref storageSize, out voxelMin); Vector3I.Clamp(ref voxelMax, ref Vector3I.Zero, ref storageSize, out voxelMax); }
public abstract void GetBlockPlacementMaterials(MyCubeBlockDefinition definition, Vector3I position, MyBlockOrientation orientation, MyCubeGrid grid);
public override void UpdateBeforeSimulation10() { base.UpdateBeforeSimulation10(); if (!CheckUnobstructed()) { if (SafeConstraint != null) { RemoveConstraintInBoth(); } return; } if (SafeConstraint != null) { bool staticOk = this.CubeGrid.IsStatic || !m_other.CubeGrid.IsStatic; if (!staticOk || !IsWorking || !m_other.IsWorking) { return; } Debug.Assert(!m_other.CubeGrid.MarkedForClose && !CubeGrid.MarkedForClose); var mergeBlockDefinition = this.BlockDefinition as MyMergeBlockDefinition; float maxStrength = mergeBlockDefinition != null ? mergeBlockDefinition.Strength : 0.1f; float dist = (float)(WorldMatrix.Translation - m_other.WorldMatrix.Translation).Length() - CubeGrid.GridSize; if (dist > CubeGrid.GridSize * 3) { RemoveConstraintInBoth(); return; } MergeData data = new MergeData(); CalculateMergeData(ref data); (m_constraint.ConstraintData as HkMalleableConstraintData).Strength = data.ConstraintStrength; if (data.PositionOk && data.AxisOk && data.RotationOk) { if (m_frameCounter++ >= 3) { Vector3I gridOffset = CalculateOtherGridOffset(); Vector3I otherGridOffset = m_other.CalculateOtherGridOffset(); bool canMerge = this.CubeGrid.CanMergeCubes(m_other.CubeGrid, gridOffset); if (!canMerge) { if (this.CubeGrid.GridSystems.ControlSystem.IsLocallyControlled || m_other.CubeGrid.GridSystems.ControlSystem.IsLocallyControlled) { MyHud.Notifications.Add(MyNotificationSingletons.ObstructingBlockDuringMerge); } return; } var handle = BeforeMerge; if (handle != null) { BeforeMerge(); } if (Sync.IsServer) { foreach (var block in CubeGrid.GetBlocks()) { var mergeBlock = block.FatBlock as MyShipMergeBlock; if (mergeBlock != null && mergeBlock != this && mergeBlock.InConstraint) { (block.FatBlock as MyShipMergeBlock).RemoveConstraintInBoth(); } } MyCubeGrid mergedGrid = this.CubeGrid.MergeGrid_MergeBlock(m_other.CubeGrid, gridOffset); if (mergedGrid == null) { mergedGrid = m_other.CubeGrid.MergeGrid_MergeBlock(this.CubeGrid, otherGridOffset); } Debug.Assert(mergedGrid != null); RemoveConstraintInBoth(); } } } else { m_frameCounter = 0; } return; } foreach (var other in m_gridList) { if (other.MarkedForClose) { continue; } Vector3I pos = Vector3I.Zero; double dist = double.MaxValue; LineD l = new LineD(Physics.ClusterToWorld(Physics.RigidBody.Position), Physics.ClusterToWorld(Physics.RigidBody.Position) + GetMergeNormalWorld()); if (other.GetLineIntersectionExactGrid(ref l, ref pos, ref dist)) { var block = other.GetCubeBlock(pos).FatBlock as MyShipMergeBlock; if (block == null || block.InConstraint || !block.IsWorking || !block.CheckUnobstructed() || block.GetMergeNormalWorld().Dot(GetMergeNormalWorld()) > 0.0f) { return; } if (!block.FriendlyWithBlock(this)) { return; } CreateConstraint(other, block); NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; m_updateBeforeFlags |= UpdateBeforeFlags.EnableConstraint; break; } } }
private static void GetVoxelShapeDimensions(IMyVoxelBase voxelMap, NaniteShape shape, out Vector3I minCorner, out Vector3I maxCorner, out Vector3I numCells) { { var bbox = shape.GetWorldBoundaries(); ComputeShapeBounds(voxelMap, ref bbox, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner); } numCells = new Vector3I((maxCorner.X - minCorner.X) / CELL_SIZE, (maxCorner.Y - minCorner.Y) / CELL_SIZE, (maxCorner.Z - minCorner.Z) / CELL_SIZE); }
public override void OnMouseClick(VoxState s, FreeCamera camera, Vector2 mPos, MouseButton button, Viewport vp) { Ray r = camera.GetViewRay(mPos, vp.Width, vp.Height); if(button == MouseButton.Left) { VoxLocation? vl = VRayHelper.GetInner(r, s); if(vl.HasValue) { var loc = vl.Value; if(hasStart) { Vector3I end = new Vector3I( loc.RegionLoc.X * Region.WIDTH + loc.VoxelLoc.X, loc.VoxelLoc.Y, loc.RegionLoc.Y * Region.DEPTH + loc.VoxelLoc.Z ); Vector3I min = new Vector3I(Math.Min(start.X, end.X), Math.Min(start.Y, end.Y), Math.Min(start.Z, end.Z)); Vector3I max = new Vector3I(Math.Max(start.X, end.X), Math.Max(start.Y, end.Y), Math.Max(start.Z, end.Z)); for(int ry = min.Y; ry <= max.Y; ry++) { for(int rz = min.Z; rz <= max.Z; rz++) { for(int rx = min.X; rx <= max.X; rx++) { loc = new VoxLocation(new Vector3I(rx, ry, rz)); s.World.regions[loc.RegionIndex].RemoveVoxel(loc.VoxelLoc.X, loc.VoxelLoc.Y, loc.VoxelLoc.Z); } } } hasStart = false; } else { start = new Vector3I( loc.RegionLoc.X * Region.WIDTH + loc.VoxelLoc.X, loc.VoxelLoc.Y, loc.RegionLoc.Y * Region.DEPTH + loc.VoxelLoc.Z ); hasStart = true; } } } else if(button == MouseButton.Right) { VoxLocation? vl = VRayHelper.GetOuter(r, s); if(vl.HasValue) { var loc = vl.Value; if(hasStart) { Vector3I end = new Vector3I( loc.RegionLoc.X * Region.WIDTH + loc.VoxelLoc.X, loc.VoxelLoc.Y, loc.RegionLoc.Y * Region.DEPTH + loc.VoxelLoc.Z ); Vector3I min = new Vector3I(Math.Min(start.X, end.X), Math.Min(start.Y, end.Y), Math.Min(start.Z, end.Z)); Vector3I max = new Vector3I(Math.Max(start.X, end.X), Math.Max(start.Y, end.Y), Math.Max(start.Z, end.Z)); for(int ry = min.Y; ry <= max.Y; ry++) { for(int rz = min.Z; rz <= max.Z; rz++) { for(int rx = min.X; rx <= max.X; rx++) { loc = new VoxLocation(new Vector3I(rx, ry, rz)); s.World.regions[loc.RegionIndex].AddVoxel(loc.VoxelLoc.X, loc.VoxelLoc.Y, loc.VoxelLoc.Z, CurVoxID); } } } hasStart = false; } else { start = new Vector3I( loc.RegionLoc.X * Region.WIDTH + loc.VoxelLoc.X, loc.VoxelLoc.Y, loc.RegionLoc.Y * Region.DEPTH + loc.VoxelLoc.Z ); hasStart = true; } } } }
public override bool ConnectionAllowed(ref Vector3I otherBlockMinPos, ref Vector3I otherBlockMaxPos, ref Vector3I faceNormal, MyCubeBlockDefinition def) { return(ConnectionAllowedInternal(ref faceNormal, def)); }
public static void CalculateSamplePosition(ref Vector3 localPos, out Vector3I samplePosition, ref Vector2 texCoord, int resolution) { Vector3 abs = Vector3.Abs(localPos); if (abs.X > abs.Y) { if (abs.X > abs.Z) { localPos /= abs.X; texCoord.Y = -localPos.Y; if (localPos.X > 0.0f) { texCoord.X = -localPos.Z; samplePosition.X = (int)Faces.XPositive; } else { texCoord.X = localPos.Z; samplePosition.X = (int)Faces.XNegative; } } else { localPos /= abs.Z; texCoord.Y = -localPos.Y; if (localPos.Z > 0.0f) { texCoord.X = localPos.X; samplePosition.X = (int)Faces.ZPositive; } else { texCoord.X = -localPos.X; samplePosition.X = (int)Faces.ZNegative; } } } else { if (abs.Y > abs.Z) { localPos /= abs.Y; texCoord.Y = -localPos.Z; if (localPos.Y > 0.0f) { texCoord.X = -localPos.X; samplePosition.X = (int)Faces.YPositive; } else { texCoord.X = localPos.X; samplePosition.X = (int)Faces.YNegative; } } else { localPos /= abs.Z; texCoord.Y = -localPos.Y; if (localPos.Z > 0.0f) { texCoord.X = localPos.X; samplePosition.X = (int)Faces.ZPositive; } else { texCoord.X = -localPos.X; samplePosition.X = (int)Faces.ZNegative; } } } texCoord = ((texCoord + 1f) * .5f * resolution); samplePosition.Y = (int)Math.Round(texCoord.X); samplePosition.Z = (int)Math.Round(texCoord.Y); }
public void ProcessStrafing() { if (!this.AllowStrafing) { return; } if (this.Strafing == false) { TimeSpan duration = MyAPIGateway.Session.GameDateTime - this.LastStrafeEndTime; if (duration.TotalMilliseconds >= this.ThisStrafeCooldown) { //Logger.MsgDebug("Begin Strafe", DebugTypeEnum.AutoPilot); this.LastStrafeStartTime = MyAPIGateway.Session.GameDateTime; this.ThisStrafeDuration = Rnd.Next(StrafeMinDurationMs, StrafeMaxDurationMs); this.Strafing = true; MyAPIGateway.Parallel.Start(() => { _autoPilot.Collision.RunSecondaryCollisionChecks(); this.CurrentAllowedStrafeDirections = Vector3I.Zero; this.CurrentStrafeDirections = new Vector3I(Rnd.Next(-1, 2), Rnd.Next(-1, 2), Rnd.Next(-1, 2)); if (this.CurrentStrafeDirections.X != 0) { this.CurrentAllowedStrafeDirections.X = 1; var rAngle = VectorHelper.GetAngleBetweenDirections(_collision.Matrix.Right, Vector3D.Normalize(_autoPilot.GetCurrentWaypoint() - _collision.Matrix.Translation)); var lAngle = VectorHelper.GetAngleBetweenDirections(_collision.Matrix.Left, Vector3D.Normalize(_autoPilot.GetCurrentWaypoint() - _collision.Matrix.Translation)); bool rTargetIntersect = (rAngle < this.StrafeMinimumSafeAngleFromTarget && _autoPilot.DistanceToCurrentWaypoint < this.StrafeMinimumTargetDistance); bool lTargetIntersect = (lAngle < this.StrafeMinimumSafeAngleFromTarget && _autoPilot.DistanceToCurrentWaypoint < this.StrafeMinimumTargetDistance); if (this.CurrentStrafeDirections.X == 1) { if (rTargetIntersect || (_collision.RightResult.HasTarget(StrafeMinimumTargetDistance) && !_collision.LeftResult.HasTarget(StrafeMinimumTargetDistance))) { Logger.MsgDebug("Strafe: X Reverse", DebugTypeEnum.AutoPilot); this.CurrentStrafeDirections.X *= -1; } else if (lTargetIntersect || (_collision.RightResult.HasTarget(StrafeMinimumTargetDistance) && _collision.LeftResult.HasTarget(StrafeMinimumTargetDistance))) { Logger.MsgDebug("Strafe: X Negate", DebugTypeEnum.AutoPilot); this.CurrentStrafeDirections.X = 0; } } else { if (lTargetIntersect || (_collision.LeftResult.HasTarget(StrafeMinimumTargetDistance) && !_collision.RightResult.HasTarget(StrafeMinimumTargetDistance))) { Logger.MsgDebug("Strafe: X Reverse", DebugTypeEnum.AutoPilot); this.CurrentStrafeDirections.X *= -1; } else if (rTargetIntersect || (_collision.LeftResult.HasTarget(StrafeMinimumTargetDistance) && _collision.RightResult.HasTarget(StrafeMinimumTargetDistance))) { Logger.MsgDebug("Strafe: X Negate", DebugTypeEnum.AutoPilot); this.CurrentStrafeDirections.X = 0; } } } if (this.CurrentStrafeDirections.Y != 0) { this.CurrentAllowedStrafeDirections.Y = 1; var uAngle = VectorHelper.GetAngleBetweenDirections(_collision.Matrix.Up, Vector3D.Normalize(_autoPilot.GetCurrentWaypoint() - _collision.Matrix.Translation)); var dAngle = VectorHelper.GetAngleBetweenDirections(_collision.Matrix.Down, Vector3D.Normalize(_autoPilot.GetCurrentWaypoint() - _collision.Matrix.Translation)); bool uTargetIntersect = (uAngle < this.StrafeMinimumSafeAngleFromTarget && _autoPilot.DistanceToCurrentWaypoint < this.StrafeMinimumTargetDistance); bool dTargetIntersect = (dAngle < this.StrafeMinimumSafeAngleFromTarget && _autoPilot.DistanceToCurrentWaypoint < this.StrafeMinimumTargetDistance); if (this.CurrentStrafeDirections.Y == 1) { if (uTargetIntersect || (_collision.UpResult.HasTarget(StrafeMinimumTargetDistance) && !_collision.DownResult.HasTarget(StrafeMinimumTargetDistance))) { Logger.MsgDebug("Strafe: Y Reverse", DebugTypeEnum.AutoPilot); this.CurrentStrafeDirections.Y *= -1; } else if (dTargetIntersect || (_collision.UpResult.HasTarget(StrafeMinimumTargetDistance) && _collision.DownResult.HasTarget(StrafeMinimumTargetDistance))) { Logger.MsgDebug("Strafe: Y Negate", DebugTypeEnum.AutoPilot); this.CurrentStrafeDirections.Y = 0; } } else { if (dTargetIntersect || (_collision.DownResult.HasTarget(StrafeMinimumTargetDistance) && !_collision.UpResult.HasTarget(StrafeMinimumTargetDistance))) { Logger.MsgDebug("Strafe: Y Reverse", DebugTypeEnum.AutoPilot); this.CurrentStrafeDirections.Y *= -1; } else if (uTargetIntersect || (_collision.DownResult.HasTarget(StrafeMinimumTargetDistance) && _collision.UpResult.HasTarget(StrafeMinimumTargetDistance))) { Logger.MsgDebug("Strafe: Y Negate", DebugTypeEnum.AutoPilot); this.CurrentStrafeDirections.Y = 0; } } } if (this.CurrentStrafeDirections.Z != 0) { this.CurrentAllowedStrafeDirections.Z = 1; var fAngle = VectorHelper.GetAngleBetweenDirections(_collision.Matrix.Forward, Vector3D.Normalize(_autoPilot.GetCurrentWaypoint() - _collision.Matrix.Translation)); var bAngle = VectorHelper.GetAngleBetweenDirections(_collision.Matrix.Backward, Vector3D.Normalize(_autoPilot.GetCurrentWaypoint() - _collision.Matrix.Translation)); bool fTargetIntersect = (fAngle < this.StrafeMinimumSafeAngleFromTarget && _autoPilot.DistanceToCurrentWaypoint < this.StrafeMinimumTargetDistance); bool bTargetIntersect = (bAngle < this.StrafeMinimumSafeAngleFromTarget && _autoPilot.DistanceToCurrentWaypoint < this.StrafeMinimumTargetDistance); if (this.CurrentStrafeDirections.Z == 1) { if (fTargetIntersect || (_collision.ForwardResult.HasTarget(StrafeMinimumTargetDistance) && !_collision.BackwardResult.HasTarget(StrafeMinimumTargetDistance))) { Logger.MsgDebug("Strafe: Z Reverse", DebugTypeEnum.AutoPilot); this.CurrentStrafeDirections.Z *= -1; } else if (bTargetIntersect || (_collision.ForwardResult.HasTarget(StrafeMinimumTargetDistance) && _collision.BackwardResult.HasTarget(StrafeMinimumTargetDistance))) { Logger.MsgDebug("Strafe: Z Negate", DebugTypeEnum.AutoPilot); this.CurrentStrafeDirections.Z = 0; } } else { if (bTargetIntersect || (_collision.BackwardResult.HasTarget(StrafeMinimumTargetDistance) && !_collision.ForwardResult.HasTarget(StrafeMinimumTargetDistance))) { Logger.MsgDebug("Strafe: Z Reverse", DebugTypeEnum.AutoPilot); this.CurrentStrafeDirections.Z *= -1; } else if (fTargetIntersect || (_collision.BackwardResult.HasTarget(StrafeMinimumTargetDistance) && _collision.ForwardResult.HasTarget(StrafeMinimumTargetDistance))) { Logger.MsgDebug("Strafe: Z Negate", DebugTypeEnum.AutoPilot); this.CurrentStrafeDirections.Z = 0; } } } if (_autoPilot.UpDirectionFromPlanet != Vector3D.Zero && _autoPilot.MyAltitude < _autoPilot.MinimumPlanetAltitude) { var thrustDir = VectorHelper.GetThrustDirectionsAwayFromDirection(_collision.Matrix, -_autoPilot.UpDirectionFromPlanet); if (thrustDir.X != 0) { this.CurrentAllowedStrafeDirections.X = 1; this.CurrentStrafeDirections.X = thrustDir.X; } if (thrustDir.Y != 0) { this.CurrentAllowedStrafeDirections.Y = 1; this.CurrentStrafeDirections.Y = thrustDir.Y; } if (thrustDir.Z != 0) { this.CurrentAllowedStrafeDirections.Z = 1; this.CurrentStrafeDirections.Z = thrustDir.Z; } } }, () => { SetThrust(this.CurrentAllowedStrafeDirections, this.CurrentStrafeDirections); }); } } else { TimeSpan duration = MyAPIGateway.Session.GameDateTime - this.LastStrafeStartTime; if (duration.TotalMilliseconds >= this.ThisStrafeDuration) { //Logger.MsgDebug("End Strafe", DebugTypeEnum.General); this.InvertStrafingActivated = false; this.LastStrafeEndTime = MyAPIGateway.Session.GameDateTime; this.ThisStrafeCooldown = Rnd.Next(StrafeMinCooldownMs, StrafeMaxCooldownMs); this.Strafing = false; _collisionStrafeAdjusted = false; _minAngleDistanceStrafeAdjusted = false; _collisionStrafeDirection = Vector3D.Zero; SetThrust(new Vector3I(0, 0, 0), new Vector3I(0, 0, 0)); //Logger.AddMsg("Cooldown: " + this.ThisStrafeCooldown.ToString(), true); } else { //Logger.MsgDebug("Strafe Collision: " + _collision.VelocityResult.CollisionImminent.ToString() + " - " + _collision.VelocityResult.Time.ToString(), DebugTypeEnum.Collision); if (!_collisionStrafeAdjusted && _collision.VelocityResult.CollisionImminent()) { Logger.MsgDebug("Strafe Velocity Collision Detect: " + _collision.VelocityResult.Type.ToString() + ", " + _collision.VelocityResult.GetCollisionDistance(), DebugTypeEnum.Collision); _collisionStrafeAdjusted = true; StopStrafeDirectionNearestPosition(_collision.VelocityResult.GetCollisionCoords()); _collisionStrafeDirection = Vector3D.Normalize(_collision.VelocityResult.GetCollisionCoords() - RemoteControl.WorldMatrix.Translation); } else if (_collisionStrafeAdjusted && VectorHelper.GetAngleBetweenDirections(_collisionStrafeDirection, Vector3D.Normalize(_collision.Velocity - RemoteControl.WorldMatrix.Translation)) > 15) { Logger.MsgDebug("Strafe Collision Detect", DebugTypeEnum.General); StopStrafeDirectionNearestPosition(_collision.VelocityResult.GetCollisionCoords()); _collisionStrafeDirection = Vector3D.Normalize(_collision.VelocityResult.GetCollisionCoords() - RemoteControl.WorldMatrix.Translation); } if (_minAngleDistanceStrafeAdjusted && _autoPilot.AngleToCurrentWaypoint < this.StrafeMinimumSafeAngleFromTarget && _autoPilot.DistanceToCurrentWaypoint < this.StrafeMinimumTargetDistance) { Logger.MsgDebug("Strafe Min Dist/Angle Detect", DebugTypeEnum.General); _minAngleDistanceStrafeAdjusted = false; StopStrafeDirectionNearestPosition(_collision.VelocityResult.GetCollisionCoords()); _collisionStrafeDirection = Vector3D.Normalize(_collision.VelocityResult.GetCollisionCoords() - RemoteControl.WorldMatrix.Translation); } } } }