SOLVED Larger BaseMaterial Preview Renders

Is it possible to create a render of a material at a higher resolution? Can I make a call that would allow me to get an image at 512x512 from BaseMaterial->GetPreview()?

Also you need a new R25 tag so we can tag our posts accordingly.

hi,

there's also RenderMaterialPreview that allow you to do this. Mark as private but still usable.

Progress hook can be defined to the basebitmap, BASEBITMAP_DATA_PROGRESSHOOK and BASEBITMAP_DATA_PROGRESSHOOK_CTX must be defined.

BaseMaterial* mat = doc->GetFirstMaterial();
if (mat)
{
  BaseMaterial* clone = (BaseMaterial*)mat->GetClone(COPYFLAGS::NO_HIERARCHY, nullptr); // copy without children
  if (clone)
  {
    finally
    {
      BaseMaterial::Free(clone);
    };

    BaseBitmap* bm = BaseBitmap::Alloc();
    if (bm)
    {
      if (bm->Init(1024, 1024) == IMAGERESULT::OK) // initialize preview bitmap with the preferred size
      {

        RENDERRESULT render_result = RENDERRESULT::PROJECTNOTFOUND;
      

        render_result = RenderMaterialPreview(doc->GetDocumentPath(), clone, mat, nullptr, bm, nullptr, 0, RENDER_PREVIEW_USE_BMP_SIZE);
        
        if ((render_result != RENDERRESULT::OK) && (render_result != RENDERRESULT::SAVINGFAILED)) // not ok and not only missing texture?
          BaseBitmap::Free(bm);
        else
          ShowBitmap(bm);
      }
      else
      {
        BaseBitmap::Free(bm);
      }
    }
  }
}

Hope that helped.
Cheers,
Manuel

I think I should be able to make a direct call to the Material using Message() with the following data filled out.

MatPreviewGenerateImage* image = (MatPreviewGenerateImage* )data;

I am going to try this now but if this is not recommended then please let me know. This may require me to make calls to other "MATPREVIEW_XXXX" messages as well, since ideally I want to use the default scene supplied by the renderer itself and not have to pass in my own document.

hi,

there's also RenderMaterialPreview that allow you to do this. Mark as private but still usable.

Progress hook can be defined to the basebitmap, BASEBITMAP_DATA_PROGRESSHOOK and BASEBITMAP_DATA_PROGRESSHOOK_CTX must be defined.

BaseMaterial* mat = doc->GetFirstMaterial();
if (mat)
{
  BaseMaterial* clone = (BaseMaterial*)mat->GetClone(COPYFLAGS::NO_HIERARCHY, nullptr); // copy without children
  if (clone)
  {
    finally
    {
      BaseMaterial::Free(clone);
    };

    BaseBitmap* bm = BaseBitmap::Alloc();
    if (bm)
    {
      if (bm->Init(1024, 1024) == IMAGERESULT::OK) // initialize preview bitmap with the preferred size
      {

        RENDERRESULT render_result = RENDERRESULT::PROJECTNOTFOUND;
      

        render_result = RenderMaterialPreview(doc->GetDocumentPath(), clone, mat, nullptr, bm, nullptr, 0, RENDER_PREVIEW_USE_BMP_SIZE);
        
        if ((render_result != RENDERRESULT::OK) && (render_result != RENDERRESULT::SAVINGFAILED)) // not ok and not only missing texture?
          BaseBitmap::Free(bm);
        else
          ShowBitmap(bm);
      }
      else
      {
        BaseBitmap::Free(bm);
      }
    }
  }
}

Hope that helped.
Cheers,
Manuel

That is exactly what I am looking for @m_magalhaes , thanks! I will test this later today. Although it looks like I need to pass in a document path and am wondering how I could possibly use whatever internal document that the renderers are using. Since in cases like Octane (and now I believe Redshift) they do not ship with any "library/materialpreview" c4d files at all. I will try passing an empty filename and see what happens.

@m_magalhaes said in Larger BaseMaterial Preview Renders:

Progress hook can be defined to the basebitmap, BASEBITMAP_DATA_PROGRESSHOOK and BASEBITMAP_DATA_PROGRESSHOOK_CTX must be defined.

Would you be able to show me exactly how these should be used? And what the Function declaration passed to BASEBITMAP_DATA_PROGRESSHOOK should look like?

Thanks!
Kent

Hi,

The function looks like this. As you can see the progressRef and progressIndex are passed arguments. While BASEBITMAP_DATA_PROGRESSHOOK looks like you just need to pass a function (here a lambda), i still don't know what the context is good for. Sorry i don't have enough time to investigate more and give you a better answer. I will try to find more time this week.

Be aware that this is marked as Private and "hack". So, it could change in the futur.

static BaseBitmap* GenerateBaseMaterialPreviewBitmap(BaseDocument* doc, Int32 w, Int32 h, const MediaSessionProgressRef& progressRef, Int progressIndex)
{
	iferr_scope_handler
	{
		return nullptr;
	};

	BaseBitmap* bm = nullptr;

	if (doc)
	{
		BaseMaterial* mat;

		mat = doc->GetFirstMaterial();
		if (mat)
		{
			BaseMaterial* clone = (BaseMaterial*)mat->GetClone(COPYFLAGS::NO_HIERARCHY, nullptr); // copy without children
			if (clone)
			{
				finally
				{
					BaseMaterial::Free(clone);
				};

				mat->Remove();
				finally
				{
					BaseMaterial::Free(mat);
				};

				bm = BaseBitmap::Alloc();
				if (bm)
				{
					if (bm->Init(w, h) == IMAGERESULT::OK) // initialize preview bitmap with the preferred size
					{
						RENDERRESULT render_result = RENDERRESULT::PROJECTNOTFOUND;

						struct ProgressHelper
						{
							MediaSessionProgressRef progressRef;
							Int											progressIndex = -1;
						};

						ProgressHelper progressHelper = {progressRef, progressIndex};

						auto progress = [](Float p, RENDERPROGRESSTYPE progress_type, void* context) -> void
						{
							ProgressHelper* h = (ProgressHelper*)context;
							if (h && progress_type == RENDERPROGRESSTYPE::DURINGRENDERING)
							{
								h->progressRef.SetProgressAndCheckBreak(h->progressIndex, p) iferr_ignore();
							}
						};

						ProgressHook* prog = progress;
						bm->SetData(BASEBITMAP_DATA_PROGRESSHOOK, GeData((void*)prog, VOIDVALUE));
						bm->SetData(BASEBITMAP_DATA_PROGRESSHOOK_CTX, GeData((void*)&progressHelper, VOIDVALUE));

						render_result = RenderMaterialPreview(doc->GetDocumentPath(), clone, mat, nullptr, bm, nullptr, 0, RENDER_PREVIEW_USE_BMP_SIZE | RENDER_PREVIEW_USE_CURRENT_QUEUE);

						if ((render_result != RENDERRESULT::OK) && (render_result != RENDERRESULT::SAVINGFAILED)) // not ok and not only missing texture?
							BaseBitmap::Free(bm);
					}
					else
					{
						BaseBitmap::Free(bm);
					}
				}
			}
		}
	}

	return bm;
}

@m_magalhaes said in Larger BaseMaterial Preview Renders:

The function looks like this. As you can see the progressRef and progressIndex are passed arguments. While BASEBITMAP_DATA_PROGRESSHOOK looks like you just need to pass a function (here a lambda), i still don't know what the context is good for. Sorry i don't have enough time to investigate more and give you a better answer. I will try to find more time this week.

Be aware that this is marked as Private and "hack". So, it could change in the futur.

Thanks. Looks like I was passing in the ProgressHook correctly but still for some reason I do not get any callbacks to it. Perhaps it is because I am not passing in an actual document filename, not sure. But I am still getting the correct renders back even though my ProgressHook does not get called, just would have been nice to see the progress on larger images.

The context in this situation would have been great for me to let me set the progress in my progress dialog. So that is what it is useful for.

It is fine that it is private and may change, I am only using this for internal tools to generate images, IE not a customer facing tool.

Thanks for the help.