public MyMaterialLayer() { StartHeight = 0; EndHeight = 0; MaterialName = null; MaterialDefinition = null; }
public MyMaterialLayer(float start, float end, string name) { StartHeight = start; EndHeight = end; MaterialName = name; MaterialDefinition = null; }
public void Start(Vector3D position, Vector3D initialVelocity, float scale, MyVoxelMaterialDefinition mat) { Components.MyRenderComponentDebrisVoxel voxelDebrisRender = Container.Entity.Render as Components.MyRenderComponentDebrisVoxel; voxelDebrisRender.TexCoordOffset = MyUtils.GetRandomFloat(5, 15); voxelDebrisRender.TexCoordScale = MyUtils.GetRandomFloat(8, 12); voxelDebrisRender.VoxelMaterialIndex = mat.Index; base.Start(position, initialVelocity, scale); Container.Entity.Render.NeedsResolveCastShadow = true; Container.Entity.Render.FastCastShadowResolve = true; }
public MyCompositeOrePlanetDeposit(MyCsgShapeBase baseShape, int seed, float minDepth, float maxDepth, MyOreProbability[] oreProbabilties, MyVoxelMaterialDefinition material) : base(baseShape, material) { m_minDepth = minDepth; double outherSphereVolume = (4.0 * MathHelper.Pi * Math.Pow(minDepth, 3.0f)) / 3.0; double innerSphereVolume = (4.0 * MathHelper.Pi * Math.Pow(maxDepth, 3.0f)) / 3.0; double depositVolume = (4.0 * MathHelper.Pi * Math.Pow(DEPOSIT_MAX_SIZE, 3.0f)) / 3.0; double volume = outherSphereVolume - innerSphereVolume; m_numDeposits = oreProbabilties.Length > 0 ? (int)Math.Floor((volume * 0.4f) / depositVolume) : 0; int numSectors = (int)(minDepth / DEPOSIT_MAX_SIZE); MyRandom random = MyRandom.Instance; FillMaterialCollections(); Vector3D offset = -new Vector3D(DEPOSIT_MAX_SIZE/2.0); using (var stateToken = random.PushSeed(seed)) { for (int i = 0; i < m_numDeposits; ++i) { Vector3D direction = MyProceduralWorldGenerator.GetRandomDirection(random); float distanceFromCenter = random.NextFloat(maxDepth,minDepth); Vector3D position = direction * distanceFromCenter; Vector3I cellPos = Vector3I.Ceiling((Shape.Center() + position)/ DEPOSIT_MAX_SIZE); MyCompositeShapeOreDeposit deposit; if (m_deposits.TryGetValue(cellPos, out deposit) == false) { var oreDefinition = GetOre(random.NextFloat(0, 1), oreProbabilties); var materialDefinition = m_materialsByOreType[oreDefinition.OreName][random.Next() % m_materialsByOreType[oreDefinition.OreName].Count]; deposit = new MyCompositeShapeOreDeposit(new MyCsgSimpleSphere(cellPos * DEPOSIT_MAX_SIZE + offset, random.NextFloat(64, DEPOSIT_MAX_SIZE / 2.0f)), materialDefinition); m_deposits[cellPos] = deposit; } } } m_materialsByOreType.Clear(); }
public MyCompositeShapeOreDeposit(MyCsgShapeBase shape, MyVoxelMaterialDefinition material) { System.Diagnostics.Debug.Assert(material != null, "Shape must have material"); Shape = shape; m_material = material; }
private void InitInternal() { // TODO: This will be fixed and made much more simple once ore models are done // https://app.asana.com/0/6594565324126/10473934569658 var physicalItem = MyDefinitionManager.Static.GetPhysicalItemDefinition(Item.Content); string model = physicalItem.Model; VoxelMaterial = null; float scale = 1.0f; if (Item.Content is MyObjectBuilder_Ore) { string oreSubTypeId = physicalItem.Id.SubtypeId.ToString(); foreach (var mat in MyDefinitionManager.Static.GetVoxelMaterialDefinitions()) { if (oreSubTypeId == mat.MinedOre) { VoxelMaterial = mat; model = MyDebris.GetRandomDebrisVoxel(); scale = (float)Math.Pow((float)Item.Amount * physicalItem.Volume / MyDebris.VoxelDebrisModelVolume, 0.333f); break; } } scale = (float)Math.Pow((float)Item.Amount * physicalItem.Volume / MyDebris.VoxelDebrisModelVolume, 0.333f); } if (scale < 0.05f) Close(); else if (scale < 0.15f) scale = 0.15f; FormatDisplayName(m_displayedText, Item); Init(m_displayedText, model, null, null, null); PositionComp.Scale = scale; // Must be set after init var massProperties = new HkMassProperties(); HkShape shape = GetPhysicsShape(physicalItem.Mass * (float)Item.Amount, scale, out massProperties); var scaleMatrix = Matrix.CreateScale(scale); if (Physics != null) Physics.Close(); Physics = new MyPhysicsBody(this, RigidBodyFlag.RBF_DEBRIS); if (VoxelMaterial != null) { HkConvexTransformShape transform = new HkConvexTransformShape((HkConvexShape)shape, ref scaleMatrix, HkReferencePolicy.None); Physics.CreateFromCollisionObject(transform, Vector3.Zero, MatrixD.Identity, massProperties, MyPhysics.FloatingObjectCollisionLayer); Physics.Enabled = true; transform.Base.RemoveReference(); } else { Physics.CreateFromCollisionObject(shape, Vector3.Zero, MatrixD.Identity, massProperties, MyPhysics.FloatingObjectCollisionLayer); Physics.Enabled = true; } Physics.MaterialType = VoxelMaterial != null ? MyMaterialType.ROCK : MyMaterialType.METAL; Physics.PlayCollisionCueEnabled = true; NeedsUpdate = MyEntityUpdateEnum.EACH_FRAME; }
public void CreateVoxelMeteorCrater(Vector3D center, float radius, Vector3 normal, MyVoxelMaterialDefinition material) { var msg = new MeteorCraterMsg(); msg.EntityId = Entity.EntityId; msg.Center = center; msg.Radius = radius; msg.Normal = normal; msg.Material = material.Index; MySession.Static.SyncLayer.SendMessageToAll(ref msg, MyTransportMessageEnum.Success); }
private bool HasMaterial(MyVoxelMaterialDefinition material) { if(material == Material0 || material == Material1 || material == Material2) { return true; } return false; }
protected abstract void OverwriteAllMaterialsInternal(MyVoxelMaterialDefinition material);
public void CreateVoxelMeteorCrater(Vector3D center, float radius, Vector3 normal, MyVoxelMaterialDefinition material) { BeforeContentChanged = true; MyMultiplayer.RaiseEvent(RootVoxel, x => x.CreateVoxelMeteorCrater_Implementation, center, radius, normal, material.Index); }
void IMyStorage.MergeVoxelMaterials(MyMwcVoxelFilesEnum voxelFile, Vector3I voxelPosition, MyVoxelMaterialDefinition materialToSet) { EnsureMutable(); m_trueStorage.MergeVoxelMaterials(voxelFile, voxelPosition, materialToSet); }
public static void MakeCrater(MyVoxelBase voxelMap, BoundingSphereD sphere, Vector3 direction, MyVoxelMaterialDefinition material) { ProfilerShort.Begin("MakeCrater"); Vector3 normal = Vector3.Normalize(sphere.Center - voxelMap.RootVoxel.WorldMatrix.Translation); Vector3I minCorner, maxCorner; { Vector3D sphereMin = sphere.Center - (sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES) * 1.3f; Vector3D sphereMax = sphere.Center + (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES) * 1.3f; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMin, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMax, out maxCorner); } voxelMap.Storage.ClampVoxelCoord(ref minCorner); voxelMap.Storage.ClampVoxelCoord(ref maxCorner); Vector3I worldMinCorner = minCorner + voxelMap.StorageMin; Vector3I worldMaxCorner = maxCorner + voxelMap.StorageMin; // We are tracking which voxels were changed, so we can invalidate only needed cells in the cache bool changed = false; ProfilerShort.Begin("Reading cache"); m_cache.Resize(minCorner, maxCorner); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref worldMinCorner, ref worldMaxCorner); ProfilerShort.End(); ProfilerShort.Begin("Changing cache"); int removedVoxelContent = 0; Vector3I tempVoxelCoord; Vector3I cachePos = (maxCorner - minCorner) / 2; byte oldMaterial = m_cache.Material(ref cachePos); float digRatio = 1 - Vector3.Dot(normal, direction); Vector3 newCenter = sphere.Center - normal * (float)sphere.Radius * 1.1f;//0.9f; float sphRadA = (float)(sphere.Radius * 1.5f); float sphRadSqA = (float)(sphRadA * sphRadA); float voxelSizeHalfTransformedPosA = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadA + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); float voxelSizeHalfTransformedNegA = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (-2 * sphRadA + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); Vector3 newDelCenter = newCenter + normal * (float)sphere.Radius * (0.7f + digRatio) + direction * (float)sphere.Radius * 0.65f; float sphRadD = (float)(sphere.Radius); float sphRadSqD = (float)(sphRadD * sphRadD); float voxelSizeHalfTransformedPosD = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadD + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); float voxelSizeHalfTransformedNegD = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (-2 * sphRadD + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); Vector3 newSetCenter = newCenter + normal * (float)sphere.Radius * (digRatio) + direction * (float)sphere.Radius * 0.3f; float sphRadS = (float)(sphere.Radius * 0.1f); float sphRadSqS = (float)(sphRadS * sphRadS); float voxelSizeHalfTransformedPosS = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadS + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); for (tempVoxelCoord.Z = minCorner.Z, cachePos.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, ++cachePos.Z) { for (tempVoxelCoord.Y = minCorner.Y, cachePos.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, ++cachePos.Y) { for (tempVoxelCoord.X = minCorner.X, cachePos.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, ++cachePos.X) { Vector3D voxelPosition; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref tempVoxelCoord, out voxelPosition); byte originalContent = m_cache.Content(ref cachePos); //Add sphere if (originalContent != MyVoxelConstants.VOXEL_CONTENT_FULL) { float addDist = (float)(voxelPosition - newCenter).LengthSquared(); float addDiff = (float)(addDist - sphRadSqA); byte newContent; if (addDiff > voxelSizeHalfTransformedPosA) { newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (addDiff < voxelSizeHalfTransformedNegA) { newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { float value = (float)Math.Sqrt(addDist + sphRadSqA - 2 * sphRadA * Math.Sqrt(addDist)); if (addDiff < 0) { value = -value; } // This formula will work even if diff is positive or negative newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - value / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } if (newContent > originalContent) { if (material != null) { m_cache.Material(ref cachePos, oldMaterial); } changed = true; m_cache.Content(ref cachePos, newContent); } } //Delete sphere float delDist = (float)(voxelPosition - newDelCenter).LengthSquared(); float delDiff = (float)(delDist - sphRadSqD); byte contentToRemove; if (delDiff > voxelSizeHalfTransformedPosD) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (delDiff < voxelSizeHalfTransformedNegD) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { float value = (float)Math.Sqrt(delDist + sphRadSqD - 2 * sphRadD * Math.Sqrt(delDist)); if (delDiff < 0) { value = -value; } // This formula will work even if diff is positive or negative contentToRemove = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - value / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } originalContent = m_cache.Content(ref cachePos); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY && contentToRemove > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { changed = true; int newVal = originalContent - contentToRemove; if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY) newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY; m_cache.Content(ref cachePos, (byte)newVal); removedVoxelContent += originalContent - newVal; } //Set material float setDist = (float)(voxelPosition - newSetCenter).LengthSquared(); float setDiff = (float)(setDist - sphRadSqS); if (setDiff <= MyVoxelConstants.VOXEL_SIZE_IN_METRES * 1.5f) // could be VOXEL_SIZE_IN_METRES_HALF, but we want to set material in empty cells correctly { MyVoxelMaterialDefinition originalMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref cachePos)); // Change the material: // - always on boundaries between material and nothing // - smoothly on inner boundaries MyVoxelMaterialDefinition newMaterial = material; if (setDiff > 0) { byte content = m_cache.Content(ref cachePos); if (content == MyVoxelConstants.VOXEL_CONTENT_FULL) newMaterial = originalMaterial; if (setDiff >= voxelSizeHalfTransformedPosS && content != MyVoxelConstants.VOXEL_CONTENT_EMPTY) // set material behind boundary only for empty voxels newMaterial = originalMaterial; } if (originalMaterial == newMaterial) { continue; } m_cache.Material(ref cachePos, newMaterial.Index); changed = true; } float dist = (float)(voxelPosition - newCenter).LengthSquared(); float diff = (float)(dist - sphRadSqA); if (diff <= 0f) { originalContent = m_cache.Content(ref cachePos); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { bool wrinkled = m_cache.WrinkleVoxelContent(ref cachePos, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_ADD, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_REMOVE); if (wrinkled) changed = true; } } } } } ProfilerShort.End(); if (changed) { ProfilerShort.Begin("RemoveSmallVoxelsUsingChachedVoxels"); RemoveSmallVoxelsUsingChachedVoxels(); ProfilerShort.BeginNextBlock("Writing cache"); minCorner += voxelMap.StorageMin; maxCorner += voxelMap.StorageMin; voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref minCorner, ref maxCorner); MyShapeSphere sphereShape = new MyShapeSphere(); sphereShape.Center = sphere.Center; sphereShape.Radius = (float)(sphere.Radius*1.5); OnVoxelChanged(OperationType.Cut, voxelMap, sphereShape); ProfilerShort.End(); } ProfilerShort.End(); }
public static void MakeCrater(MyVoxelBase voxelMap, BoundingSphereD sphere, Vector3 normal, MyVoxelMaterialDefinition material) { ProfilerShort.Begin("MakeCrater"); Vector3I minCorner, maxCorner; { Vector3D sphereMin = sphere.Center - (sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES); Vector3D sphereMax = sphere.Center + (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMin, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMax, out maxCorner); } voxelMap.Storage.ClampVoxelCoord(ref minCorner); voxelMap.Storage.ClampVoxelCoord(ref maxCorner); // We are tracking which voxels were changed, so we can invalidate only needed cells in the cache bool changed = false; ProfilerShort.Begin("Reading cache"); m_cache.Resize(minCorner, maxCorner); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref minCorner, ref maxCorner); ProfilerShort.End(); ProfilerShort.Begin("Changing cache"); int removedVoxelContent = 0; Vector3I tempVoxelCoord; Vector3I cachePos; for (tempVoxelCoord.Z = minCorner.Z, cachePos.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, ++cachePos.Z) { for (tempVoxelCoord.Y = minCorner.Y, cachePos.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, ++cachePos.Y) { for (tempVoxelCoord.X = minCorner.X, cachePos.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, ++cachePos.X) { Vector3D voxelPosition; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref tempVoxelCoord, out voxelPosition); float addDist = (float)(voxelPosition - sphere.Center).Length(); float addDiff = (float)(addDist - sphere.Radius); byte newContent; if (addDiff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (addDiff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - addDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } byte originalContent = m_cache.Content(ref cachePos); if (newContent > originalContent && originalContent > 0) { if (material != null) { m_cache.Material(ref cachePos, material.Index); } changed = true; m_cache.Content(ref cachePos, newContent); } float delDist = (float)(voxelPosition - (sphere.Center + (float)sphere.Radius * 0.7f * normal)).Length(); float delDiff = (float)(delDist - sphere.Radius); byte contentToRemove; if (delDiff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (delDiff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentToRemove = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - delDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } originalContent = m_cache.Content(ref cachePos); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY && contentToRemove > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { changed = true; int newVal = originalContent - contentToRemove; if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY) newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY; m_cache.Content(ref cachePos, (byte)newVal); removedVoxelContent += originalContent - newVal; } float setDist = (float)(voxelPosition - (sphere.Center - (float)sphere.Radius * 0.5f * normal)).Length(); float setDiff = (float)(setDist - sphere.Radius / 4f); if (setDiff <= MyVoxelConstants.VOXEL_SIZE_IN_METRES * 1.5f) // could be VOXEL_SIZE_IN_METRES_HALF, but we want to set material in empty cells correctly { byte indestructibleContentToSet = MyVoxelConstants.VOXEL_CONTENT_FULL; if (setDiff >= MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) // outside { indestructibleContentToSet = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (setDiff >= -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) // boundary { indestructibleContentToSet = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - setDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } MyVoxelMaterialDefinition originalMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref cachePos)); // Change the material: // - always on boundaries between material and nothing // - smoothly on inner boundaries MyVoxelMaterialDefinition newMaterial = material; if (setDiff > 0) { byte content = m_cache.Content(ref cachePos); if (content == MyVoxelConstants.VOXEL_CONTENT_FULL) newMaterial = originalMaterial; if (setDiff >= MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF && content != MyVoxelConstants.VOXEL_CONTENT_EMPTY) // set material behind boundary only for empty voxels newMaterial = originalMaterial; } if (originalMaterial == newMaterial) { continue; } m_cache.Material(ref cachePos, newMaterial.Index); changed = true; } float dist = (float)(voxelPosition - sphere.Center).Length(); float diff = (float)(dist - sphere.Radius); if (diff <= 0f) { originalContent = m_cache.Content(ref cachePos); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { bool wrinkled = m_cache.WrinkleVoxelContent(ref cachePos, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_ADD, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_REMOVE); if (wrinkled) changed = true; } } } } } ProfilerShort.End(); if (changed) { ProfilerShort.Begin("RemoveSmallVoxelsUsingChachedVoxels"); RemoveSmallVoxelsUsingChachedVoxels(); ProfilerShort.BeginNextBlock("Writing cache"); voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref minCorner, ref maxCorner); ProfilerShort.End(); } ProfilerShort.End(); }
protected override void OverwriteAllMaterialsInternal(MyVoxelMaterialDefinition material) { Debug.Fail("Not implemented."); }
/// <summary> /// Converts voxel material to ore material and puts it into the inventory. If there is no /// corresponding ore for given voxel type, nothing happens. /// </summary> private bool TryHarvestOreMaterial(MyVoxelMaterialDefinition material, Vector3 hitPosition, int removedAmount, bool onlyCheck) { if (string.IsNullOrEmpty(material.MinedOre)) return false; //Do one frame heatup only in singleplayer, lag will solve it in multiplayer if (InitialHeatup()) return true; if (!onlyCheck) { ProfilerShort.Begin("TryHarvestOreMaterial"); var oreObjBuilder = MyObjectBuilderSerializer.CreateNewObject<MyObjectBuilder_Ore>(material.MinedOre); float amountCubicMeters = (float)(((float)removedAmount / (float)MyVoxelConstants.VOXEL_CONTENT_FULL) * MyVoxelConstants.VOXEL_VOLUME_IN_METERS * VoxelHarvestRatio); amountCubicMeters *= (float)material.MinedOreRatio; if (!MySession.Static.AmountMined.ContainsKey(material.MinedOre)) MySession.Static.AmountMined[material.MinedOre] = 0; MySession.Static.AmountMined[material.MinedOre] += (MyFixedPoint)amountCubicMeters; float maxDropCubicMeters = 0.150f; var physItem = MyDefinitionManager.Static.GetPhysicalItemDefinition(oreObjBuilder); MyFixedPoint amountInItemCount = (MyFixedPoint)(amountCubicMeters / physItem.Volume); MyFixedPoint maxAmountPerDrop = (MyFixedPoint)(maxDropCubicMeters / physItem.Volume); if (OutputInventory != null) { MyFixedPoint amountDropped = amountInItemCount * (1 - m_inventoryCollectionRatio); amountDropped = MyFixedPoint.Min(maxAmountPerDrop * 10 - (MyFixedPoint)0.001, amountDropped); MyFixedPoint inventoryAmount = (amountInItemCount * m_inventoryCollectionRatio) - amountDropped; OutputInventory.AddItems(inventoryAmount, oreObjBuilder); SpawnOrePieces(amountDropped, maxAmountPerDrop, hitPosition, oreObjBuilder, material); } else { SpawnOrePieces(amountInItemCount, maxAmountPerDrop, hitPosition, oreObjBuilder, material); } ProfilerShort.End(); } return true; }
public void CreateExplosionDebris(ref BoundingSphereD explosionSphere, float voxelsCountInPercent, MyVoxelMaterialDefinition voxelMaterial, MyVoxelBase voxelMap) { MyDebug.AssertDebug((voxelsCountInPercent >= 0.0f) && (voxelsCountInPercent <= 1.0f)); MyDebug.AssertDebug(explosionSphere.Radius > 0); ProfilerShort.Begin("CreateExplosionDebris"); ProfilerShort.Begin("Matrices"); // This matrix will rotate all newly created debrises, so they won't apper as alligned with coordinate system MatrixD randomRotationMatrix = MatrixD.CreateRotationX(MyUtils.GetRandomRadian()) * MatrixD.CreateRotationY(MyUtils.GetRandomRadian()); float highScale = MathHelper.Clamp((float)explosionSphere.Radius * m_debrisScaleUpper, 0, m_debrisScaleClamp); float lowScale = highScale * (m_debrisScaleLower / m_debrisScaleUpper); int objectsToGenerate = (int)(m_voxelDebrisOffsets.Count * voxelsCountInPercent); ProfilerShort.End(); ProfilerShort.Begin("m_positionOffsets"); const float SPHERE_FIT_CUBE_SCALE = 1 / 1.73f; // Resize sphere to fit inside cube int debrisCount = m_voxelDebrisOffsets.Count; //float debrisScale = Math.Max(explosionSphere.Radius / debrisCount, 0.2f); float debrisScale = Math.Max((float)explosionSphere.Radius, 0.2f); for (int i = 0; i < debrisCount; i++) { MyDebrisVoxel newObj = CreateVoxelDebris(); if (newObj == null) { break; // no point in continuing } Vector3D position = m_voxelDebrisOffsets[i] * (float)explosionSphere.Radius * SPHERE_FIT_CUBE_SCALE; Vector3D.Transform(ref position, ref randomRotationMatrix, out position); position += explosionSphere.Center; var initialVelocity = MyUtils.GetRandomVector3Normalized(); if (initialVelocity == Vector3.Zero) continue; initialVelocity *= MyUtils.GetRandomFloat(MyDebrisConstants.EXPLOSION_DEBRIS_INITIAL_SPEED_MIN, MyDebrisConstants.EXPLOSION_DEBRIS_INITIAL_SPEED_MAX); (newObj.Debris as MyDebrisVoxel.MyDebrisVoxelLogic).Start(position, initialVelocity, debrisScale, voxelMaterial); } ProfilerShort.End(); ProfilerShort.End(); }
public void CreateDirectedDebris(Vector3 sourceWorldPosition, Vector3 offsetDirection, float minSourceDistance, float maxSourceDistance, float minDeviationAngle, float maxDeviationAngle, int debrisPieces, float initialSpeed, float scale, MyVoxelMaterialDefinition material) { ProfilerShort.Begin("Create directed debris"); MyDebug.AssertDebug(debrisPieces > 0); for (int i = 0; i < debrisPieces; ++i) { var newObj = CreateVoxelDebris(); if (newObj == null) { break; // no point in continuing } float dist = MyUtils.GetRandomFloat(minSourceDistance, maxSourceDistance); float angleX = MyUtils.GetRandomFloat(minDeviationAngle, maxDeviationAngle); float angleY = MyUtils.GetRandomFloat(minDeviationAngle, maxDeviationAngle); var rotation = Matrix.CreateRotationX(angleX) * Matrix.CreateRotationY(angleY); var deviatedDir = Vector3.Transform(offsetDirection, rotation); var startPos = sourceWorldPosition + deviatedDir * dist; var initialVelocity = deviatedDir * initialSpeed; (newObj.Debris as MyDebrisVoxel.MyDebrisVoxelLogic).Start(startPos, initialVelocity, scale, material); } ProfilerShort.End(); }
public MyBoxOreDeposit(MyCsgShapeBase baseShape, MyVoxelMaterialDefinition material) : base(baseShape, material) { m_boxShape = (MyCsgBox)baseShape; }
public bool MatchMaterials(MyVoxelMaterialDefinition material0, MyVoxelMaterialDefinition material1, MyVoxelMaterialDefinition material2) { return HasMaterial(material0) && HasMaterial(material1) && HasMaterial(material2); }
void IMyStorage.OverwriteAllMaterials(MyVoxelMaterialDefinition material) { EnsureMutable(); m_trueStorage.OverwriteAllMaterials(material); }
private void SpawnOrePieces(MyFixedPoint amountItems, MyFixedPoint maxAmountPerDrop, Vector3 hitPosition, MyObjectBuilder_PhysicalObject oreObjBuilder, MyVoxelMaterialDefinition voxelMaterial) { ProfilerShort.Begin("SpawnOrePieces"); var forward = Vector3.Normalize(m_sensor.FrontPoint - m_sensor.Center); //var pos = m_sensor.CutOutSphere.Center + forward * m_floatingObjectSpawnOffset; var pos = hitPosition - forward * m_floatingObjectSpawnRadius; BoundingSphere bsphere = new BoundingSphere(pos, m_floatingObjectSpawnRadius); while (amountItems > 0) { MyFixedPoint dropAmount = MyFixedPoint.Min(amountItems, maxAmountPerDrop); amountItems -= dropAmount; var inventoryItem = new MyPhysicalInventoryItem(dropAmount, oreObjBuilder); var item = MyFloatingObjects.Spawn(inventoryItem, bsphere, null, voxelMaterial); item.Physics.LinearVelocity = MyUtils.GetRandomVector3HemisphereNormalized(forward) * MyUtils.GetRandomFloat(5, 8); item.Physics.AngularVelocity = MyUtils.GetRandomVector3Normalized() * MyUtils.GetRandomFloat(4, 8); } ProfilerShort.End(); }
private void InitInternal() { // TODO: This will be fixed and made much more simple once ore models are done // https://app.asana.com/0/6594565324126/10473934569658 var itemDefinition = MyDefinitionManager.Static.GetPhysicalItemDefinition(Item.Content); m_health = itemDefinition.Health; // Setting voxel material (if applicable) VoxelMaterial = null; if (itemDefinition.VoxelMaterial != MyStringHash.NullOrEmpty) { VoxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(itemDefinition.VoxelMaterial.String); } else if (Item.Content is MyObjectBuilder_Ore) { string oreSubTypeId = itemDefinition.Id.SubtypeName; string materialName = (Item.Content as MyObjectBuilder_Ore).GetMaterialName(); bool hasMaterialName = (Item.Content as MyObjectBuilder_Ore).HasMaterialName(); foreach (var mat in MyDefinitionManager.Static.GetVoxelMaterialDefinitions()) { if ((hasMaterialName && materialName == mat.Id.SubtypeName) || (hasMaterialName == false && oreSubTypeId == mat.MinedOre)) { VoxelMaterial = mat; break; } } } // Setting the item's model string model = itemDefinition.Model; if (itemDefinition.HasModelVariants) { int modelNum = itemDefinition.Models.Length; Debug.Assert(m_modelVariant >= 0 && m_modelVariant < modelNum, "Model variant overflow. This can happen if model variants changed"); m_modelVariant = m_modelVariant % modelNum; model = itemDefinition.Models[m_modelVariant]; } else if (Item.Content is MyObjectBuilder_Ore && VoxelMaterial != null) { // Only ores without found voxel material use the defined model (otherwise, the scrap metal does not work) model = MyDebris.GetRandomDebrisVoxel(); } // Setting the scale float scale = this.Item.Scale; if (Item.Content is MyObjectBuilder_Ore) { scale *= (float)Math.Pow((float)Item.Amount * itemDefinition.Volume / MyDebris.VoxelDebrisModelVolume, 0.333f); } else { scale *= (float)Math.Pow(itemDefinition.Volume / itemDefinition.ModelVolume, 0.333f); } if (scale < 0.05f) Close(); else if (scale < 0.15f) scale = 0.15f; FormatDisplayName(m_displayedText, Item); Debug.Assert(model != null, "Floating object model is null"); Init(m_displayedText, model, null, null, null); PositionComp.Scale = scale; // Must be set after init var massProperties = new HkMassProperties(); var mass = MyPerGameSettings.Destruction ? MyDestructionHelper.MassToHavok(itemDefinition.Mass) : itemDefinition.Mass; mass = mass * (float)Item.Amount; HkShape shape = GetPhysicsShape(mass, scale, out massProperties); var scaleMatrix = Matrix.CreateScale(scale); if (Physics != null) Physics.Close(); Physics = new MyPhysicsBody(this, RigidBodyFlag.RBF_DEBRIS); int layer = mass > MyPerGameSettings.MinimumLargeShipCollidableMass ? MyPhysics.CollisionLayers.FloatingObjectCollisionLayer : MyPhysics.CollisionLayers.LightFloatingObjectCollisionLayer; if (VoxelMaterial != null || (shape.IsConvex && scale != 1f)) { HkConvexTransformShape transform = new HkConvexTransformShape((HkConvexShape)shape, ref scaleMatrix, HkReferencePolicy.None); Physics.CreateFromCollisionObject(transform, Vector3.Zero, MatrixD.Identity, massProperties, layer); Physics.Enabled = true; transform.Base.RemoveReference(); } else { Physics.CreateFromCollisionObject(shape, Vector3.Zero, MatrixD.Identity, massProperties, layer); Physics.Enabled = true; } Physics.MaterialType = this.EvaluatePhysicsMaterial(itemDefinition.PhysicalMaterial); Physics.PlayCollisionCueEnabled = true; Physics.RigidBody.ContactSoundCallbackEnabled = true; m_easeCollisionForce = new HkEasePenetrationAction(Physics.RigidBody, 2f); m_massChangeForCollisions = 0.010f; NeedsUpdate = MyEntityUpdateEnum.EACH_FRAME; }
public static void CutOutShapeWithProperties( MyVoxelBase voxelMap, MyShape shape, out float voxelsCountInPercent, out MyVoxelMaterialDefinition voxelMaterial, Dictionary<MyVoxelMaterialDefinition, int> exactCutOutMaterials = null, bool updateSync = false, bool onlyCheck = false, bool applyDamageMaterial = false, bool onlyApplyMaterial = false) { if (MySession.Static.EnableVoxelDestruction == false) { voxelsCountInPercent = 0; voxelMaterial = null; return; } ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()"); int originalSum = 0; int removedSum = 0; bool materials = exactCutOutMaterials != null; // Bring the shape into voxel space. var oldTranmsform = shape.Transformation; var newTransf = oldTranmsform * voxelMap.PositionComp.WorldMatrixInvScaled; newTransf.Translation += voxelMap.SizeInMetresHalf; shape.Transformation = newTransf; // This boundary should now be in our local space var bbox = shape.GetWorldBoundaries(); Vector3I minCorner, maxCorner; ComputeShapeBounds(voxelMap, ref bbox, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner); bool readMaterial = exactCutOutMaterials != null || applyDamageMaterial; var cacheMin = minCorner - 1; var cacheMax = maxCorner + 1; //try on making the read/write cell alligned see MyOctreeStorage.WriteRange - Micro octree leaf /*const int SHIFT = 4; const int REM = (1 << SHIFT) - 1; const int MASK = ~REM; cacheMin &= MASK; cacheMax = (cacheMax + REM) & MASK;*/ voxelMap.Storage.ClampVoxelCoord(ref cacheMin); voxelMap.Storage.ClampVoxelCoord(ref cacheMax); m_cache.Resize(cacheMin, cacheMax); m_cache.ClearMaterials(0); // Advise that the read content shall be cached MyVoxelRequestFlags flags = MyVoxelRequestFlags.AdviseCache; voxelMap.Storage.ReadRange(m_cache, readMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax, ref flags); Vector3I center; if (materials) { center = m_cache.Size3D / 2; voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref center)); } else { center = (cacheMin + cacheMax) / 2; voxelMaterial = voxelMap.Storage.GetMaterialAt(ref center); } MyVoxelMaterialDefinition voxelMat = null; ProfilerShort.Begin("Main loop"); Vector3I pos; for (pos.X = minCorner.X; pos.X <= maxCorner.X; ++pos.X) for (pos.Y = minCorner.Y; pos.Y <= maxCorner.Y; ++pos.Y) for (pos.Z = minCorner.Z; pos.Z <= maxCorner.Z; ++pos.Z) { // get original amount var relPos = pos - cacheMin; var lin = m_cache.ComputeLinear(ref relPos); var original = m_cache.Content(lin); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove continue; Vector3D spos = (Vector3D)(pos - voxelMap.StorageMin) * MyVoxelConstants.VOXEL_SIZE_IN_METRES; var volume = shape.GetVolume(ref spos); if (volume == 0f) // if there is no intersection continue; var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); var toRemove = maxRemove;// (int)(maxRemove * voxelMat.DamageRatio); var newVal = Math.Max(original - toRemove, 0);//MathHelper.Clamp(original - toRemove, 0, original-maxRemove); var removed = original - newVal; if (!onlyCheck && !onlyApplyMaterial) m_cache.Content(lin, (byte)newVal); originalSum += original; removedSum += removed; if (readMaterial) voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(lin)); if (exactCutOutMaterials != null) { int value = 0; exactCutOutMaterials.TryGetValue(voxelMat, out value); value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed); exactCutOutMaterials[voxelMat] = value; } if (applyDamageMaterial && voxelMat.HasDamageMaterial && !onlyCheck) m_cache.Material(lin, voxelMat.DamagedMaterialId); } if (removedSum > 0 && updateSync && Sync.IsServer) { shape.SendDrillCutOutRequest(voxelMap, applyDamageMaterial); } ProfilerShort.BeginNextBlock("Write"); if (removedSum > 0 && !onlyCheck) { // Clear all small voxel that may have been created during explosion. They can be created even outside the range of // explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the // explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we // will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove // B voxels too. //!! TODO AR & MK : check if this is needed !! //RemoveSmallVoxelsUsingChachedVoxels(); var dataTypeFlags = applyDamageMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content; if (MyFakes.LOG_NAVMESH_GENERATION) MyAIComponent.Static.Pathfinding.VoxelPathfinding.DebugLog.LogStorageWrite(voxelMap, m_cache, dataTypeFlags, cacheMin, cacheMax); voxelMap.Storage.WriteRange(m_cache, dataTypeFlags, ref cacheMin, ref cacheMax); } ProfilerShort.End(); voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f; shape.Transformation = oldTranmsform; if (removedSum > 0) OnVoxelChanged(OperationType.Cut, voxelMap, shape); ProfilerShort.End(); }
// Use when you want to change whole cell to one single material public void Reset(MyVoxelMaterialDefinition defaultMaterial) { IsSingleMaterial = true; m_singleMaterial = defaultMaterial.Index; m_averageCellMaterial = m_singleMaterial; m_averageNonRareCellMaterial = m_singleMaterial; // might be rare, but we have no way of knowing what non-rare material to use m_materials = null; }
public static void CutOutShapeWithProperties( MyVoxelBase voxelMap, MyShape shape, out float voxelsCountInPercent, out MyVoxelMaterialDefinition voxelMaterial, Dictionary<MyVoxelMaterialDefinition, int> exactCutOutMaterials = null, bool updateSync = false, bool onlyCheck = false) { ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()"); int originalSum = 0; int removedSum = 0; var bbox = shape.GetWorldBoundaries(); Vector3I minCorner, maxCorner; ComputeShapeBounds(ref bbox, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner); var cacheMin = minCorner - 1; var cacheMax = maxCorner + 1; voxelMap.Storage.ClampVoxelCoord(ref cacheMin); voxelMap.Storage.ClampVoxelCoord(ref cacheMax); m_cache.Resize(cacheMin, cacheMax); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cacheMin, ref cacheMax); { var shapeCenter = bbox.Center; Vector3I exactCenter; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeCenter, out exactCenter); exactCenter -= cacheMin; exactCenter = Vector3I.Clamp(exactCenter, Vector3I.Zero, m_cache.Size3D - 1); voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref exactCenter)); } for (var it = new Vector3I.RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext()) { var relPos = it.Current - cacheMin; // get original amount var original = m_cache.Content(ref relPos); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove continue; Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos); var volume = shape.GetVolume(ref vpos); if (volume == 0f) // if there is no intersection continue; var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos)); var toRemove = (int)(maxRemove * voxelMat.DamageRatio); var newVal = MathHelper.Clamp(original - toRemove, 0, maxRemove); var removed = Math.Abs(original - newVal); if (!onlyCheck) m_cache.Content(ref relPos, (byte)newVal); originalSum += original; removedSum += removed; if (exactCutOutMaterials != null) { int value = 0; exactCutOutMaterials.TryGetValue(voxelMat, out value); value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed); exactCutOutMaterials[voxelMat] = value; } } if (removedSum > 0 && !onlyCheck) { // Clear all small voxel that may have been created during explosion. They can be created even outside the range of // explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the // explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we // will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove // B voxels too. //!! TODO AR & MK : check if this is needed !! RemoveSmallVoxelsUsingChachedVoxels(); voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax); } if (removedSum > 0 && updateSync && Sync.IsServer) { shape.SendDrillCutOutRequest(voxelMap.SyncObject); } voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f; ProfilerShort.End(); }
// Change material for specified voxel // If this material is single material for whole cell, we do nothing. Otherwise we allocate 3D arrays and start using them. public void SetMaterial(MyVoxelMaterialDefinition material, ref Vector3I voxelCoordInCell) { SetMaterial(material.Index, ref voxelCoordInCell); }
void IMyStorage.SetSurfaceMaterial(MyVoxelMaterialDefinition material, int cellThickness) { EnsureMutable(); m_trueStorage.SetSurfaceMaterial(material, cellThickness); }
public MaterialCell(MyVoxelMaterialDefinition defaultMaterial) { // By default cell contains only one single material Reset(defaultMaterial); }
public MyCompositeShapeOreDeposit(MyCsgShapeBase shape, MyVoxelMaterialDefinition material) { Shape = shape; m_material = material; }
public void OverwriteAllMaterials(MyVoxelMaterialDefinition material) { MyPrecalcComponent.AssertUpdateThread(); using (m_storageLock.AcquireExclusiveUsing()) { m_compressedData = null; OverwriteAllMaterialsInternal(material); } OnRangeChanged(Vector3I.Zero, Size - 1, MyStorageDataTypeFlags.Material); }