public ModelRoot Run(ModelRoot model, OsmLayer layers, BoundingBox bbox, GeoTransformPipeline transform, bool computeElevations, DEMDataSet dataSet = null, bool downloadMissingFiles = true, bool withBuildingsColors = false, string defaultBuildingsColor = null) { model = model ?? _gltfService.CreateNewModel(); if (layers == OsmLayer.None) { return(model); } IOsmDataService osmDataService = _dataServiceFactory.Create(Settings.DataServiceType); List <IOsmProcessor> processors = Build(layers, computeElevations, transform, withBuildingsColors, defaultBuildingsColor); foreach (var p in processors) { p.DataSettings.FlatGeobufTilesDirectory = Settings.FlatGeobufTilesDirectory; p.Init(_elevationService, _gltfService, _meshService, osmDataService, _logger); model = p.Run(model, bbox, computeElevations, dataSet, downloadMissingFiles); } return(model); }
internal void RunGPX(DEMDataSet largeDataSet, DEMDataSet localDataset) { try { string outputDir = Path.GetFullPath("."); string _gpxFile = Path.Combine("SampleData", "20191022-Puch-Pöllau.gpx"); string sensorLogFile = Path.Combine("SampleData", "20191023-Puch-Pöllau-sensorlog.json"); var sensorLog = SensorLog.FromJson(sensorLogFile); //sensorLog.Plot("sensorLog.png"); string balloonModel = Path.Combine("SampleData", "OE-SOE.glb"); float Z_FACTOR = 2f; float trailWidthMeters = 5f; ModelRoot balloon = ModelRoot.Load(balloonModel); //======================= /// Line strip from GPX /// // Get GPX points var segments = GpxImport.ReadGPX_Segments <GpxTrackPoint>(_gpxFile, p => p); var pointsGpx = segments.SelectMany(seg => seg); var geoPoints = pointsGpx.ToGeoPoints(); var model = _sharpGltfService.CreateNewModel(); //var largeMesh = GetMeshFromGpxTrack(outputDir, largeDataSet, geoPoints // , bboxScale: 5 // , zFactor: Z_FACTOR // , generateTIN: false // , tinPrecision: 500d // , drawGpxOnTexture: false // , ImageryProvider.OpenTopoMap); //meshes.Add(largeMesh); model = GetMeshFromGpxTrack(model, outputDir, localDataset, geoPoints , bboxScale: (1.3, 1.5) , zFactor: Z_FACTOR , generateTIN: false , tinPrecision: 50d , drawGpxOnTexture: true , ImageryProvider.EsriWorldImagery); var gpxPoints = geoPoints.ReprojectGeodeticToCartesian().ZScale(Z_FACTOR); model = _sharpGltfService.AddLine(model, gpxPoints, new Vector4(0, 1, 0, 0.5f), trailWidthMeters); // model export Console.WriteLine("GenerateModel..."); var node = model.LogicalNodes.First(); pointsGpx = pointsGpx.ReprojectGeodeticToCartesian().ZScale(Z_FACTOR); // animations node = CreateAnimationFromGpx("GPX", node, pointsGpx, 1f); node = CreateAnimationFromGpx("GPX x500", node, pointsGpx, 500f); var sceneBuilderBalloon = balloon.DefaultScene.ToSceneBuilder(); var sceneBuilderTerrain = model.DefaultScene.ToSceneBuilder(); //sceneBuilderBalloon. model.SaveGLB(Path.Combine(Directory.GetCurrentDirectory(), $"{GetType().Name}.glb")); } catch (Exception ex) { _logger.LogError(ex, ex.Message); } }
internal void ExportVisualTopoToGLB(VisualTopoModel visualTopoModel, DEMDataSet dataset, string outputFile, bool drawOnTexture, float marginMeters, float zFactor, ImageryProvider imageryProvider) { int outputSrid = 3857; float lineWidth = 1.0F; int numTilesPerImage = 4; BoundingBox bbox = visualTopoModel.BoundingBox // relative coords .Translate(visualTopoModel.EntryPoint.Longitude, visualTopoModel.EntryPoint.Latitude, visualTopoModel.EntryPoint.Elevation ?? 0) // absolute coords .Pad(marginMeters) // margin around model .ReprojectTo(visualTopoModel.SRID, dataset.SRID); // DEM coords //======================= // Height map (get dem elevation for bbox) // // Get height map // Note that ref Bbox means that the bbox will be adjusted to match DEM data var heightMap = elevationService.GetHeightMap(ref bbox, dataset, downloadMissingFiles: true); var bboxTerrainSpace = bbox.ReprojectTo(dataset.SRID, outputSrid); // terrain coords // Model origin GeoPoint axisOriginWorldSpace = visualTopoModel.EntryPoint.ReprojectTo(visualTopoModel.SRID, outputSrid) .CenterOnOrigin(bboxTerrainSpace); Vector3 axisOriginModelSpace = visualTopoModel.EntryPoint.AsVector3(); //await signalR.ReportGenerateProgressAsync(signalRConnectionId, "Getting GPX extent elevation...", 20); //======================= // Local transform function from model coordinates (relative to entry, in meters) // and global coordinates absolute in final 3D model space // IEnumerable <GeoPoint> TransformLine(IEnumerable <GeoPoint> line) { var newLine = line.Translate(visualTopoModel.EntryPoint) // Translate to entry (=> global topo coord space) .ReprojectTo(visualTopoModel.SRID, outputSrid) // Reproject to terrain coord space .CenterOnOrigin(bboxTerrainSpace) // Center on terrain space origin .CenterOnOrigin(axisOriginWorldSpace); return(newLine); }; //======================= // 3D model // var gltfModel = sharpGltfService.CreateNewModel(); // Add X/Y/Z axis on entry point var axis = meshService.CreateAxis(); sharpGltfService.AddMesh(gltfModel, "Axis", axis, doubleSided: false); int i = 0; var triangulation = visualTopoModel.TriangulationFull3D.Clone() .Translate(axisOriginModelSpace) // already zScaled if zFactor > 1 .ReprojectTo(visualTopoModel.SRID, outputSrid) .CenterOnOrigin(bboxTerrainSpace) .CenterOnOrigin(axisOriginWorldSpace.AsVector3()); gltfModel = sharpGltfService.AddMesh(gltfModel, "Cavite3D", triangulation, VectorsExtensions.CreateColor(0, 255, 0), doubleSided: false); ////======================= //// 3D cavity model //foreach (var line in visualTopoModel.Topology3D) // model.Topology3D is the graph of topo paths //{ // // Add line to model // gltfModel = sharpGltfService.AddLine(gltfModel // , string.Concat("CavitySection", i++) // name of 3D node // , TransformLine(line) // call transform function // , color: VectorsExtensions.CreateColor(255, 0, 0, 128) // , lineWidth); //} // Reproject and center height map coordinates heightMap = heightMap.ReprojectTo(dataset.SRID, outputSrid) .CenterOnOrigin(bboxTerrainSpace) .ZScale(zFactor) .CenterOnOrigin(axisOriginWorldSpace); //======================= // Textures // PBRTexture pbrTexture = null; if (imageryProvider != null) { TileRange tiles = imageryService.DownloadTiles(bbox, imageryProvider, numTilesPerImage); string fileName = Path.Combine(Path.GetDirectoryName(outputFile), "Texture.jpg"); Console.WriteLine("Construct texture..."); TextureInfo texInfo = null; if (drawOnTexture) { var topoTexture = visualTopoModel.Topology3D.SelectMany(l => l).Translate(visualTopoModel.EntryPoint).ReprojectTo(visualTopoModel.SRID, 4326); texInfo = imageryService.ConstructTextureWithGpxTrack(tiles, bbox, fileName, TextureImageFormat.image_jpeg , topoTexture, drawGpxVertices: true); } else { texInfo = imageryService.ConstructTexture(tiles, bbox, fileName, TextureImageFormat.image_jpeg); } pbrTexture = PBRTexture.Create(texInfo, null); } // //======================= gltfModel = sharpGltfService.AddTerrainMesh(gltfModel, heightMap, pbrTexture); gltfModel.SaveGLB(outputFile); }
public static ModelRoot GenerateTIN(HeightMap hMap, double precision, SharpGltfService gltf, PBRTexture textures, int srid) { return(TINGeneration.AddTINMesh(gltf.CreateNewModel(), hMap, precision, gltf, textures, srid)); }
private void Buildings3DOnly() { string outputDir = Directory.GetCurrentDirectory(); string WKT_SF_BIG = "POLYGON((-122.53517427420718 37.81548554152065,-122.35149660086734 37.81548554152065,-122.35149660086734 37.70311455416941,-122.53517427420718 37.70311455416941,-122.53517427420718 37.81548554152065))"; string WKT_SF_SMALL = "POLYGON((-122.42722692299768 37.81034598808797, -122.38886060524865 37.81034598808797, -122.38886060524865 37.784573673820816, -122.42722692299768 37.784573673820816, -122.42722692299768 37.81034598808797))"; string WKT_SF_SUPERSMALL = "POLYGON((-122.41063177228989 37.80707295150412,-122.40904390455307 37.80707295150412,-122.40904390455307 37.806064225434206,-122.41063177228989 37.806064225434206,-122.41063177228989 37.80707295150412))"; // FULL string WKT_PRIPYAT_FULL = "POLYGON((30.021919548702254 51.41813804241615,30.083030998897566 51.41813804241615,30.083030998897566 51.389438684773985,30.021919548702254 51.389438684773985,30.021919548702254 51.41813804241615))"; // Cas 1 //string WKT_PRIPYAT = "POLYGON((30.05430313958436 51.404795567637294,30.055118531124887 51.404795567637294,30.055118531124887 51.40432372279637,30.05430313958436 51.40432372279637,30.05430313958436 51.404795567637294))"; // cas 2 //string WKT_PRIPYAT = "POLYGON((30.062877280833636 51.40748141189236,30.063456637980853 51.40748141189236,30.063456637980853 51.40716017522757,30.062877280833636 51.40716017522757,30.062877280833636 51.40748141189236))"; // cas 3 //string WKT_PRIPYAT = "POLYGON((30.065251398582948 51.407283441091266,30.066243815918458 51.407283441091266,30.066243815918458 51.40558353075506,30.065251398582948 51.40558353075506,30.065251398582948 51.407283441091266))"; string WKT_PRIPRYAT_SOMEROADS = "POLYGON((30.062684362726948 51.40792711901257,30.064690655070088 51.40792711901257,30.064690655070088 51.40693664170241,30.062684362726948 51.40693664170241,30.062684362726948 51.40792711901257))"; // SF Big: POLYGON((-122.53517427420718 37.81548554152065,-122.35149660086734 37.81548554152065,-122.35149660086734 37.70311455416941,-122.53517427420718 37.70311455416941,-122.53517427420718 37.81548554152065)) // SF Small: POLYGON((-122.41967382241174 37.81034598808797,-122.39761533547326 37.81034598808797,-122.39761533547326 37.79162804294824,-122.41967382241174 37.79162804294824,-122.41967382241174 37.81034598808797)) // Napoli, multi polygon (https://www.openstreetmap.org/relation/8955771) //new BoundingBox(14.364430059744153, 14.365218629194532, 40.78433307340424, 40.785023575175295); string WKT_AIX_FULL = "POLYGON((5.402291662243135 43.565714431347274,5.48056925013376 43.565714431347274,5.48056925013376 43.50797300081391,5.402291662243135 43.50797300081391,5.402291662243135 43.565714431347274))"; string WKT_AIX_WITHTERRAIN = "POLYGON((5.440657648511835 43.55957815383877,5.444434198804804 43.55957815383877,5.444434198804804 43.5579454365131,5.440657648511835 43.5579454365131,5.440657648511835 43.55957815383877))"; string WKT_AIX_SMALLOSMBUG = "POLYGON((5.441805234256467 43.55910060792738,5.442684998813352 43.55910060792738,5.442684998813352 43.55877017799191,5.441805234256467 43.55877017799191,5.441805234256467 43.55910060792738))"; string WKT_MONACO = "POLYGON((7.392147587957001 43.75577569838535,7.4410710803886415 43.75577569838535,7.4410710803886415 43.71757458493263,7.392147587957001 43.71757458493263,7.392147587957001 43.75577569838535))"; string WKT_MONACO_DEBUG = "POLYGON((7.421709439122424 43.73663530909531,7.433961769902453 43.73663530909531,7.433961769902453 43.733007331111345,7.421709439122424 43.733007331111345,7.421709439122424 43.73663530909531))";//"POLYGON((7.426780270757294 43.73870913810349,7.432520198049164 43.73870913810349,7.432520198049164 43.73501926928533,7.426780270757294 43.73501926928533,7.426780270757294 43.73870913810349))"; string WKT_HK = "POLYGON((114.13119740014092 22.360520982593926,114.21050495629326 22.360520982593926,114.21050495629326 22.28874575980822,114.13119740014092 22.28874575980822,114.13119740014092 22.360520982593926))"; string WKT_FRISCO = "POLYGON((-122.5235839391063 37.81433638393927,-122.36222224477036 37.81433638393927,-122.36222224477036 37.71228516909579,-122.5235839391063 37.71228516909579,-122.5235839391063 37.81433638393927))"; string WKT_DEFENSE = "POLYGON((2.222075572216413 48.902615468120246,2.3024130966304757 48.902615468120246,2.3024130966304757 48.86355756505397,2.222075572216413 48.86355756505397,2.222075572216413 48.902615468120246))"; DEMDataSet dataset = DEMDataSet.NASADEM; var name = nameof(WKT_DEFENSE); var bbox = GeometryService.GetBoundingBox(WKT_DEFENSE); bool computeElevations = true; ModelRoot model = _gltfService.CreateNewModel(); bool withTerrain = false; if (withTerrain) { var heightMap = _elevationService.GetHeightMap(ref bbox, dataset); var transform = new ModelGenerationTransform(bbox, Reprojection.SRID_PROJECTED_MERCATOR, centerOnOrigin: true, ZScale, centerOnZOrigin: true); heightMap = transform.TransformHeightMap(heightMap); TileRange tiles = _imageryService.DownloadTiles(bbox, ImageryProvider.MapBoxSatellite, 15); string fileName = Path.Combine(outputDir, "Texture.jpg"); TextureInfo texInfo = _imageryService.ConstructTexture(tiles, bbox, fileName, TextureImageFormat.image_jpeg); var pbrTexture = PBRTexture.Create(texInfo, null); model = _osmProcessor.Run(model, OsmLayer.Buildings | OsmLayer.Highways, bbox, transform, computeElevations, dataset, downloadMissingFiles: true); model = _gltfService.AddTerrainMesh(model, heightMap, pbrTexture); } else { var transform = new ModelGenerationTransform(bbox, Reprojection.SRID_PROJECTED_MERCATOR, centerOnOrigin: true, ZScale, centerOnZOrigin: true); model = _osmProcessor.Run(model, OsmLayer.Buildings | OsmLayer.Highways, bbox, transform, computeElevations, dataset, downloadMissingFiles: true); } model.SaveGLB(Path.Combine(Directory.GetCurrentDirectory(), name + ".glb")); }
/// <summary> /// Generates a VisualTopo file 3D model /// </summary> /// <remarks>LT* (Lambert Carto) projections are not supported and could produce imprecise results (shifted by +10meters)</remarks> /// <param name="vtopoFile">VisualTopo .TRO file</param> /// <param name="imageryProvider">Imagery provider for terrain texture. Set to null for untextured model</param> /// <param name="bboxMarginMeters">Terrain margin (meters) around VisualTopo model</param> public void Run_3DModelGeneration(string vtopoFile, ImageryProvider imageryProvider, float bboxMarginMeters = 1000, bool generateTopoOnlyModel = false, float zFactor = 1f) { try { //======================= // Generation params // int outputSRID = 3857; // Output SRID float lineWidth = 1.0F; // Topo lines width (meters) var dataset = DEMDataSet.AW3D30; // DEM dataset for terrain and elevation int TEXTURE_TILES = 8; // Texture quality (number of tiles for bigger side) 4: med, 8: high, 12: ultra string outputDir = Directory.GetCurrentDirectory(); bool GENERATE_LINE3D = false; //======================= // Open and parse file // // model will have available properties // => Graph (nodes/arcs) // => BoundingBox // => Topology3D -> list of point-to-point lines // => SRID of model file StopwatchLog timeLog = StopwatchLog.StartNew(_logger); VisualTopoModel model = _visualTopoService.LoadFile(vtopoFile, Encoding.GetEncoding("ISO-8859-1") , decimalDegrees: true , ignoreRadialBeams: true , zFactor); timeLog.LogTime($"Loading {vtopoFile} model file"); // for debug, //var b = GetBranches(model); // graph list of all nodes //var lowestPoint = model.Sets.Min(s => s.Data.Min(d => d.GlobalGeoPoint?.Elevation ?? 0)); BoundingBox bbox = model.BoundingBox // relative coords .Translate(model.EntryPoint.Longitude, model.EntryPoint.Latitude, model.EntryPoint.Elevation ?? 0) // absolute coords .Pad(bboxMarginMeters) // margin around model .ReprojectTo(model.SRID, dataset.SRID); // DEM coords // Get height map // Note that ref Bbox means that the bbox will be adjusted to match DEM data var heightMap = _elevationService.GetHeightMap(ref bbox, dataset, downloadMissingFiles: true); var bboxTerrainSpace = bbox.ReprojectTo(dataset.SRID, outputSRID); // terrain coords timeLog.LogTime("Terrain height map"); //======================= // Get entry elevation (need to reproject to DEM coordinate system first) // and sections entry elevations // _visualTopoService.ComputeFullCavityElevations(model, dataset, zFactor); // will add TerrainElevationAbove and entry elevations _visualTopoService.Create3DTriangulation(model); timeLog.LogTime("Cavity points elevation"); // Model origin GeoPoint axisOriginWorldSpace = model.EntryPoint.ReprojectTo(model.SRID, outputSRID) .CenterOnOrigin(bboxTerrainSpace); Vector3 axisOriginModelSpace = model.EntryPoint.AsVector3(); //======================= // Local transform function from model coordinates (relative to entry, in meters) // and global coordinates absolute in final 3D model space // IEnumerable <GeoPoint> TransformLine(IEnumerable <GeoPoint> line) { var newLine = line.Translate(model.EntryPoint) // Translate to entry (=> global topo coord space) .ReprojectTo(model.SRID, outputSRID) // Reproject to terrain coord space .CenterOnOrigin(bboxTerrainSpace) // Center on terrain space origin .CenterOnOrigin(axisOriginWorldSpace); return(newLine); }; //======================= // 3D model // var gltfModel = _gltfService.CreateNewModel(); // Add X/Y/Z axis on entry point var axis = _meshService.CreateAxis(); _gltfService.AddMesh(gltfModel, "Axis", axis, doubleSided: false); int i = 0; var triangulation = model.TriangulationFull3D.Clone() .Translate(axisOriginModelSpace) // already zScaled if zFactor > 1 .ReprojectTo(model.SRID, outputSRID) .CenterOnOrigin(bboxTerrainSpace) .CenterOnOrigin(axisOriginWorldSpace.AsVector3()); gltfModel = _gltfService.AddMesh(gltfModel, "Cavite3D", model.TriangulationFull3D, VectorsExtensions.CreateColor(0, 255, 0), doubleSided: false); if (GENERATE_LINE3D) { foreach (var line in model.Topology3D) // model.Topology3D is the graph of topo paths { // Add line to model gltfModel = _gltfService.AddLine(gltfModel , string.Concat("GPX", i++) // name of 3D node , TransformLine(line) // call transform function , color: VectorsExtensions.CreateColor(255, 0, 0, 128) , lineWidth); } } timeLog.LogTime("Topo 3D model"); //axis = _meshService.CreateAxis(10,100); //_gltfService.AddMesh(gltfModel, "Axis", axis, doubleSided: false); if (generateTopoOnlyModel) { // Uncomment this to save 3D model for topo only (without terrain) gltfModel.SaveGLB(string.Concat(Path.GetFileNameWithoutExtension(vtopoFile) + $"Z{zFactor}_TopoOnly.glb")); } // Reproject and center height map coordinates heightMap = heightMap.ReprojectTo(dataset.SRID, outputSRID) .CenterOnOrigin(bboxTerrainSpace) .ZScale(zFactor) .CenterOnOrigin(axisOriginWorldSpace); //.BakeCoordinates(); timeLog.LogTime("Height map transform"); //======================= // Textures // PBRTexture pbrTexture = null; if (imageryProvider != null) { TileRange tiles = _imageryService.DownloadTiles(bbox, imageryProvider, TEXTURE_TILES); string fileName = Path.Combine(outputDir, "Texture.jpg"); timeLog.LogTime("Imagery download"); Console.WriteLine("Construct texture..."); //TextureInfo texInfo = _imageryService.ConstructTexture(tiles, bbox, fileName, TextureImageFormat.image_jpeg); var topoTexture = model.Topology3D.SelectMany(l => l).Translate(model.EntryPoint).ReprojectTo(model.SRID, 4326); TextureInfo texInfo = _imageryService.ConstructTextureWithGpxTrack(tiles, bbox, fileName, TextureImageFormat.image_jpeg , topoTexture, false); pbrTexture = PBRTexture.Create(texInfo, null); timeLog.LogTime("Texture creation"); } // //======================= // Triangulate height map _logger.LogInformation($"Triangulating height map and generating 3D mesh..."); gltfModel = _gltfService.AddTerrainMesh(gltfModel, heightMap, pbrTexture); gltfModel.SaveGLB(string.Concat(Path.GetFileNameWithoutExtension(vtopoFile) + $"Z{zFactor}.glb")); timeLog.LogTime("3D model"); } catch (Exception ex) { _logger.LogError("Error :" + ex.Message); } }
private Location3DModelResponse Generate3DLocationModel(Location3DModelRequest request, Location3DModelSettings settings) { Location3DModelResponse response = new Location3DModelResponse(); try { bool imageryFailed = false; using (TimeSpanBlock timer = new TimeSpanBlock($"3D model {request.Id}", _logger)) { BoundingBox bbox = GetBoundingBoxAroundLocation(request.Latitude, request.Longitude, settings.SideSizeKm); HeightMap hMap = _elevationService.GetHeightMap(ref bbox, settings.Dataset); var transform = new ModelGenerationTransform(bbox, Reprojection.SRID_PROJECTED_MERCATOR, centerOnOrigin: true, settings.ZScale, centerOnZOrigin: true); response.Attributions.AddRange(settings.Attributions); // will be added to the model response.Attributions.Add(settings.Dataset.Attribution); // will be added to the model PBRTexture pbrTexture = null; if (settings.ImageryProvider != null) { response.Attributions.Add(settings.ImageryProvider.Attribution); // will be added to the model // Imagery TileRange tiles = _imageryService.ComputeBoundingBoxTileRange(bbox, settings.ImageryProvider, settings.MinTilesPerImage); Debug.Assert(tiles.Count < 400); tiles = _imageryService.DownloadTiles(tiles, settings.ImageryProvider); string fileName = Path.Combine(settings.OutputDirectory, $"{request.Id}_Texture.jpg"); TextureInfo texInfo = _imageryService.ConstructTexture(tiles, bbox, fileName, TextureImageFormat.image_jpeg); transform.BoundingBox = bbox; hMap = transform.TransformHeightMap(hMap); //var normalMap = _imageryService.GenerateNormalMap(hMap, settings.OutputDirectory, $"{request.Id}_normalmap.png"); pbrTexture = PBRTexture.Create(texInfo); } // Center on origin //hMap = hMap.CenterOnOrigin(out Matrix4x4 transform).BakeCoordinates(); //response.Origin = new GeoPoint(request.Latitude, request.Longitude).ReprojectTo(Reprojection.SRID_GEODETIC, Reprojection.SRID_PROJECTED_MERCATOR); ModelRoot model = _gltfService.CreateNewModel(); //======================= // Buildings if (settings.OsmBuildings) { model = _sampleOsmProcessor.Run(model, OsmLayer.Buildings, bbox, transform, computeElevations: true, settings.Dataset, settings.DownloadMissingFiles); } if (settings.GenerateTIN) { model = AddTINMesh(model, hMap, 2d, _gltfService, pbrTexture, Reprojection.SRID_PROJECTED_MERCATOR); } else { model = _gltfService.AddTerrainMesh(model, hMap, pbrTexture); } model.Asset.Generator = "DEM Net Elevation API with SharpGLTF"; //model.TryUseExtrasAsList(true).AddRange(response.Attributions); model.SaveGLB(Path.Combine(settings.OutputDirectory, string.Concat(imageryFailed ? "imageryFailed_" : "", settings.ModelFileNameGenerator(settings, request)))); // cleanup //if (pbrTexture != null) //{ // if (pbrTexture.NormalTexture != null) File.Delete(pbrTexture.NormalTexture.FilePath); // File.Delete(pbrTexture.BaseColorTexture.FilePath); //} response.Elapsed = timer.Elapsed; response.NumTiles = pbrTexture.BaseColorTexture.TileCount; } } catch (Exception) { throw; } return(response); }