Created the data to allow thumbnails to be cached by mesh id
Estimated memory size for mesh Mesh Render Id Get long hash for color default constructor for face and vertex issue: MatterHackers/MCCentral#3519 Improve thumbnail generation for complicated models
This commit is contained in:
parent
1b4a617da2
commit
c1588fcd04
7 changed files with 121 additions and 97 deletions
|
|
@ -48,9 +48,9 @@ namespace MatterHackers.MatterControl
|
|||
private static readonly bool Is32Bit = IntPtr.Size == 4;
|
||||
|
||||
// For 32 bit max size to ray trace is 8 MB mesh for 64 bit the max size is 40 MB.
|
||||
private long MaxFileSizeForTracing => Is32Bit ? 8 * 1000 * 1000 : 40 * 1000 * 1000;
|
||||
private long MaxFileSizeForTracing => Is32Bit ? 8 * 1000 * 1000 : 16 * 1000 * 1000;
|
||||
|
||||
private long MaxFileSizeForThumbnail => Is32Bit ? 16 * 1000 * 1000 : 100 * 1000 * 1000;
|
||||
private long MaxFileSizeForThumbnail => Is32Bit ? 16 * 1000 * 1000 : 32 * 1000 * 1000;
|
||||
|
||||
public Task<IObject3D> CreateItem(ILibraryItem item, Action<double, string> progressReporter)
|
||||
{
|
||||
|
|
@ -101,12 +101,12 @@ namespace MatterHackers.MatterControl
|
|||
}
|
||||
|
||||
|
||||
public async Task GetThumbnail(ILibraryItem item, int width, int height, ThumbnailSetter imageCallback)
|
||||
public async Task GetThumbnail(ILibraryItem libraryItem, int width, int height, ThumbnailSetter imageCallback)
|
||||
{
|
||||
IObject3D object3D = null;
|
||||
|
||||
long fileSize = 0;
|
||||
if (item is ILibraryAssetStream contentModel
|
||||
if (libraryItem is ILibraryAssetStream contentModel
|
||||
// Only load the stream if it's available - prevents download of Internet content simply for thumbnails
|
||||
&& contentModel.LocalContentExists
|
||||
&& contentModel.FileSize < MaxFileSizeForThumbnail)
|
||||
|
|
@ -115,17 +115,65 @@ namespace MatterHackers.MatterControl
|
|||
// TODO: Wire up limits for thumbnail generation. If content is too big, return null allowing the thumbnail to fall back to content default
|
||||
object3D = await contentModel.CreateContent();
|
||||
}
|
||||
else if (item is ILibraryObject3D)
|
||||
else if (libraryItem is ILibraryObject3D)
|
||||
{
|
||||
object3D = await (item as ILibraryObject3D)?.GetObject3D(null);
|
||||
object3D = await (libraryItem as ILibraryObject3D)?.GetObject3D(null);
|
||||
}
|
||||
|
||||
var thumbnail = GetThumbnail(object3D, width, height, forceOrthographic: fileSize > MaxFileSizeForTracing);
|
||||
string thumbnailId = libraryItem.ID;
|
||||
if (libraryItem is IThumbnail thumbnailKey)
|
||||
{
|
||||
thumbnailId = thumbnailKey.ThumbnailKey;
|
||||
}
|
||||
|
||||
var thumbnail = GetThumbnail(object3D, thumbnailId, width, height, false);
|
||||
imageCallback?.Invoke(thumbnail, true);
|
||||
}
|
||||
|
||||
public ImageBuffer GetThumbnail(IObject3D item, string thumbnailId, int width, int height, bool onlyUseCache)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return DefaultImage.CreateScaledImage(width, height);
|
||||
}
|
||||
|
||||
var image = LoadCachedImage(thumbnailId, width, height);
|
||||
|
||||
if(image != null)
|
||||
{
|
||||
return image;
|
||||
}
|
||||
|
||||
if(onlyUseCache)
|
||||
{
|
||||
return DefaultImage.CreateScaledImage(width, height);
|
||||
}
|
||||
|
||||
int estimatedMemorySize = item.EstimatedMemory();
|
||||
if (estimatedMemorySize > MaxFileSizeForThumbnail)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
bool forceOrthographic = false;
|
||||
if (estimatedMemorySize > MaxFileSizeForTracing)
|
||||
{
|
||||
forceOrthographic = true;
|
||||
}
|
||||
|
||||
bool RenderOrthographic = (forceOrthographic) ? true : UserSettings.Instance.ThumbnailRenderingMode == "orthographic";
|
||||
|
||||
var thumbnail = ThumbnailEngine.Generate(
|
||||
item,
|
||||
RenderOrthographic ? RenderType.ORTHOGROPHIC : RenderType.RAY_TRACE,
|
||||
width,
|
||||
height,
|
||||
allowMultiThreading: !ApplicationController.Instance.ActivePrinter.Connection.PrinterIsPrinting);
|
||||
|
||||
if (thumbnail != null)
|
||||
{
|
||||
// Cache at requested size
|
||||
string cachePath = ApplicationController.Instance.ThumbnailCachePath(item, width, height);
|
||||
string cachePath = ApplicationController.Instance.ThumbnailCachePath(thumbnailId, width, height);
|
||||
|
||||
// TODO: Lookup best large image and downscale if required
|
||||
if (false)
|
||||
|
|
@ -134,40 +182,61 @@ namespace MatterHackers.MatterControl
|
|||
}
|
||||
|
||||
AggContext.ImageIO.SaveImageData(cachePath, thumbnail);
|
||||
|
||||
if (ApplicationController.Instance.Library.ActiveContainer is ILibraryWritableContainer writableContainer)
|
||||
var meshCachePath = ApplicationController.Instance.ThumbnailCachePath(item.MeshRenderId().ToString(), width, height);
|
||||
if (meshCachePath != cachePath)
|
||||
{
|
||||
writableContainer.SetThumbnail(item, thumbnail.Width, thumbnail.Height, thumbnail);
|
||||
// also save it to the mesh cache
|
||||
AggContext.ImageIO.SaveImageData(meshCachePath, thumbnail);
|
||||
}
|
||||
}
|
||||
|
||||
return thumbnail ?? DefaultImage.CreateScaledImage(width, height);
|
||||
}
|
||||
|
||||
internal static ImageBuffer LoadCachedImage(string cacheId, int width, int height)
|
||||
{
|
||||
ImageBuffer cachedItem = LoadImage(ApplicationController.Instance.ThumbnailCachePath(cacheId, width, height));
|
||||
if (cachedItem != null)
|
||||
{
|
||||
return cachedItem;
|
||||
}
|
||||
|
||||
if (width < 100
|
||||
&& height < 100)
|
||||
{
|
||||
// check for a 100x100 image
|
||||
var cachedAt100x100 = LoadImage(ApplicationController.Instance.ThumbnailCachePath(cacheId, 100, 100));
|
||||
if (cachedAt100x100 != null)
|
||||
{
|
||||
return cachedAt100x100.CreateScaledImage(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ImageBuffer LoadImage(string filePath)
|
||||
{
|
||||
ImageBuffer thumbnail = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
var temp = new ImageBuffer();
|
||||
AggContext.ImageIO.LoadImageData(filePath, temp);
|
||||
temp.SetRecieveBlender(new BlenderPreMultBGRA());
|
||||
|
||||
thumbnail = temp;
|
||||
}
|
||||
|
||||
imageCallback(thumbnail, raytracedImage: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If thumbnail generation was aborted or failed, return the default icon for this content type
|
||||
imageCallback(DefaultImage, raytracedImage: true);
|
||||
return thumbnail;
|
||||
}
|
||||
catch { } // Suppress exceptions, return null on any errors
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
public ImageBuffer GetThumbnail(IObject3D object3D, int width, int height, bool forceOrthographic)
|
||||
{
|
||||
if (object3D == null)
|
||||
{
|
||||
return DefaultImage;
|
||||
}
|
||||
|
||||
bool RenderOrthographic = (forceOrthographic) ? true : UserSettings.Instance.ThumbnailRenderingMode == "orthographic";
|
||||
|
||||
var thumbnail = ThumbnailEngine.Generate(
|
||||
object3D,
|
||||
RenderOrthographic ? RenderType.ORTHOGROPHIC : RenderType.RAY_TRACE,
|
||||
width,
|
||||
height,
|
||||
allowMultiThreading: !ApplicationController.Instance.ActivePrinter.Connection.PrinterIsPrinting);
|
||||
|
||||
|
||||
return thumbnail ?? DefaultImage;
|
||||
}
|
||||
public ImageBuffer DefaultImage => AggContext.StaticData.LoadIcon("mesh.png");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue