public override MyShape Clone() { MyShapeSphere sphere1 = new MyShapeSphere(); sphere1.Transformation = base.Transformation; sphere1.Center = this.Center; sphere1.Radius = this.Radius; return(sphere1); }
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(); }
private MyBrushSphere() { m_shape = new MyShapeSphere(); m_shape.Radius = MinScale; m_transform = MatrixD.Identity; m_radius = new MyBrushGUIPropertyNumberSlider( m_shape.Radius, MinScale, MaxScale, MySessionComponentVoxelHand.VOXEL_HALF, MyVoxelBrushGUIPropertyOrder.First, MyCommonTexts.VoxelHandProperty_Sphere_Radius ); m_radius.ValueChanged += RadiusChanged; m_list = new List<MyGuiControlBase>(); m_radius.AddControlsToList(m_list); }
protected virtual bool TryDrillVoxels(MyVoxelBase voxels, Vector3D hitPosition, bool collectOre, bool onlyCheck) { const float DISCARDING_MULTIPLIER = 3.0f; bool somethingDrilled = false; var bsphere = new MyShapeSphere() { Center = m_cutOut.Sphere.Center, Radius = (float)m_cutOut.Sphere.Radius }; if (!collectOre) bsphere.Radius *= DISCARDING_MULTIPLIER; float voxelsCountInPercent; MyVoxelMaterialDefinition material; MyVoxelGenerator.CutOutShapeWithProperties(voxels, bsphere, out voxelsCountInPercent, out material, m_drilledMaterialBuffer, Sync.IsServer, onlyCheck); foreach (var entry in m_drilledMaterialBuffer) { somethingDrilled = (!collectOre || TryHarvestOreMaterial(entry.Key, hitPosition, entry.Value, onlyCheck)) || somethingDrilled; if (somethingDrilled && !onlyCheck) { MyDebris.Static.CreateDirectedDebris(hitPosition, MyUtils.GetRandomVector3Normalized(), 0.1f, 1, 0, MathHelper.Pi, 5, 1, 0.15f, entry.Key); } } m_drilledMaterialBuffer.Clear(); return somethingDrilled; }
public static void MakeCrater(MyVoxelBase voxelMap, BoundingSphereD sphere, Vector3 direction, MyVoxelMaterialDefinition material) { ProfilerShort.Begin("MakeCrater"); Vector3 normal = Vector3.Normalize(sphere.Center - voxelMap.RootVoxel.WorldMatrix.Translation); Vector3I minCorner, maxCorner; { Vector3D sphereMin = sphere.Center - (sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES) * 1.3f; Vector3D sphereMax = sphere.Center + (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES) * 1.3f; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMin, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMax, out maxCorner); } voxelMap.Storage.ClampVoxelCoord(ref minCorner); voxelMap.Storage.ClampVoxelCoord(ref maxCorner); Vector3I worldMinCorner = minCorner + voxelMap.StorageMin; Vector3I worldMaxCorner = maxCorner + voxelMap.StorageMin; // We are tracking which voxels were changed, so we can invalidate only needed cells in the cache bool changed = false; ProfilerShort.Begin("Reading cache"); m_cache.Resize(minCorner, maxCorner); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref worldMinCorner, ref worldMaxCorner); ProfilerShort.End(); ProfilerShort.Begin("Changing cache"); int removedVoxelContent = 0; Vector3I tempVoxelCoord; Vector3I cachePos = (maxCorner - minCorner) / 2; byte oldMaterial = m_cache.Material(ref cachePos); float digRatio = 1 - Vector3.Dot(normal, direction); Vector3 newCenter = sphere.Center - normal * (float)sphere.Radius * 1.1f;//0.9f; float sphRadA = (float)(sphere.Radius * 1.5f); float sphRadSqA = (float)(sphRadA * sphRadA); float voxelSizeHalfTransformedPosA = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadA + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); float voxelSizeHalfTransformedNegA = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (-2 * sphRadA + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); Vector3 newDelCenter = newCenter + normal * (float)sphere.Radius * (0.7f + digRatio) + direction * (float)sphere.Radius * 0.65f; float sphRadD = (float)(sphere.Radius); float sphRadSqD = (float)(sphRadD * sphRadD); float voxelSizeHalfTransformedPosD = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadD + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); float voxelSizeHalfTransformedNegD = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (-2 * sphRadD + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); Vector3 newSetCenter = newCenter + normal * (float)sphere.Radius * (digRatio) + direction * (float)sphere.Radius * 0.3f; float sphRadS = (float)(sphere.Radius * 0.1f); float sphRadSqS = (float)(sphRadS * sphRadS); float voxelSizeHalfTransformedPosS = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadS + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); for (tempVoxelCoord.Z = minCorner.Z, cachePos.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, ++cachePos.Z) { for (tempVoxelCoord.Y = minCorner.Y, cachePos.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, ++cachePos.Y) { for (tempVoxelCoord.X = minCorner.X, cachePos.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, ++cachePos.X) { Vector3D voxelPosition; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref tempVoxelCoord, out voxelPosition); byte originalContent = m_cache.Content(ref cachePos); //Add sphere if (originalContent != MyVoxelConstants.VOXEL_CONTENT_FULL) { float addDist = (float)(voxelPosition - newCenter).LengthSquared(); float addDiff = (float)(addDist - sphRadSqA); byte newContent; if (addDiff > voxelSizeHalfTransformedPosA) { newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (addDiff < voxelSizeHalfTransformedNegA) { newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { float value = (float)Math.Sqrt(addDist + sphRadSqA - 2 * sphRadA * Math.Sqrt(addDist)); if (addDiff < 0) { value = -value; } // This formula will work even if diff is positive or negative newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - value / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } if (newContent > originalContent) { if (material != null) { m_cache.Material(ref cachePos, oldMaterial); } changed = true; m_cache.Content(ref cachePos, newContent); } } //Delete sphere float delDist = (float)(voxelPosition - newDelCenter).LengthSquared(); float delDiff = (float)(delDist - sphRadSqD); byte contentToRemove; if (delDiff > voxelSizeHalfTransformedPosD) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (delDiff < voxelSizeHalfTransformedNegD) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { float value = (float)Math.Sqrt(delDist + sphRadSqD - 2 * sphRadD * Math.Sqrt(delDist)); if (delDiff < 0) { value = -value; } // This formula will work even if diff is positive or negative contentToRemove = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - value / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } originalContent = m_cache.Content(ref cachePos); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY && contentToRemove > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { changed = true; int newVal = originalContent - contentToRemove; if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY) { newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } m_cache.Content(ref cachePos, (byte)newVal); removedVoxelContent += originalContent - newVal; } //Set material float setDist = (float)(voxelPosition - newSetCenter).LengthSquared(); float setDiff = (float)(setDist - sphRadSqS); if (setDiff <= MyVoxelConstants.VOXEL_SIZE_IN_METRES * 1.5f) // could be VOXEL_SIZE_IN_METRES_HALF, but we want to set material in empty cells correctly { MyVoxelMaterialDefinition originalMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref cachePos)); // Change the material: // - always on boundaries between material and nothing // - smoothly on inner boundaries MyVoxelMaterialDefinition newMaterial = material; if (setDiff > 0) { byte content = m_cache.Content(ref cachePos); if (content == MyVoxelConstants.VOXEL_CONTENT_FULL) { newMaterial = originalMaterial; } if (setDiff >= voxelSizeHalfTransformedPosS && content != MyVoxelConstants.VOXEL_CONTENT_EMPTY) // set material behind boundary only for empty voxels { newMaterial = originalMaterial; } } if (originalMaterial == newMaterial) { continue; } m_cache.Material(ref cachePos, newMaterial.Index); changed = true; } float dist = (float)(voxelPosition - newCenter).LengthSquared(); float diff = (float)(dist - sphRadSqA); if (diff <= 0f) { originalContent = m_cache.Content(ref cachePos); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { bool wrinkled = m_cache.WrinkleVoxelContent(ref cachePos, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_ADD, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_REMOVE); if (wrinkled) { changed = true; } } } } } } ProfilerShort.End(); if (changed) { ProfilerShort.Begin("RemoveSmallVoxelsUsingChachedVoxels"); RemoveSmallVoxelsUsingChachedVoxels(); ProfilerShort.BeginNextBlock("Writing cache"); minCorner += voxelMap.StorageMin; maxCorner += voxelMap.StorageMin; voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref minCorner, ref maxCorner); MyShapeSphere sphereShape = new MyShapeSphere(); sphereShape.Center = sphere.Center; sphereShape.Radius = (float)(sphere.Radius * 1.5); OnVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, sphereShape); ProfilerShort.End(); } ProfilerShort.End(); }
private static void VoxelPlacement() { var camera = MySector.MainCamera; if (camera == null) return; var offset = 0; // MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF; var targetPosition = camera.Position + (Vector3D)camera.ForwardVector * 4.5f - offset; MyVoxelBase targetVoxelMap = null; foreach (var voxelMap in MySession.Static.VoxelMaps.Instances) { if (voxelMap.PositionComp.WorldAABB.Contains(targetPosition) == ContainmentType.Contains) { targetVoxelMap = voxelMap; break; } } if (targetVoxelMap == null) return; Vector3I targetVoxel; MyVoxelCoordSystems.WorldPositionToVoxelCoord(targetVoxelMap.PositionLeftBottomCorner, ref targetPosition, out targetVoxel); MyVoxelCoordSystems.VoxelCoordToWorldPosition(targetVoxelMap.PositionLeftBottomCorner, ref targetVoxel, out targetPosition); targetPosition += offset; var size = 3.0f; const int shapeType = 0; { BoundingBoxD aabb; MyVoxelCoordSystems.VoxelCoordToWorldAABB(targetVoxelMap.PositionLeftBottomCorner, ref targetVoxel, out aabb); VRageRender.MyRenderProxy.DebugDrawAABB(aabb, Color.Blue, 1f, 1f, true); } BoundingSphereD sphere; BoundingBoxD box; if (shapeType == 0) { sphere = new BoundingSphereD(targetPosition, size * 0.5f); VRageRender.MyRenderProxy.DebugDrawSphere(targetPosition, size * 0.5f, Color.White, 1f, true); } else if (shapeType == 1) { box = new BoundingBoxD( targetPosition - size * 0.5f, targetPosition + size * 0.5f); VRageRender.MyRenderProxy.DebugDrawAABB(box, Color.White, 1f, 1f, true); } else if (shapeType == 2) { MyVoxelCoordSystems.WorldPositionToVoxelCoord(targetVoxelMap.PositionLeftBottomCorner, ref targetPosition, out targetVoxel); //targetVoxel = Vector3I.Zero; MyVoxelCoordSystems.VoxelCoordToWorldAABB(targetVoxelMap.PositionLeftBottomCorner, ref targetVoxel, out box); VRageRender.MyRenderProxy.DebugDrawAABB(box, Vector3.One, 1f, 1f, true); } bool leftPressed = MyInput.Static.IsLeftMousePressed(); if (leftPressed) { MyShape shape; if (shapeType == 0) { shape = new MyShapeSphere() { Center = sphere.Center, Radius = (float)sphere.Radius, }; } else if (shapeType == 1 || shapeType == 2) { shape = new MyShapeBox() { Boundaries = box, }; } if (shape != null) { float dummy; MyVoxelMaterialDefinition dummy2; MyVoxelGenerator.CutOutShapeWithProperties(targetVoxelMap, shape, out dummy, out dummy2); } } }
public static void CutOutVoxelMap(float radius, Vector3D center, MyVoxelBase voxelMap, bool createDebris, bool damage = false) { MyVoxelMaterialDefinition voxelMaterial = null; float voxelContentRemovedInPercent = 0; //cut off var sphereShape = new MyShapeSphere() { Center = center, Radius = radius }; MyVoxelGenerator.CutOutShapeWithProperties(voxelMap, sphereShape, out voxelContentRemovedInPercent, out voxelMaterial, null, false, applyDamageMaterial: damage); // Only if at least something was removed from voxel map // If voxelContentRemovedInPercent is more than zero than also voxelMaterial shouldn't be null, but I rather check both of them. if ((voxelContentRemovedInPercent > 0) && (voxelMaterial != null)) { BoundingSphereD voxelExpSphere = new BoundingSphereD(center, radius); //remove decals VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("HideTrianglesAfterExplosion"); foreach (uint id in voxelMap.Render.RenderObjectIDs) VRageRender.MyRenderProxy.HideDecals(id, voxelExpSphere.Center, (float)voxelExpSphere.Radius); VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("CreateDebris"); if (createDebris && MyRenderConstants.RenderQualityProfile.ExplosionDebrisCountMultiplier > 0) { // Create debris rocks thrown from the explosion // This must be called before ApplyExplosionForceAndDamage (because there we apply impulses to the debris) MyDebris.Static.CreateExplosionDebris(ref voxelExpSphere, voxelContentRemovedInPercent, voxelMaterial, voxelMap); } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("CreateParticleEffect"); if (createDebris) { MyParticleEffect explosionEffect; if (MyParticlesManager.TryCreateParticleEffect((int)MyParticleEffectsIDEnum.MaterialExplosion_Destructible, out explosionEffect)) { explosionEffect.WorldMatrix = MatrixD.CreateTranslation(voxelExpSphere.Center); explosionEffect.UserRadiusMultiplier = (float)voxelExpSphere.Radius; } } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); } }
private static unsafe void MakeCraterInternal(MyVoxelBase voxelMap, ref BoundingSphereD sphere, ref Vector3 direction, MyVoxelMaterialDefinition material) { Vector3I vectori; Vector3I vectori2; Vector3I vectori5; Vector3 vector = Vector3.Normalize(sphere.Center - voxelMap.RootVoxel.WorldMatrix.Translation); Vector3D worldPosition = sphere.Center - ((sphere.Radius - 1.0) * 1.2999999523162842); Vector3D vectord2 = sphere.Center + ((sphere.Radius + 1.0) * 1.2999999523162842); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref worldPosition, out vectori); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref vectord2, out vectori2); voxelMap.Storage.ClampVoxelCoord(ref vectori, 1); voxelMap.Storage.ClampVoxelCoord(ref vectori2, 1); Vector3I lodVoxelRangeMin = (Vector3I)(vectori + voxelMap.StorageMin); Vector3I lodVoxelRangeMax = (Vector3I)(vectori2 + voxelMap.StorageMin); bool flag = false; if (m_cache == null) { m_cache = new MyStorageData(MyStorageDataTypeFlags.All); } m_cache.Resize(vectori, vectori2); MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent; voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, lodVoxelRangeMin, lodVoxelRangeMax, ref considerContent); int num = 0; Vector3I p = (Vector3I)((vectori2 - vectori) / 2); byte materialIdx = m_cache.Material(ref p); float num3 = 1f - Vector3.Dot(vector, direction); Vector3 vector2 = ((Vector3)sphere.Center) - ((vector * ((float)sphere.Radius)) * 1.1f); float num4 = (float)(sphere.Radius * 1.5); float num5 = num4 * num4; float num6 = 0.5f * ((2f * num4) + 0.5f); float num7 = 0.5f * ((-2f * num4) + 0.5f); Vector3 vector3 = (vector2 + ((vector * ((float)sphere.Radius)) * (0.7f + num3))) + ((direction * ((float)sphere.Radius)) * 0.65f); float radius = (float)sphere.Radius; float num9 = radius * radius; float num10 = 0.5f * ((2f * radius) + 0.5f); float num11 = 0.5f * ((-2f * radius) + 0.5f); Vector3 vector4 = (vector2 + ((vector * ((float)sphere.Radius)) * num3)) + ((direction * ((float)sphere.Radius)) * 0.3f); float num12 = (float)(sphere.Radius * 0.10000000149011612); float num13 = num12 * num12; float num14 = 0.5f * ((2f * num12) + 0.5f); vectori5.Z = vectori.Z; p.Z = 0; goto TR_003C; TR_0005: int *numPtr1 = (int *)ref vectori5.X; numPtr1[0]++; int *numPtr2 = (int *)ref p.X; numPtr2[0]++; TR_0036: while (true) { Vector3D vectord3; byte num18; if (vectori5.X > vectori2.X) { int *numPtr3 = (int *)ref vectori5.Y; numPtr3[0]++; int *numPtr4 = (int *)ref p.Y; numPtr4[0]++; break; } MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref vectori5, out vectord3); byte num15 = m_cache.Content(ref p); if (num15 != 0xff) { byte num22; float num20 = (float)(vectord3 - vector2).LengthSquared(); float num21 = num20 - num5; if (num21 > num6) { num22 = 0; } else if (num21 < num7) { num22 = 0xff; } else { float num23 = (float)Math.Sqrt((num20 + num5) - ((2f * num4) * Math.Sqrt((double)num20))); if (num21 < 0f) { num23 = -num23; } num22 = (byte)(127f - ((num23 / 0.5f) * 127f)); } if (num22 > num15) { if (material != null) { m_cache.Material(ref p, materialIdx); } flag = true; m_cache.Content(ref p, num22); } } float num16 = (float)(vectord3 - vector3).LengthSquared(); float num17 = num16 - num9; if (num17 > num10) { num18 = 0; } else if (num17 < num11) { num18 = 0xff; } else { float num24 = (float)Math.Sqrt((num16 + num9) - ((2f * radius) * Math.Sqrt((double)num16))); if (num17 < 0f) { num24 = -num24; } num18 = (byte)(127f - ((num24 / 0.5f) * 127f)); } num15 = m_cache.Content(ref p); if ((num15 > 0) && (num18 > 0)) { flag = true; int num25 = num15 - num18; if (num25 < 0) { num25 = 0; } m_cache.Content(ref p, (byte)num25); num += num15 - num25; } float num19 = ((float)(vectord3 - vector4).LengthSquared()) - num13; if (num19 <= 1.5f) { MyVoxelMaterialDefinition voxelMaterialDefinition = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref p)); MyVoxelMaterialDefinition objB = material; if (num19 > 0f) { byte num26 = m_cache.Content(ref p); if (num26 == 0xff) { objB = voxelMaterialDefinition; } if ((num19 >= num14) && (num26 != 0)) { objB = voxelMaterialDefinition; } } if (ReferenceEquals(voxelMaterialDefinition, objB)) { goto TR_0005; } else { m_cache.Material(ref p, objB.Index); flag = true; } } if ((((((float)(vectord3 - vector2).LengthSquared()) - num5) <= 0f) && (m_cache.Content(ref p) > 0)) && m_cache.WrinkleVoxelContent(ref p, 0.5f, 0.45f)) { flag = true; } goto TR_0005; } TR_0039: while (true) { if (vectori5.Y > vectori2.Y) { int *numPtr5 = (int *)ref vectori5.Z; numPtr5[0]++; int *numPtr6 = (int *)ref p.Z; numPtr6[0]++; break; } vectori5.X = vectori.X; p.X = 0; goto TR_0036; } TR_003C: while (true) { if (vectori5.Z <= vectori2.Z) { vectori5.Y = vectori.Y; p.Y = 0; break; } if (flag) { RemoveSmallVoxelsUsingChachedVoxels(); vectori = (Vector3I)(vectori + voxelMap.StorageMin); voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.All, vectori, (Vector3I)(vectori2 + voxelMap.StorageMin), true, false); MyShapeSphere sphere1 = new MyShapeSphere(); sphere1.Center = sphere.Center; sphere1.Radius = (float)(sphere.Radius * 1.5); BoundingBoxD worldBoundaries = sphere1.GetWorldBoundaries(); NotifyVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, ref worldBoundaries); } return; } goto TR_0039; }