private Image TryGetPlanetTexture(string name, MyModContext context, string p, out string fullPath) { bool found = false; name += p; fullPath = Path.Combine(context.ModPathData, "PlanetDataFiles", name) + ".png"; // Check for modded textures if (!context.IsBaseGame) { if (!MyFileSystem.FileExists(fullPath)) { fullPath = Path.Combine(context.ModPathData, "PlanetDataFiles", name) + ".dds"; if (MyFileSystem.FileExists(fullPath)) { found = true; } } else { found = true; } } // Check for default textures if (!found) { fullPath = Path.Combine(m_planetDataFolder, name) + ".png"; if (!MyFileSystem.FileExists(fullPath)) { fullPath = Path.Combine(m_planetDataFolder, name) + ".dds"; if (!MyFileSystem.FileExists(fullPath)) { return(null); } } } if (fullPath.Contains(".sbm")) { string archivePath = fullPath.Substring(0, fullPath.IndexOf(".sbm") + 4); string fileRelativeArchivePath = fullPath.Replace(archivePath + "\\", ""); using (var sbm = VRage.Compression.MyZipArchive.OpenOnFile(archivePath)) { try { return(SharpDXImage.Load(sbm.GetFile(fileRelativeArchivePath).GetStream())); } catch (Exception ex) { MyDebug.FailRelease("Failed to load existing " + p + " file from .sbm archive. " + fullPath); return(null); } } } return(SharpDXImage.Load(fullPath)); }
public MyCubemap(params MyCubemapData <byte>[] faces) { if (faces.Length != 6) { MyDebug.FailRelease("When loading cubemap exactly 6 faces are expected."); } base.m_faces = faces; base.m_resolution = faces[0].Resolution; base.PrepareSides(); }
internal void Unregister(IMyGunObject <MyDeviceBase> gun) { MyDebug.AssertDebug(gun != null); if (!m_gunsByDefId.ContainsKey(gun.DefinitionId)) { MyDebug.FailRelease("deinition ID " + gun.DefinitionId + " not in m_gunsByDefId"); return; } MyDebug.AssertDebug(m_gunsByDefId[gun.DefinitionId].Contains(gun)); m_gunsByDefId[gun.DefinitionId].Remove(gun); if (WeaponUnregistered != null) { WeaponUnregistered(this, new EventArgs() { Weapon = gun }); } }
public override bool IsOverlapOverThreshold(BoundingBoxD worldAabb, float thresholdPercentage) { if (m_storage == null) { if (MyEntities.GetEntityByIdOrDefault(this.EntityId) != this) { MyDebug.FailRelease("Voxel map was deleted!"); } else { MyDebug.FailRelease("Voxel map is still in world but has null storage!"); } return(false); } //Debug.Assert( // worldAabb.Size.X > MyVoxelConstants.VOXEL_SIZE_IN_METRES && // worldAabb.Size.Y > MyVoxelConstants.VOXEL_SIZE_IN_METRES && // worldAabb.Size.Z > MyVoxelConstants.VOXEL_SIZE_IN_METRES, // "One of the sides of queried AABB is too small compared to voxel size. Results will be unreliable."); Vector3I minCorner, maxCorner; MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Min, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Max, out maxCorner); minCorner += StorageMin; maxCorner += StorageMin; Storage.ClampVoxelCoord(ref minCorner); Storage.ClampVoxelCoord(ref maxCorner); m_tempStorage.Resize(minCorner, maxCorner); Storage.ReadRange(m_tempStorage, MyStorageDataTypeFlags.Content, 0, ref minCorner, ref maxCorner); BoundingBoxD voxelBox; //MyRenderProxy.DebugDrawAABB(worldAabb, Color.White, 1f, 1f, true); var invFullVoxel = 1.0 / (double)MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT; var voxelVolume = 1.0 / (double)MyVoxelConstants.VOXEL_VOLUME_IN_METERS; double overlapContentVolume = 0.0; var queryVolume = worldAabb.Volume; //using (var batch = MyRenderProxy.DebugDrawBatchAABB(Matrix.Identity, new Color(Color.Green, 0.1f), true, true)) { Vector3I coord, cache; for (coord.Z = minCorner.Z, cache.Z = 0; coord.Z <= maxCorner.Z; coord.Z++, cache.Z++) { for (coord.Y = minCorner.Y, cache.Y = 0; coord.Y <= maxCorner.Y; coord.Y++, cache.Y++) { for (coord.X = minCorner.X, cache.X = 0; coord.X <= maxCorner.X; coord.X++, cache.X++) { MyVoxelCoordSystems.VoxelCoordToWorldAABB(PositionLeftBottomCorner, ref coord, out voxelBox); if (worldAabb.Intersects(voxelBox)) { var contentVolume = m_tempStorage.Content(ref cache) * invFullVoxel * voxelVolume; var overlapVolume = worldAabb.Intersect(voxelBox).Volume; overlapContentVolume += contentVolume * overlapVolume; //batch.Add(ref voxelBox); } } } } } var overlapVolumePercentage = overlapContentVolume / queryVolume; //MyRenderProxy.DebugDrawText3D(worldAabb.Center, overlapVolumePercentage.ToString("0.000"), Color.White, 1f, false); return(overlapVolumePercentage >= thresholdPercentage); }
public void CreatePruningTree(string mapName) { int depth = 0; int res = Resolution; res /= HeightmapNode.HEIGHTMAP_LEAF_SIZE; // check if we get an even tree, for now we will rely on that. while (res != 1) { if (res % HeightmapNode.HEIGHTMAP_BRANCH_FACTOR != 0) { MyDebug.FailRelease("Cannot build prunning tree for heightmap face {0}!", mapName); MyDebug.FailRelease("Heightmap resolution must be divisible by {1}, and after that a power of {0}. Failing to achieve so will disable several important optimizations!!", HeightmapNode.HEIGHTMAP_BRANCH_FACTOR, HeightmapNode.HEIGHTMAP_LEAF_SIZE); return; } depth++; res /= HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; } PruningTree = new HeightmapLevel[depth]; int offset = GetRowStart(0); if (depth == 0) { float min = float.PositiveInfinity; float max = float.NegativeInfinity; int localOffset = offset; for (int y = 0; y < HeightmapNode.HEIGHTMAP_LEAF_SIZE; ++y) { for (int x = 0; x < HeightmapNode.HEIGHTMAP_LEAF_SIZE; ++x) { float value = ((float)Data[localOffset + x] * MyCubemapHelpers.USHORT_RECIP); if (min > value) { min = value; } if (max < value) { max = value; } } localOffset += m_real_resolution; } Root.Max = max; Root.Min = min; return; } int nodes = HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; res = Resolution / HeightmapNode.HEIGHTMAP_LEAF_SIZE; // prepare leaf level PruningTree[0].Nodes = new HeightmapNode[res * res]; PruningTree[0].Res = (uint)res; int cell = 0; for (int j = 0; j < res; ++j) { int coffset = offset; for (int i = 0; i < res; ++i) { float min = float.PositiveInfinity; float max = float.NegativeInfinity; int localOffset = coffset - m_real_resolution; for (int y = -1; y <= HeightmapNode.HEIGHTMAP_LEAF_SIZE; ++y) { for (int x = -1; x <= HeightmapNode.HEIGHTMAP_LEAF_SIZE; ++x) { float value = ((float)Data[localOffset + x] * MyCubemapHelpers.USHORT_RECIP); if (min > value) { min = value; } if (max < value) { max = value; } } localOffset += m_real_resolution; } PruningTree[0].Nodes[cell] = new HeightmapNode() { Max = max, Min = min }; cell++; coffset += HeightmapNode.HEIGHTMAP_LEAF_SIZE; } offset += HeightmapNode.HEIGHTMAP_LEAF_SIZE * m_real_resolution; } int l = 0; for (int k = 1; k < depth; k++) { offset = 0; int levelRes = res / HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; PruningTree[k].Nodes = new HeightmapNode[levelRes * levelRes]; PruningTree[k].Res = (uint)levelRes; cell = 0; for (int j = 0; j < levelRes; ++j) { int coffset = offset; for (int i = 0; i < levelRes; ++i) { float min = float.PositiveInfinity; float max = float.NegativeInfinity; int localOffset = coffset; for (int y = 0; y < HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; ++y) { for (int x = 0; x < HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; ++x) { HeightmapNode n = PruningTree[l].Nodes[localOffset + x]; if (min > n.Min) { min = n.Min; } if (max < n.Max) { max = n.Max; } } localOffset += res; } PruningTree[k].Nodes[cell] = new HeightmapNode() { Max = max, Min = min }; cell++; coffset += HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; } offset += HeightmapNode.HEIGHTMAP_BRANCH_FACTOR * res; } // previous level l++; res = levelRes; } float tmin = float.PositiveInfinity; float tmax = float.NegativeInfinity; offset = 0; for (int y = 0; y < HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; ++y) { for (int x = 0; x < HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; ++x) { HeightmapNode n = PruningTree[depth - 1].Nodes[offset++]; if (tmin > n.Min) { tmin = n.Min; } if (tmax < n.Max) { tmax = n.Max; } } } Root.Max = tmax; Root.Min = tmin; }
public void GetPlanetMaps(string folder, MyModContext context, MyPlanetMaps mapsToUse, out MyCubemap[] maps) { if (m_planetMaps.ContainsKey(folder)) { maps = m_planetMaps[folder]; return; } maps = new MyCubemap[4]; MyCubemapData <byte>[] tmpMaps = new MyCubemapData <byte> [4 * 6]; byte[][] streams = new byte[4][]; string fullPath; ProfilerShort.Begin("MyHeightmapLoadingSystem::GetPlanetMaps()"); ProfilerShort.Begin("Load _mat"); // Round one: material, ore, biome if (mapsToUse.Material || mapsToUse.Biome || mapsToUse.Ores) { for (int i = 0; i < 6; ++i) { string name = Path.Combine(folder, MyCubemapHelpers.GetNameForFace(i)); using (var texture = TryGetPlanetTexture(name, context, "_mat", out fullPath)) { if (texture == null) { ClearMatValues(tmpMaps); break; } PixelBuffer buffer = texture.GetPixelBuffer(0, 0, 0); if (buffer.Format != Format.B8G8R8A8_UNorm && buffer.Format != Format.R8G8B8A8_UNorm) { MyDebug.FailRelease("While loading maps from {1}: Unsupported planet map format: {0}.", buffer.Format, fullPath); break; } if (buffer.Width != buffer.Height) { MyDebug.FailRelease("While loading maps from {0}: Width and height must be the same.", fullPath); break; } if (mapsToUse.Material) { tmpMaps[i * 4] = new MyCubemapData <byte>(buffer.Width); streams[0] = tmpMaps[i * 4].Data; } if (mapsToUse.Biome) { tmpMaps[i * 4 + 1] = new MyCubemapData <byte>(buffer.Width); streams[1] = tmpMaps[i * 4 + 1].Data; } if (mapsToUse.Ores) { tmpMaps[i * 4 + 2] = new MyCubemapData <byte>(buffer.Width); streams[2] = tmpMaps[i * 4 + 2].Data; } // Invert channels for BGRA if (buffer.Format == Format.B8G8R8A8_UNorm) { var tmp = streams[2]; streams[2] = streams[0]; streams[0] = tmp; } ReadChannelsFromImage(streams, buffer); } } } ProfilerShort.BeginNextBlock("Load _add"); // round two: add map if (mapsToUse.Occlusion) { for (int i = 0; i < 6; ++i) { string name = Path.Combine(folder, MyCubemapHelpers.GetNameForFace(i)); using (var texture = TryGetPlanetTexture(name, context, "_add", out fullPath)) { if (texture == null) { ClearAddValues(tmpMaps); break; } PixelBuffer buffer = texture.GetPixelBuffer(0, 0, 0); if (buffer.Format != Format.B8G8R8A8_UNorm && buffer.Format != Format.R8G8B8A8_UNorm) { MyDebug.FailRelease("While loading maps from {1}: Unsupported planet map format: {0}.", buffer.Format, fullPath); break; } if (buffer.Width != buffer.Height) { MyDebug.FailRelease("While loading maps from {0}: Width and height must be the same.", fullPath); break; } if (mapsToUse.Occlusion) { tmpMaps[i * 4 + 3] = new MyCubemapData <byte>(buffer.Width); streams[0] = tmpMaps[i * 4 + 3].Data; } streams[1] = streams[2] = null; // Invert channels for BGRA if (buffer.Format == Format.B8G8R8A8_UNorm) { var tmp = streams[2]; streams[2] = streams[0]; streams[0] = tmp; } ReadChannelsFromImage(streams, buffer); } } } ProfilerShort.BeginNextBlock("Finish"); for (int i = 0; i < 4; ++i) { if (tmpMaps[i] != null) { var cmaps = new MyCubemapData <byte> [6]; for (int j = 0; j < 6; j++) { cmaps[j] = tmpMaps[i + j * 4]; } maps[i] = new MyCubemap(cmaps); } } m_planetMaps[folder] = maps; ProfilerShort.End(); ProfilerShort.End(); }
public MyHeightmapFace GetHeightMap(string folderName, string faceName, MyModContext context) { ProfilerShort.Begin("MyHeightmapLoadingSystem::GetHeightMap()"); if (m_first) { PreloadCrashingData(); m_first = false; } string fullPath = null; bool found = false; // Look for modded textures if (!context.IsBaseGame) { fullPath = Path.Combine(Path.Combine(context.ModPathData, "PlanetDataFiles"), folderName, faceName); if (MyFileSystem.FileExists(fullPath + ".png")) { found = true; fullPath += ".png"; } else if (MyFileSystem.FileExists(fullPath + ".dds")) { found = true; fullPath += ".dds"; } } // Use default ones if (!found) { fullPath = Path.Combine(m_planetDataFolder, folderName, faceName); if (MyFileSystem.FileExists(fullPath + ".png")) { found = true; fullPath += ".png"; } else if (MyFileSystem.FileExists(fullPath + ".dds")) { fullPath += ".dds"; } } MyHeightmapFace value; if (m_heightMaps.TryGetValue(fullPath, out value)) { ProfilerShort.End(); return(value); } try { using (SharpDXImage image = LoadTexture(fullPath)) { if (image == null) { MyLog.Default.WriteLine("Could not load texture {0}, no suitable format found. " + fullPath); } else { PixelBuffer buffer = image.GetPixelBuffer(0, 0, 0); value = new MyHeightmapFace(buffer.Height); if (buffer.Format == Format.R16_UNorm) { PrepareHeightMap(value, buffer); } else if (buffer.Format == Format.R8_UNorm) { PrepareHeightMap8Bit(value, buffer); } else { MyDebug.FailRelease(String.Format("Heighmap texture {0}: Invalid format {1} (expecting R16_UNorm or R8_UNorm).", fullPath, buffer.Format)); } buffer = null; } } m_heightMaps[fullPath] = value; } catch (Exception e) { MyLog.Default.WriteLine(e.Message); } ProfilerShort.End(); return(value); }
void ProcessTags() { // TODO: This code could be better. // Get the list of existing tags, if there are any var existingTags = GetTags(); var length = m_tags.Length; // Order or tag processing matters // 1) Copy mod type into tags var modtype = m_type.ToString(); // 2) Verify the modtype matches what was listed in the workshop // TODO If type doesn't match, process as workshop type if (existingTags != null && existingTags.Length > 0) { MyDebug.AssertDebug(existingTags.Contains(modtype), string.Format("Mod type '{0}' does not match workshop '{1}'", modtype, existingTags[0])); } // 3a) check if user passed in the 'development' tag // If so, remove it, and mark the mod as 'dev' so it doesn't get flagged later if (m_tags.Contains(MySteamWorkshop.WORKSHOP_DEVELOPMENT_TAG)) { m_tags = (from tag in m_tags where tag != MySteamWorkshop.WORKSHOP_DEVELOPMENT_TAG select tag).ToArray(); m_isDev = true; } // 3b If tags contain mod type, remove it if (m_tags.Contains(modtype)) { m_tags = (from tag in m_tags where tag != modtype select tag).ToArray(); } // 4) if (m_tags.Length == 1 && m_tags[0] == null && existingTags != null && existingTags.Length > 0) { // 4a) If user passed no tags, use existing ones Array.Resize(ref m_tags, existingTags.Length); Array.Copy(existingTags, m_tags, existingTags.Length); } else { // 4b) Verify passed in tags are valid for this mod type MySteamWorkshop.Category[] validTags = new MySteamWorkshop.Category[0]; switch (m_type) { case WorkshopType.Mod: validTags = MySteamWorkshop.ModCategories; break; case WorkshopType.Blueprint: validTags = MySteamWorkshop.BlueprintCategories; break; case WorkshopType.Scenario: validTags = MySteamWorkshop.ScenarioCategories; break; case WorkshopType.World: validTags = MySteamWorkshop.WorldCategories; break; case WorkshopType.IngameScript: //tags = new MySteamWorkshop.Category[0]; // There are none currently break; default: MyDebug.FailRelease("Invalid category."); break; } // This query gets all the items in 'm_tags' that do *not* exist in 'validTags' // This is for detecting invalid tags passed in var invalidItems = from utag in m_tags where !( from tag in validTags select tag.Id ).Contains(utag) select utag; if (invalidItems.Count() > 0) { MySandboxGame.Log.WriteLineAndConsole(string.Format("{0} invalid tags: {1}", (m_force ? "Forced" : "Removing"), string.Join(", ", invalidItems))); if (!m_force) { m_tags = (from tag in m_tags where !invalidItems.Contains(tag) select tag).ToArray(); } } // Now prepend the 'Type' tag string[] newTags = new string[m_tags.Length + 1]; newTags[0] = m_type.ToString(); Array.Copy(m_tags, 0, newTags, 1, m_tags.Length); m_tags = newTags; } // 5) Set or clear development tag if (m_isDev) { // If user selected dev, add dev tag if (!m_tags.Contains(MySteamWorkshop.WORKSHOP_DEVELOPMENT_TAG)) { Array.Resize(ref m_tags, m_tags.Length + 1); m_tags[m_tags.Length - 1] = MySteamWorkshop.WORKSHOP_DEVELOPMENT_TAG; } } else { // If not, remove tag if (m_tags.Contains(MySteamWorkshop.WORKSHOP_DEVELOPMENT_TAG)) { m_tags = (from tag in m_tags where tag != MySteamWorkshop.WORKSHOP_DEVELOPMENT_TAG select tag).ToArray(); } } // 6) Strip empty values m_tags = m_tags.Where(x => !string.IsNullOrEmpty(x)).ToArray(); // Done MySandboxGame.Log.WriteLineAndConsole(string.Format("Publishing with tags: {0}", string.Join(", ", m_tags))); }