void PerformAction(MyVoxelMap voxelMap, MyvoxelImportAction action, MyMwcVoxelMaterialsEnum? voxelMaterial, ref bool changed) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("PerformAction"); // Voxel map size must be multiple of grid size. Or, whole grid must fit exactly into X times into voxel map, without crossing border! MyCommonDebugUtils.AssertRelease((voxelMap.Size.X % VOXELS_IN_GRID_IN_ONE_DIRECTION) == 0); // Voxel map size must be multiple of grid size. Or, whole grid must fit exactly into X times into voxel map, without crossing border! MyCommonDebugUtils.AssertRelease((voxelMap.Size.Z % VOXELS_IN_GRID_IN_ONE_DIRECTION) == 0); int gridsCountX = voxelMap.Size.X / VOXELS_IN_GRID_IN_ONE_DIRECTION; int gridsCountZ = voxelMap.Size.Z / VOXELS_IN_GRID_IN_ONE_DIRECTION; // Space between two grid points in metres m_gridPointsSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES / (float)GRID_POINTS_IN_ONE_VOXEL_IN_ONE_DIRECTION; m_gridPointsSizeHalf = m_gridPointsSize / 2.0f; // Get min corner of the box MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(m_minCoord); // Get max corner of the box MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(m_maxCoord); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); // We are tracking which voxels were changed, so we can invalidate only needed cells in the cache MyMwcVector3Int minChanged = maxCorner; MyMwcVector3Int maxChanged = minCorner; bool contentChanged = false; for (int gridX = 0; gridX < gridsCountX; gridX++) { for (int gridZ = 0; gridZ < gridsCountZ; gridZ++) { if (PerformGridAction(voxelMap, action, gridX, gridZ, ref minChanged, ref maxChanged, voxelMaterial, ref changed)) { contentChanged = true; } } } if (contentChanged) { // Extend borders for cleaning, so it's one pixel on both sides minChanged.X -= 1; minChanged.Y -= 1; minChanged.Z -= 1; maxChanged.X += 1; maxChanged.Y += 1; maxChanged.Z += 1; voxelMap.FixVoxelCoord(ref minChanged); voxelMap.FixVoxelCoord(ref maxChanged); voxelMap.InvalidateCache(minChanged, maxChanged); } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); }
public static void ChangeMaterialInBoxRelative(MyVoxelMap voxelMap, Vector3 relativeMin, Vector3 relativeMax, MyMwcVoxelMaterialsEnum material) { BoundingBox boundingBox = voxelMap.WorldAABB; // Get min and max cell coordinate where camera bounding box can fit MyMwcVector3Int cellCoordMin = voxelMap.GetVoxelCoordinateFromMeters(boundingBox.Min); MyMwcVector3Int cellCoordMax = voxelMap.GetVoxelCoordinateFromMeters(boundingBox.Max); // Fix min and max cell coordinates so they don't overlap the voxelmap voxelMap.FixVoxelCoord(ref cellCoordMin); voxelMap.FixVoxelCoord(ref cellCoordMax); cellCoordMin.X = (int)(cellCoordMax.X * relativeMin.X); cellCoordMin.Y = (int)(cellCoordMax.Y * relativeMin.Y); cellCoordMin.Z = (int)(cellCoordMax.Z * relativeMin.Z); cellCoordMax.X = (int)(cellCoordMax.X * relativeMax.X); cellCoordMax.Y = (int)(cellCoordMax.Y * relativeMax.Y); cellCoordMax.Z = (int)(cellCoordMax.Z * relativeMax.Z); MyMwcVector3Int cellCoord; for (cellCoord.X = cellCoordMin.X; cellCoord.X <= cellCoordMax.X; cellCoord.X++) { for (cellCoord.Y = cellCoordMin.Y; cellCoord.Y <= cellCoordMax.Y; cellCoord.Y++) { for (cellCoord.Z = cellCoordMin.Z; cellCoord.Z <= cellCoordMax.Z; cellCoord.Z++) { voxelMap.SetVoxelMaterialAndIndestructibleContent(material, 0, ref cellCoord); } } } voxelMap.InvalidateCache(cellCoordMin, cellCoordMax); voxelMap.CalcAverageDataCellMaterials(); //MyVoxelMaps.RecalcVoxelMaps(); }
public static void FillEmpty(MyVoxelMap voxelMap) { float safeSize = 5; // Size in voxels to leave area empty on voxel map border var size = voxelMap.Size; for (int x = 0; x < size.X; x++) { for (int y = 0; y < size.Y; y++) { for (int z = 0; z < size.Z; z++) { MyMwcVector3Int coords = new MyMwcVector3Int(x, y, z); if (x <= safeSize || y <= safeSize || z <= safeSize || x >= size.X - safeSize - 1 || y >= size.Y - safeSize - 1 || z >= size.Z - safeSize - 1) { voxelMap.SetVoxelContent(0, ref coords); } else { voxelMap.SetVoxelContent(0, ref coords); } } } } voxelMap.InvalidateCache(new MyMwcVector3Int(0, 0, 0), size); }
// This is same as normal cut-out sphere, but cache is invalidated like in cut-out sphere fast(so that voxel cut-out will be immediately visible) public static void CutOutSphereInvalidateCache(MyVoxelMap voxelMap, BoundingSphere sphere, ref bool changed) { // Get min corner of the explosion MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(new Vector3( sphere.Center.X - sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES, sphere.Center.Y - sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES, sphere.Center.Z - sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES)); // Get max corner of the explosion MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(new Vector3( sphere.Center.X + sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES, sphere.Center.Y + sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES, sphere.Center.Z + sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES)); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); // We are tracking which voxels were changed, so we can invalidate only needed cells in the cache MyMwcVector3Int minChanged = maxCorner; MyMwcVector3Int maxChanged = minCorner; int removedVoxelContent = 0; MyMwcVector3Int tempVoxelCoord; for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) { for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) { for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { Vector3 voxelPosition = voxelMap.GetVoxelCenterPositionAbsolute(ref tempVoxelCoord); float dist = (voxelPosition - sphere.Center).Length(); float diff = dist - sphere.Radius; byte contentToRemove; if (diff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (diff < -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 - diff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } int originalContent = voxelMap.GetVoxelContent(ref tempVoxelCoord); 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; voxelMap.SetVoxelContent((byte)newVal, ref tempVoxelCoord); removedVoxelContent += originalContent - newVal; if (tempVoxelCoord.X < minChanged.X) minChanged.X = tempVoxelCoord.X; if (tempVoxelCoord.Y < minChanged.Y) minChanged.Y = tempVoxelCoord.Y; if (tempVoxelCoord.Z < minChanged.Z) minChanged.Z = tempVoxelCoord.Z; if (tempVoxelCoord.X > maxChanged.X) maxChanged.X = tempVoxelCoord.X; if (tempVoxelCoord.Y > maxChanged.Y) maxChanged.Y = tempVoxelCoord.Y; if (tempVoxelCoord.Z > maxChanged.Z) maxChanged.Z = tempVoxelCoord.Z; } } } } if (removedVoxelContent > 0) { // Extend borders for cleaning, so it's one pixel on both sides minChanged.X -= 1; minChanged.Y -= 1; minChanged.Z -= 1; maxChanged.X += 1; maxChanged.Y += 1; maxChanged.Z += 1; voxelMap.FixVoxelCoord(ref minChanged); voxelMap.FixVoxelCoord(ref maxChanged); voxelMap.InvalidateCache(minChanged, maxChanged); } }
// Cut outs a sphere from voxel map (e.g. explosion in a voxel map). We modify only voxels inside the sphere - set them to full or partialy full. // Other voxel are untouched. Sphere coordinates are in world space, not relative to voxel map and is in metres. // // Method returns percent of how much voxels were removed by this explosion (value 0.0 means no voxels; value 1.0 means all voxels) // // IMPORTANT: // This is optimized version that uses cache for accessing voxels. But the cache has limits so it can be used only for not extremely large cut-outs. // Non-optimized version is: CutOutSphere - but it doesn't mean it's slow... the difference is probably just 10-20% // // Returns true if indestructible voxels has been hit (otherwise false) public static bool CutOutSphereFast(MyVoxelMap voxelMap, BoundingSphere explosion, out float voxelsCountInPercent, out MyMwcVoxelMaterialsEnum? voxelMaterial, bool isPlayerExplosion = false, float removeRatio = 1, Dictionary<MyMwcVoxelMaterialsEnum, int> exactCutOutMaterials = null) { explosion.Radius = System.Math.Min(explosion.Radius, MyExplosionsConstants.EXPLOSION_RADIUS_MAX); InvalidateCache = true; voxelMaterial = null; MyMwcVoxelMaterialsEnum newVoxelMaterialTemp; byte tempminContentValueByte; MyMwcVector3Int exactCenterOfExplosion = voxelMap.GetVoxelCoordinateFromMeters(new Vector3(explosion.Center.X, explosion.Center.Y, explosion.Center.Z)); voxelMap.FixVoxelCoord(ref exactCenterOfExplosion); voxelMap.GetMaterialAndIndestructibleContent(ref exactCenterOfExplosion, out newVoxelMaterialTemp, out tempminContentValueByte); if (voxelMaterial == null) voxelMaterial = newVoxelMaterialTemp; // We need to replace this only once int originalVoxelContentsSum = 0; // Sum of all voxel contents affected by this explosion before we extract any voxel. This value is increasing per every voxel, no matter if we realy extract it. int removedVoxelContentsSum = 0; // Sum of all voxel contents we removed by this explosion. This value increases only if we extract something from voxel map. // Get min corner of the explosion MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(new Vector3( explosion.Center.X - explosion.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES, explosion.Center.Y - explosion.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES, explosion.Center.Z - explosion.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES)); // Get max corner of the explosion MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(new Vector3( explosion.Center.X + explosion.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES, explosion.Center.Y + explosion.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES, explosion.Center.Z + explosion.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES)); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); MyMwcVector3Int cachedSubtract; cachedSubtract.X = minCorner.X - CACHED_BOUNDARY_IN_VOXELS; cachedSubtract.Y = minCorner.Y - CACHED_BOUNDARY_IN_VOXELS; cachedSubtract.Z = minCorner.Z - CACHED_BOUNDARY_IN_VOXELS; // We are tracking which voxels were changed, so we can invalidate only needed cells in the cache MyMwcVector3Int minChanged = maxCorner; MyMwcVector3Int maxChanged = minCorner; MyMwcVector3Int tempVoxelCoord; bool indestructible = true; for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) { for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) { for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { Vector3 voxelPosition = voxelMap.GetVoxelCenterPositionAbsolute(ref tempVoxelCoord); float dist = (voxelPosition - explosion.Center).Length(); float diff = dist - explosion.Radius; // This number will tell us how much of this voxel we will remove (can be zero, can be full voxel, or between) int contentToRemove; if (diff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (diff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentToRemove = (int)(MyVoxelConstants.VOXEL_ISO_LEVEL - diff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } contentToRemove = (int)(contentToRemove * removeRatio); // Only if we have to remove something (e.g. voxels that are outside of the radius aren't affected, or voxels that are // in cornes are always out of the radius, even if they are in bounding box) if (contentToRemove > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { byte minContentValueByte; MyMwcVoxelMaterialsEnum voxelMaterialTemp; voxelMap.GetMaterialAndIndestructibleContent(ref tempVoxelCoord, out voxelMaterialTemp, out minContentValueByte); int minContentValue = minContentValueByte; if (minContentValue != MyVoxelConstants.VOXEL_CONTENT_FULL) { indestructible = false; } // Alter only non-empty voxels (because we can't remove empty voxel...) int originalContent = GetCachedVoxelContent(voxelMap, ref tempVoxelCoord, ref cachedSubtract); if (originalContent > minContentValue) { // IMPORTANT: When doing transformations on 'content' value, cast it to int always!!! // It's because you can easily forget that result will be negative and if you put negative into byte, it will // be overflown and you will be surprised by results!! int newVal = originalContent - contentToRemove; if (newVal < minContentValue) newVal = minContentValue; voxelMap.SetVoxelContent((byte)newVal, ref tempVoxelCoord); SetCachedVoxelContent(voxelMap, ref tempVoxelCoord, ref cachedSubtract, (byte)newVal); // Sum of all voxel contents affected by this explosion before we extract any voxel. This value is increasing per every voxel, no matter if we realy extract it. originalVoxelContentsSum += originalContent; // Sum of all voxel contents we removed by this explosion. This value increases only if we extract something from voxel map. removedVoxelContentsSum += originalContent - newVal; if (exactCutOutMaterials != null) { int oldValue = 0; exactCutOutMaterials.TryGetValue(voxelMaterialTemp, out oldValue); exactCutOutMaterials[voxelMaterialTemp] = oldValue + removedVoxelContentsSum; } if (tempVoxelCoord.X < minChanged.X) minChanged.X = tempVoxelCoord.X; if (tempVoxelCoord.Y < minChanged.Y) minChanged.Y = tempVoxelCoord.Y; if (tempVoxelCoord.Z < minChanged.Z) minChanged.Z = tempVoxelCoord.Z; if (tempVoxelCoord.X > maxChanged.X) maxChanged.X = tempVoxelCoord.X; if (tempVoxelCoord.Y > maxChanged.Y) maxChanged.Y = tempVoxelCoord.Y; if (tempVoxelCoord.Z > maxChanged.Z) maxChanged.Z = tempVoxelCoord.Z; } } } } } InvalidateCache = false; if (removedVoxelContentsSum > 0) { // Extend borders for cleaning, so it's one pixel on both sides minChanged.X -= 1; minChanged.Y -= 1; minChanged.Z -= 1; maxChanged.X += 1; maxChanged.Y += 1; maxChanged.Z += 1; voxelMap.FixVoxelCoord(ref minChanged); voxelMap.FixVoxelCoord(ref maxChanged); // 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. RemoveSmallVoxelsUsingChachedVoxels(voxelMap, ref minCorner, ref maxCorner, ref cachedSubtract); // Extend borders for invalidating the cache, so it's one pixel on both sides minChanged.X -= 1; minChanged.Y -= 1; minChanged.Z -= 1; maxChanged.X += 1; maxChanged.Y += 1; maxChanged.Z += 1; voxelMap.FixVoxelCoord(ref minChanged); voxelMap.FixVoxelCoord(ref maxChanged); // Invalidate cache for voxels cells covered by explosion and some boundary voxels too voxelMap.InvalidateCache(minCorner, maxCorner); voxelMap.AddExplosion(explosion); } if (originalVoxelContentsSum > 0f) { voxelsCountInPercent = (float)removedVoxelContentsSum / (float)originalVoxelContentsSum; } else { voxelsCountInPercent = 0f; } return indestructible; }
// This is same as normal cut-out box, but cache is invalidated (so that voxel changes be immediately visible) public static void CutOutBoxInvalidateCache(MyVoxelMap voxelMap, BoundingBox box, ref bool changed) { // Get min corner of the box MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(box.Min); // Get max corner of the box MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(box.Max); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); // We are tracking which voxels were changed, so we can invalidate only needed cells in the cache MyMwcVector3Int minChanged = maxCorner; MyMwcVector3Int maxChanged = minCorner; int removedVoxelContent = 0; MyMwcVector3Int tempVoxelCoord; for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) { for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) { for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { Vector3 voxelPosition = voxelMap.GetVoxelCenterPositionAbsolute(ref tempVoxelCoord); byte contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL; int originalContent = voxelMap.GetVoxelContent(ref tempVoxelCoord); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { changed = true; int newVal = originalContent - contentToRemove; if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY) newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY; voxelMap.SetVoxelContent((byte)newVal, ref tempVoxelCoord); removedVoxelContent += originalContent - newVal; if (tempVoxelCoord.X < minChanged.X) minChanged.X = tempVoxelCoord.X; if (tempVoxelCoord.Y < minChanged.Y) minChanged.Y = tempVoxelCoord.Y; if (tempVoxelCoord.Z < minChanged.Z) minChanged.Z = tempVoxelCoord.Z; if (tempVoxelCoord.X > maxChanged.X) maxChanged.X = tempVoxelCoord.X; if (tempVoxelCoord.Y > maxChanged.Y) maxChanged.Y = tempVoxelCoord.Y; if (tempVoxelCoord.Z > maxChanged.Z) maxChanged.Z = tempVoxelCoord.Z; } } } } if (removedVoxelContent > 0) { // Extend borders for cleaning, so it's one pixel on both sides minChanged.X -= 1; minChanged.Y -= 1; minChanged.Z -= 1; maxChanged.X += 1; maxChanged.Y += 1; maxChanged.Z += 1; voxelMap.FixVoxelCoord(ref minChanged); voxelMap.FixVoxelCoord(ref maxChanged); voxelMap.InvalidateCache(minChanged, maxChanged); } }
// This is same as normal CreateSphere method, but cache is invalidated (so that voxel changes be immediately visible) public static void CreateSphereInvalidateCache(MyVoxelMap voxelMap, BoundingSphere sphere, ref bool changed, MyMwcVoxelMaterialsEnum? material) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("MyVoxelGenerator.CreateSphereInvalidateCache"); // Get min corner of the explosion MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(new Vector3( sphere.Center.X - sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES, sphere.Center.Y - sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES, sphere.Center.Z - sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES)); // Get max corner of the explosion MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(new Vector3( sphere.Center.X + sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES, sphere.Center.Y + sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES, sphere.Center.Z + sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES)); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); // We are tracking which voxels were changed, so we can invalidate only needed cells in the cache MyMwcVector3Int minChanged = maxCorner; MyMwcVector3Int maxChanged = minCorner; bool sphereAdded = false; MyMwcVector3Int tempVoxelCoord; for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) { for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) { for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { Vector3 voxelPosition = voxelMap.GetVoxelCenterPositionAbsolute(ref tempVoxelCoord); float dist = (voxelPosition - sphere.Center).Length(); float diff = dist - sphere.Radius; byte newContent; if (diff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (diff < -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 - diff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } byte originalContent = voxelMap.GetVoxelContent(ref tempVoxelCoord); if (newContent > originalContent) { if (material.HasValue) { MyMwcVoxelMaterialsEnum originalMaterial; byte originalIndestructibleContent; voxelMap.GetMaterialAndIndestructibleContent(ref tempVoxelCoord, out originalMaterial, out originalIndestructibleContent); voxelMap.SetVoxelMaterialAndIndestructibleContent(material.Value, originalIndestructibleContent, ref tempVoxelCoord); } changed = true; voxelMap.SetVoxelContent(newContent, ref tempVoxelCoord); sphereAdded = true; if (tempVoxelCoord.X < minChanged.X) minChanged.X = tempVoxelCoord.X; if (tempVoxelCoord.Y < minChanged.Y) minChanged.Y = tempVoxelCoord.Y; if (tempVoxelCoord.Z < minChanged.Z) minChanged.Z = tempVoxelCoord.Z; if (tempVoxelCoord.X > maxChanged.X) maxChanged.X = tempVoxelCoord.X; if (tempVoxelCoord.Y > maxChanged.Y) maxChanged.Y = tempVoxelCoord.Y; if (tempVoxelCoord.Z > maxChanged.Z) maxChanged.Z = tempVoxelCoord.Z; } } } } if (sphereAdded == true) { // Extend borders for cleaning, so it's one pixel on both sides minChanged.X -= 1; minChanged.Y -= 1; minChanged.Z -= 1; maxChanged.X += 1; maxChanged.Y += 1; maxChanged.Z += 1; voxelMap.FixVoxelCoord(ref minChanged); voxelMap.FixVoxelCoord(ref maxChanged); voxelMap.InvalidateCache(minChanged, maxChanged); } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); }
// This is same as normal CreateBox method, but cache is invalidated (so that voxel changes be immediately visible) public static void CreateBoxInvalidateCache(MyVoxelMap voxelMap, BoundingBox box, ref bool changed) { // Get min corner of the box MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(box.Min); // Get max corner of the box MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(box.Max); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); // We are tracking which voxels were changed, so we can invalidate only needed cells in the cache MyMwcVector3Int minChanged = maxCorner; MyMwcVector3Int maxChanged = minCorner; bool sphereAdded = false; MyMwcVector3Int tempVoxelCoord; for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) { for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) { for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { byte newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; byte originalContent = voxelMap.GetVoxelContent(ref tempVoxelCoord); if (newContent > originalContent) { changed = true; voxelMap.SetVoxelContent(newContent, ref tempVoxelCoord); sphereAdded = true; if (tempVoxelCoord.X < minChanged.X) minChanged.X = tempVoxelCoord.X; if (tempVoxelCoord.Y < minChanged.Y) minChanged.Y = tempVoxelCoord.Y; if (tempVoxelCoord.Z < minChanged.Z) minChanged.Z = tempVoxelCoord.Z; if (tempVoxelCoord.X > maxChanged.X) maxChanged.X = tempVoxelCoord.X; if (tempVoxelCoord.Y > maxChanged.Y) maxChanged.Y = tempVoxelCoord.Y; if (tempVoxelCoord.Z > maxChanged.Z) maxChanged.Z = tempVoxelCoord.Z; } } } } if (sphereAdded == true) { // Extend borders for cleaning, so it's one pixel on both sides minChanged.X -= 1; minChanged.Y -= 1; minChanged.Z -= 1; maxChanged.X += 1; maxChanged.Y += 1; maxChanged.Z += 1; voxelMap.FixVoxelCoord(ref minChanged); voxelMap.FixVoxelCoord(ref maxChanged); voxelMap.InvalidateCache(minChanged, maxChanged); } }
} //Create Cuboid public static void CutOutCuboid(MyVoxelMap voxelMap, MyCuboid cuboid, MyMwcVoxelMaterialsEnum? material) { BoundingBox aabb = cuboid.GetAABB(); MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(aabb.Min - new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES)); MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(aabb.Max + new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES)); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); MyMwcVector3Int tempVoxelCoord; for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) { for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) { for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { Vector3 position = voxelMap.GetVoxelCenterPositionAbsolute(ref tempVoxelCoord); BoundingBox voxelAABB = new BoundingBox(position - new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF), position + new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)); bool isInside = true; for (int i = 0; i < cuboid.Sides.Length; i++) { MyPlane side = cuboid.Sides[i].Plane; float distance = MyUtils.GetDistanceFromPointToPlane(ref position, ref side); if (distance > 0) { isInside = false; break; } } float minDistance = float.MaxValue; for (int i = 0; i < cuboid.Sides.Length; i++) { MyQuad quad = new MyQuad(); quad.Point0 = cuboid.Sides[i].Lines[0].From; quad.Point1 = cuboid.Sides[i].Lines[1].From; quad.Point2 = cuboid.Sides[i].Lines[3].From; quad.Point3 = cuboid.Sides[i].Lines[2].From; float distance = MyUtils.GetDistancePointToQuad(ref position, ref quad); if (distance < minDistance) { minDistance = distance; } } byte newContent = 0; if (isInside) { if (minDistance > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else { // This formula will work even if diff is positive or negative //newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - minDistance / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); //newContent = (byte)(MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - minDistance / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL)); } } else { if (minDistance > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { //newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; // This formula will work even if diff is positive or negative //newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - minDistance / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); newContent = (byte)(MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - minDistance / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL)); } } byte originalContent = voxelMap.GetVoxelContent(ref tempVoxelCoord); if (newContent < originalContent) { voxelMap.SetVoxelContent(newContent, ref tempVoxelCoord); if (material.HasValue) voxelMap.SetVoxelMaterialAndIndestructibleContent(material.Value, 0, ref tempVoxelCoord); } } } } voxelMap.InvalidateCache(minCorner, maxCorner); voxelMap.CalcAverageDataCellMaterials(); } //CutOut Cuboid
} //CreateCylinder public static void CutOutCylinder(MyVoxelMap voxelMap, float radius1, float radius2, MyOrientedBoundingBox box, MyMwcVoxelMaterialsEnum? material, ref bool changed) { //box.HalfExtent x = radius1 //box.HalfExtent y = length/2 //box.HalfExtent z = radius2 BoundingBox aabb = box.GetAABB(); MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(aabb.Min - new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES)); MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(aabb.Max + new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES)); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); MyMwcVector3Int tempVoxelCoord; for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) { for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) { for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { Vector3 position = voxelMap.GetVoxelCenterPositionAbsolute(ref tempVoxelCoord); //BoundingBox voxelAABB = new BoundingBox(position - new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF), position + new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)); byte newContent = 0; // Transform the point into box-local space and check against // our extents. Quaternion qinv = Quaternion.Conjugate(box.Orientation); Vector3 plocal = Vector3.Transform(position - box.Center, qinv); //MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF float distY = 0; int sY = System.Math.Sign(plocal.Y); if (sY > 0) { distY = plocal.Y - box.HalfExtent.Y; } else { distY = plocal.Y + box.HalfExtent.Y; } float distRatio = 1; distRatio = MathHelper.Clamp((plocal.Y + box.HalfExtent.Y) / (2 * box.HalfExtent.Y), 0, 1); int contentY = -1; if (sY > 0) { if (distY > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_FULL; } else if (distY < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else { // This formula will work even if diff is positive or negative //contentY = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distY / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); contentY = MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distY / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } else { if (distY < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_FULL; } else if (distY > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else { // This formula will work even if diff is positive or negative //contentY = MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distY / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); contentY = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distY / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } Matrix boxMatrix = Matrix.CreateFromQuaternion(box.Orientation); Vector3 hY1 = box.Center + boxMatrix.Up * box.HalfExtent.Y; Vector3 hY2 = box.Center + boxMatrix.Down * box.HalfExtent.Y; float dist = MyUtils.GetPointLineDistance(ref hY1, ref hY2, ref position); float diff = dist - MathHelper.Lerp(radius2, radius1, distRatio); //float diff = dist - box.HalfExtent.Z; byte newContent2; if (diff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent2 = MyVoxelConstants.VOXEL_CONTENT_FULL; } else if (diff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent2 = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else { // This formula will work even if diff is positive or negative //newContent2 = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - diff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); newContent2 = (byte)(MyVoxelConstants.VOXEL_CONTENT_FULL - (int)(MyVoxelConstants.VOXEL_ISO_LEVEL - diff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL)); } newContent = (byte)System.Math.Max(contentY, newContent2); //newContent = (byte)contentY; byte originalContent = voxelMap.GetVoxelContent(ref tempVoxelCoord); if (newContent < originalContent) { voxelMap.SetVoxelContent(newContent, ref tempVoxelCoord); if (material.HasValue) voxelMap.SetVoxelMaterialAndIndestructibleContent(material.Value, 0, ref tempVoxelCoord); } } } } voxelMap.InvalidateCache(minCorner, maxCorner); voxelMap.CalcAverageDataCellMaterials(); } //CutoutCylinder
public static void CutOutOrientedBox(MyVoxelMap voxelMap, MyOrientedBoundingBox box, ref bool changed) { BoundingBox aabb = box.GetAABB(); MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(aabb.Min - new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES)); MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(aabb.Max + new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES)); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); System.Threading.Tasks.Parallel.For(minCorner.X, maxCorner.X, i => { System.Threading.Tasks.Parallel.For(minCorner.Y, maxCorner.Y, j => { System.Threading.Tasks.Parallel.For(minCorner.Z, maxCorner.Z, k => { MyMwcVector3Int tempVoxelCoord = new MyMwcVector3Int(i, j, k); Vector3 position = voxelMap.GetVoxelCenterPositionAbsolute(ref tempVoxelCoord); BoundingBox voxelAABB = new BoundingBox(position - new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF), position + new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)); byte newContent = 0; ContainmentType ct = box.Contains(ref voxelAABB); if (ct == ContainmentType.Contains) { newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (ct == ContainmentType.Disjoint) { newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // Transform the point into box-local space and check against // our extents. Quaternion qinv = Quaternion.Conjugate(box.Orientation); Vector3 plocal = Vector3.Transform(position - box.Center, qinv); //MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF float distX = 0; float distY = 0; float distZ = 0; int sX = System.Math.Sign(plocal.X); int sY = System.Math.Sign(plocal.Y); int sZ = System.Math.Sign(plocal.Z); if (sX > 0) { distX = plocal.X - box.HalfExtent.X; } else { distX = plocal.X + box.HalfExtent.X; } if (sY > 0) { distY = plocal.Y - box.HalfExtent.Y; } else { distY = plocal.Y + box.HalfExtent.Y; } if (sZ > 0) { distZ = plocal.Z - box.HalfExtent.Z; } else { distZ = plocal.Z + box.HalfExtent.Z; } //float diff = (distX + distY + distZ) / 3; //float diff = (sX*sY*sZ) * System.Math.Min(System.Math.Min(distX,distY), distZ); int contentX; int contentY; int contentZ; if (sX < 0) { if (distX > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentX = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (distX < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentX = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentX = MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distX / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } else { if (distX < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentX = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (distX > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentX = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentX = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distX / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } if (sY < 0) { if (distY > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (distY < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentY = MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distY / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } else { if (distY < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (distY > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentY = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distY / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } if (sZ < 0) { if (distZ > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentZ = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (distZ < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentZ = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentZ = MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distZ / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } else { if (distZ < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentZ = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (distZ > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentZ = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentZ = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distZ / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } //voxelMap.SetVoxelContent( (byte)((contentX + contentY + contentZ)/3.0f), ref tempVoxelCoord); newContent = (byte)(System.Math.Min(System.Math.Min(contentX, contentY), contentZ)); } byte originalContent = voxelMap.GetVoxelContent(ref tempVoxelCoord); if (newContent < originalContent) { voxelMap.SetVoxelContent(newContent, ref tempVoxelCoord, true); //changed = true; } }); }); }); /* for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) { for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) { for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { } } }*/ changed = true; voxelMap.InvalidateCache(minCorner, maxCorner); voxelMap.CalcAverageDataCellMaterials(); }
// Create world using data received from server public void CreateWorldFromDataReceivedFromServer() { MyMwcLog.WriteLine("CreateWorldFromDataReceivedFromServer - START"); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("CreateWorldFromDataReceivedFromServer"); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("MySession.BeforeLoad"); MySession.Static.BeforeLoad(m_checkpoint); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); CreateWorldFromDataReceivedFromServer_LoadCheckpoint(); bool canUseGenerator = m_sessionType.Value != MyMwcStartSessionRequestTypeEnum.EDITOR_SANDBOX && m_sessionType.Value != MyMwcStartSessionRequestTypeEnum.SANDBOX_OWN && MyFakes.ENABLE_GENERATED_ASTEROIDS; if (m_checkpoint.SectorObjectBuilder.FromGenerator && canUseGenerator) // When no sector on server, use procedural generator { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("ProceduralGenerator.Player"); if (m_checkpoint.PlayerObjectBuilder == null) { MyMwcObjectBuilder_SmallShip_Player playerShipObjectBuilder = CreatePlayerShip(); playerShipObjectBuilder.PositionAndOrientation.Position = Vector3.Zero; playerShipObjectBuilder.PositionAndOrientation.Up = Vector3.Up; playerShipObjectBuilder.PositionAndOrientation.Forward = Vector3.Forward; m_checkpoint.PlayerObjectBuilder = new MyMwcObjectBuilder_Player(100f, 10000f, 0f, null, playerShipObjectBuilder, null); } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); } UpdateSmallshipsOfferedByVendors(m_checkpoint); if (((m_checkpoint.SectorObjectBuilder.FromGenerator && MyFakes.ENABLE_GENERATED_ASTEROIDS) || canUseGenerator)) // When no sector on server, use procedural generator { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Generating sector"); //Use objects from server and generate new items into them //m_checkpoint.SectorObjectBuilder.SectorObjects = new List<MyMwcObjectBuilder_Base>(); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Safe areas"); if (m_checkpoint.SectorObjectBuilder.SectorObjects == null) { m_checkpoint.SectorObjectBuilder.SectorObjects = new List<MyMwcObjectBuilder_Base>(); } MyMwcLog.WriteLine("Adding safe areas"); List<BoundingSphere> safeAreas = new List<BoundingSphere>(); foreach (MyMwcObjectBuilder_Base objectBuilder in m_checkpoint.SectorObjectBuilder.SectorObjects) { MyMwcObjectBuilder_DummyPoint dummyObjectBuilder = objectBuilder as MyMwcObjectBuilder_DummyPoint; if (dummyObjectBuilder != null && dummyObjectBuilder.DummyFlags.HasFlag(MyDummyPointFlags.SAFE_AREA)) { safeAreas.Add(new BoundingSphere(dummyObjectBuilder.PositionAndOrientation.Position, dummyObjectBuilder.Size.Length() / 2.0f)); } MyMwcObjectBuilder_VoxelMap voxelObjectBuilder = objectBuilder as MyMwcObjectBuilder_VoxelMap; if (voxelObjectBuilder != null) { MyMwcVector3Int sizeInVoxels = MyVoxelFiles.Get(voxelObjectBuilder.VoxelFile).SizeInVoxels; Vector3 sizeInMeters = new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES * sizeInVoxels.X, MyVoxelConstants.VOXEL_SIZE_IN_METRES * sizeInVoxels.Y, MyVoxelConstants.VOXEL_SIZE_IN_METRES * sizeInVoxels.Z); safeAreas.Add(new BoundingSphere(voxelObjectBuilder.PositionAndOrientation.Position, sizeInMeters.Length() / 2.0f)); } } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); MyMwcLog.WriteLine("GenerateSector"); MySolarSystemMapSectorData sectorData = GenerateSector(m_sectorIdentifier.Position, m_checkpoint.SectorObjectBuilder.SectorObjects, safeAreas, m_checkpoint.SectorObjectBuilder.SectorObjects.Count > 0); //MySolarSystemMapSectorData sectorData = GenerateSectorData(); m_checkpoint.SectorObjectBuilder.AreaTemplate = sectorData.Area; m_checkpoint.SectorObjectBuilder.AreaMultiplier = sectorData.AreaInfluenceMultiplier; MySector.UseGenerator = true; MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); } else if (!m_checkpoint.SectorObjectBuilder.AreaTemplate.HasValue) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Generating sector area data"); MySolarSystemMapSectorData sectorData = GenerateSectorData(); m_checkpoint.SectorObjectBuilder.AreaTemplate = sectorData.Area; m_checkpoint.SectorObjectBuilder.AreaMultiplier = sectorData.AreaInfluenceMultiplier; MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); } MyMwcLog.WriteLine("CreateFromSectorObjectBuilder"); CreateFromSectorObjectBuilder(m_checkpoint.SectorObjectBuilder); MyTrailerLoad.TrailerAnimation = null; // If null, then loop above didn't contain player's ship MyCommonDebugUtils.AssertRelease(MySession.PlayerShip != null); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Preload cockpit models"); MySmallShip playerShip = MySession.PlayerShip; // Pre-load player's cockpit interior models // IMPORTANT: Only data and no vertex buffers, because this method is called from Update and not from Draw MyModels.GetModelOnlyData(MySession.PlayerShip.CockpitInteriorModelEnum); MyModels.GetModelOnlyData(MySession.PlayerShip.CockpitGlassModelEnum); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); //0002325: AI - Add friend bot to story and sandbox, he will be there by default. if (!IsEditorActive() && MyFakes.SPAWN_FRIENDS == true) { MySession.PlayerFriends.Clear();// when saving bots will be enabled please remove this if (MySession.PlayerFriends.Count == 0) { MySmallShipBot bot = CreateFakeBot("Friend", MyMwcObjectBuilder_SmallShip_TypesEnum.GREISER, MySession.PlayerShip.WorldMatrix.Translation + new Vector3(0, 30, 30), 1f, MyMwcObjectBuilder_FactionEnum.Euroamerican); MySession.PlayerFriends.Add(bot); bot.Follow(MySession.PlayerShip); bot.Save = false; bot = CreateFakeBot("Friend", MyMwcObjectBuilder_SmallShip_TypesEnum.GREISER, MySession.PlayerShip.WorldMatrix.Translation + new Vector3(0, -30, 30), 1f, MyMwcObjectBuilder_FactionEnum.Euroamerican); MySession.PlayerFriends.Add(bot); bot.Follow(MySession.PlayerShip); bot.Save = false; } } MyMwcLog.WriteLine("MySession.Static.AfterLoad"); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("AfterLoad"); MySession.Static.AfterLoad(m_checkpoint); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Side missions"); // Side missions foreach (var dummy in MyEntities.GetEntities().OfType<MyDummyPoint>()) { if ((dummy.DummyFlags & MyDummyPointFlags.SIDE_MISSION) != 0) { MyMwcLog.WriteLine("Side missions"); // TODO: Choose random submission var sideMission = new MySideMissionAssassination(new MyMissionBase.MyMissionLocation(m_checkpoint.CurrentSector.Position, dummy.EntityId.Value.NumericValue)); if (MyMissions.GetMissionByID(sideMission.ID) == null) { MyMissions.AddMission(sideMission); } } } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); MyMwcLog.WriteLine("MySession.Static.Player.TravelEnter"); //Unpacks player friends needed for mission script MySession.Static.Player.TravelEnter(); if (MySession.Is25DSector) MyGlobalEvents.DisableAllGlobalEvents(); else MyGlobalEvents.EnableAllGlobalEvents(); // Init active mission System.Diagnostics.Debug.Assert(MyMissions.ActiveMission == null); MyMwcLog.WriteLine("Active mission load - START"); if (GetGameType() == MyGuiScreenGamePlayType.GAME_STORY && (MyMultiplayerGameplay.Static == null || MyMultiplayerGameplay.Static.IsHost)) { MyMwcLog.WriteLine("Starting story mission"); if (m_checkpoint.ActiveMissionID != -1) { MyMwcLog.WriteLine("ActiveMissionID: " + m_checkpoint.ActiveMissionID); MyMission mission = MyMissions.GetMissionByID((MyMissionID)m_checkpoint.ActiveMissionID) as MyMission; MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Load active mission"); if (mission.IsMainSector) { mission.InsertRequiredActors(); } mission.Load(); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); } else { MyMwcLog.WriteLine("ActiveMissionID: none"); if (m_missionToStart.HasValue) { MyMission mission = MyMissions.GetMissionByID(m_missionToStart.Value) as MyMission; MyScriptWrapper.DebugSetFactions(mission); mission.Accept(); m_missionToStart = null; } } MyMissions.RefreshAvailableMissions(); if (m_travelReason == MyMwcTravelTypeEnum.SOLAR) { if (MyMissions.ActiveMission == null || MyMissions.ActiveMission.MovePlayerToMadelynHangar) { if (MyMissionBase.IsPlayerShipNearMadelyn()) { if (MyMissions.ActiveMission != null) MyMissionBase.MovePlayerAndFriendsToHangar(MyMissions.ActiveMission.RequiredActors); else MyMissionBase.MovePlayerAndFriendsToHangar(new MyActorEnum[] { MyActorEnum.MARCUS, MyActorEnum.TARJA, MyActorEnum.VALENTIN }); } } } } else if (GetGameType() == MyGuiScreenGamePlayType.GAME_SANDBOX) { MyMwcLog.WriteLine("Starting sandbox mission"); MyMissions.StartSandboxMission(m_checkpoint.CurrentSector.Position); } MyMwcLog.WriteLine("Active mission load - END"); MyEntities.UpdateAfterSimulation(); //Updates AABBs of objects if (MyMultiplayerGameplay.IsStory()) { MyMultiplayerGameplay.MakeInventoryItemsTradeable(MySession.PlayerShip); } if (MyFakes.MWBUILDER) { MyVoxelMap voxelMap = null; if (MyVoxelMaps.GetVoxelMapsCount() == 0) { // MyMwcObjectBuilder_VoxelMap voxelMapOb = new MyMwcObjectBuilder_VoxelMap(Vector3.Zero, MyMwcVoxelFilesEnum.Cube_512x512x512, MyMwcVoxelMaterialsEnum.Stone_01); // voxelMap = (MyVoxelMap)MyEntities.CreateFromObjectBuilderAndAdd(null, voxelMapOb, Matrix.Identity); voxelMap = new MyVoxelMap(); voxelMap.Init(Vector3.Zero, new MyMwcVector3Int(1024, 1024, 1024), MyMwcVoxelMaterialsEnum.Stone_01); //MyVoxelImport.Fill(voxelMap); MyVoxelImport.FillEmpty(voxelMap); MyEntities.Add(voxelMap); voxelMap.SetPosition(Vector3.Zero); MyVoxelGenerator.CreateSphere(voxelMap, new BoundingSphere(Vector3.Zero, 1024)); voxelMap.InvalidateCache(new MyMwcVector3Int(0, 0, 0), new MyMwcVector3Int(1024, 1024, 1024)); MyVoxelMaps.RecalcVoxelMaps(); voxelMap.UpdateAABBHr(); voxelMap.SaveVoxelContents(Path.Combine(MyMinerGame.Static.RootDirectory, "VoxelMaps", MyVoxelFiles.ExportFile + ".vox")); //MyVoxelGenerator.CutOutBoxRelative(voxelMap, new Vector3(0, 0.5f, 0), new Vector3(1, 1, 1)); /* MyVoxelGenerator.ChangeMaterialInBoxRelative(voxelMap, new Vector3(0, 0.49f, 0), new Vector3(1, 0.5f, 1), MyMwcVoxelMaterialsEnum.Uranite_01); MyVoxelGenerator.ChangeMaterialInBoxRelative(voxelMap, new Vector3(0, 0.2f, 0), new Vector3(1, 0.49f, 1), MyMwcVoxelMaterialsEnum.Nickel_01); MyVoxelGenerator.ChangeMaterialInBoxRelative(voxelMap, new Vector3(0, 0.0f, 0), new Vector3(1, 0.1f, 1), MyMwcVoxelMaterialsEnum.Lava_01); */ } else { voxelMap = MyVoxelMaps.GetVoxelMaps()[0]; MyPhysics.physicsSystem.GravitationPoints.Clear(); MyPhysics.physicsSystem.GravitationPoints.Add(new Tuple<BoundingSphere,float>(new BoundingSphere(voxelMap.WorldAABB.GetCenter(), voxelMap.WorldAABB.Size().Length()), 2000)); // voxelMap.Init(Vector3.Zero, new MyMwcVector3Int(1024, 1024, 1024), MyMwcVoxelMaterialsEnum.Stone_01); // MyVoxelImport.Fill(voxelMap); // MyVoxelGenerator.CutOutBoxRelative(voxelMap, new Vector3(0, 0.3f, 0), new Vector3(1, 1, 1)); // string name = Path.Combine(MyFileSystemUtils.GetApplicationUserDataFolder(), "VoxelMap_0_mikrogen.vox"); // voxelMap.SaveVoxelContents(name); // voxelMap.SetName("VoxelMap_0_mikrogen.vox"); // voxelMap.Init(null, Vector3.Zero, null); } MySpectator.Position = voxelMap.WorldAABB.GetCenter(); MyCamera.SetViewMatrix(MySpectator.GetViewMatrix()); } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); MyMwcLog.WriteLine("CreateWorldFromDataReceivedFromServer - END"); }