Notifications
Clear all

[Closed] Grabbing The Material Preview

Hey All,

I just wrote a new post detailing my method for capturing the preview from the material editor. I thought I’d share as it’s something I’ve wanted to do for years but have not been able to figure out until now. What it does is allow high-res thumbnails to be generated to file from the material editor window. It’s also disgustingly hacky, so avert your eyes if you are of a nervous scripting disposition. :surprised

I wrote it so that I can begin writing a shader database system for work, but since I wrote this part in my spare time, I can share it with you peeps. Hopefully it will be useful for any similar material based asset tracking scripts you might want to write.

http://lonerobot.net/?p=1918

46 Replies

I’ve got another slightly hacky way of doing it.

Install Kees’s Helium plugin, and you can use the function to get the shader ball as a bitmap value. It’s not quite as good as the real preview but it’s a lot less lines of code than yours

Wow, great! I don’t know why Autodesk doesn’t give access to this part directly. It would be really great to have the option to have our own material preview window inside our scripts/plugins…

Thank you!

Ha, that’s because someone else did the hard work for you, Dave

Good to know that helium can do this too though – thanks.

this will do it

//********************************************************************************************
  // MtlPreviewToBitmap
  
  def_visible_primitive(MtlPreviewToBitmap, "MtlPreviewToBitmap");
  
  Value* MtlPreviewToBitmap_cf(Value** arg_list, int count)
{
	check_arg_count(MtlPreviewToBitmap, 2, count);

	MtlBase* mb = arg_list[0]->to_mtlbase();
	int sz = arg_list[1]->to_int();

	PStamp *ps = mb->CreatePStamp(sz,1);
	if(ps)
	{
		int d = PSDIM(sz);
		int scanw = ByteWidth(d);
		int nb = scanw*d;

		UBYTE *buf = new UBYTE[nb + sizeof(BITMAPINFOHEADER)];
		if(!buf)
			 &undefined;

// get the image data

		ps->GetImage(&buf[sizeof(BITMAPINFOHEADER)]);
		
// and create the header info		
		
		BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)buf;
		bih->biSize = sizeof(BITMAPINFOHEADER);
		bih->biWidth = d; 
		bih->biHeight = d; 
		bih->biPlanes = 1; 
		bih->biBitCount = 24;
		bih->biCompression = BI_RGB;
		bih->biSizeImage = 0;
		
		Bitmap *map = TheManager->Create((PBITMAPINFO)buf);
		delete [] buf;

		if(map)
		{
			one_typed_value_local(MAXBitMap* mbm);
			vl.mbm = new MAXBitMap();
			vl.mbm->bi.CopyImageInfo(&map->Storage()->bi);
			vl.mbm->bi.SetFirstFrame(0);
			vl.mbm->bi.SetLastFrame(0);
			vl.mbm->bi.SetName("");
			vl.mbm->bi.SetDevice("");
			if(vl.mbm->bi.Type() > BMM_TRUE_64)
				vl.mbm->bi.SetType(BMM_TRUE_64);
			vl.mbm->bm = map;
			return_value(vl.mbm);
		}
	}
	return &undefined;
}

sz = 0 -> 3232
sz = 1-> 88
88
sz > 1 -> 24*24

display (MtlPreviewToBitmap (getMeditMaterial 1) 0)	

edited to remove memcpy

Is it possible to do the other way around?
Meaning – sending in a custom bitmap as a ‘material preview’?

The reason why I ask is because in a exporter I’ve been working on for a long time has it’s own ‘preview tab’ in the material, which then shows the external rendered preview image.
It would be very nice to send that image back into the material slot directly instead.

The exporter calls on a external renderer, that’s why it works with the current setup – we render a preview scene externally, save to a file named the same as material, then when you open that material in the editor it just shows that image.

yes but I think it would need a custom mtl plugin which overides the mtlbase pstamp routines.

it might be possible without the use of a custom mtl, as the PStamp object has a setimage method.

very nice! could you post it on “useful mxs extensions” thread, please?

Thank you guys for sharing this.

@Pete:
There is a action that opens the preview (“Magnify”) window. Perhaps you may want to check it out and see if that could replace the double click hack?

actionMan.executeAction 2 "40296"
3 Replies
(@lonerobot)
Joined: 11 months ago

Posts: 0

Can anyone verify if this works? I’ve tried this call in 2013, 2014 and 2015 and it returns false with no material window magnified.

I’d +1 for a SDK heads up if anyone was kind enough to do it.

(@lonerobot)
Joined: 11 months ago

Posts: 0

Ack, my bad – its just a focus issue, you need to call MatEditor.Open() before you run the actionman item.

(@denist)
Joined: 11 months ago

Posts: 0

it’s a Material Editor action. it means the editor has to be in focus when you execute this action.

edited

oops. you already answered your question

Hi Chaps,

thanks for all your input.

Klunk – For those of us not clear about how to approach the SDK, is this method easily usable? My limit is that I’ve built an SDK maxscript extension before, is this a case of adding this and re-compiling? Many thanks for your solution

PolyTools3d – Thanks a million, anything to remove some of my hacky steps is awesome, I’ll change the code and update the article, I’m sure that will work much better.

Page 1 / 4