[Closed] Max Maps to Mental Ray
Well now everything works on the mental ray’s side, I got distortion working
However the max translation part aint looking very good. No matter what I do it always crashes mental ray which then after some time crashes max. Even with TranslateParameters() commented out (so it doesn’t do anything) it crashes. I’ve copied all the stuff nearly directly from mrTwoSidedShader.
Unfortunately my shader is so damn complicated that I’m not sure what part of it is crashing mental ray since it crashed mr even without the mr support stuff added…
Both Noise and Wood maps crash MR but Distortion and Tile just make mental ray give error that they aren’t supported. (This is without any mr code) The only difference I can think of they have is that Noise and Wood got the custom curve control. Perhaps I’ll try to disable that and see what happens tomorrow.
I’m not sure you can claim that.
The list of ‘worst documented features in the SDK’ is pretty huge.
Okey I’ve gotten the Distortion maps translation to work fine. However I’m running into problem with the mental ray version of the map. Distortion the world/object spaces is easy but UV causes some problems.
How would I distort the submaps UV space in mental ray? I tried something like this:
coords.x = dist_dir.x * ((float)*mi_eval_scalar(¶ms->distortion_str));
coords.y = dist_dir.y * ((float)*mi_eval_scalar(¶ms->distortion_str));
coords.z = dist_dir.z * ((float)*mi_eval_scalar(¶ms->distortion_str));
vectorAdd(&state->tex, &coords); // A+B
state->tex_list[0] = state->tex;
vectorAdd(&state->point, &coords);
However it just creates some random noise, no matter how small vector I add to the tex value.
The shader should distort ALL texture coordinate spaces by adding the “coords” vector to them. Any ideas how I would achieve this? Adding “coords” to “point” does the trick for obj/world spaces.
EDIT:
As I suspected the ICurveCtl crashes mental ray. I wonder why?
Where are you gettings state->tex value from?
You are adding to it – does it have a meaninful value going in?
I’d do something like
vectorAdd(&state->tex_list[0], &coords);
…does that work?
When? At translation time? And how?
/Z
I just can’t figure out why curvecontrol crashes mr, probably while trying to translate it doesn’t recognize it and halts. There are just dozen different possibilities where it could go wrong and its impossible to test them individually so I guess I’ve hit dead end here.
If anybody has ideas why mental ray doesn’t like ICurveCtl I’d be happy to hear them, otherwise this project is pretty much buried.
Thanks for help everybody, at least now I know a lot more about mental ray.
Maybe you can head over to : http://dl3d.free.fr/phpBB2/index.php
And try it there, David Lanier seems to have programmed a few shaders…
Can’t help with much else…
Goodluck,
-Johan
vectorAdd(&state->tex_list[0], &coords); works a lot better thanks. I though state->tex would already have some value which doesn’t seem to be the case. Still not exact match with scanline but I think I’ll get there with some tinkering.
Yeah well about the curvecontrol. the stuff that makes that curve work is spread all over the place (1000s lines of code). You can get the source code for whole stuff here: http://www.niksula.cs.hut.fi/~jylilamm/BerconMaps/BerconMapsSource_25_7_2008.rar
If you really wanna look into it check these:
ParamDlg* BerconNoise::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
BerconDlg.h
class BerconCurveDlgProcNOISE : public ParamMap2UserDlgProc
void BerconNoise::Reset()
I’m pretty sure its one of those four thing places which crashes.
It doesn’t have any mr stuff since thats not the problem. Disabling the curve control properly gives error that the maps aint mental ray compatible when trying to render, otherwise they crash when displayed in medit or rendering. Both Wood and Noise maps have the curve control so they crash but Distortion and Tile don’t and they properly display the warning.
Here are some reasons that might crash it:
- It reads the refrecene using GetReference() and doesn’t recognize ICurveCtl.
- It doesn’t like my custom ParamDlg wrapper which is required to ICurveCtl properly update its reference when switching between two copies of the map.
- It doesn’t like the update callbacks (BerconCurveDlgProcNOISE)
- It doesn’t like curve->RegisterResourceMaker(new BerconRefMaker((ResourceMakerCallback *)this));
Well suprise suprise.
RefTargetHandle BerconNoise::GetReference(int i) {
switch (i) {
...
case CURVE_REF: return NULL;//return curve;
...
}
}
That makes it work in mental ray, so when max translates the scene to mental ray it goes through all references using that function, when it runs into the ICurveCtl it doesn’t recognize and crashes.
However returning NULL there probably brings a lot of issues with other things, so how would I make it feed the NULL only when the mental ray translation is asking for it? I guess it would something like (renderer == mental ray && rendering == true)
mental ray shouldn’t do anything with it because I was planning on doing manual translation for it anyway…
Any ideas?
If anybody is still reading this, how does UVW coordinates go in mental ray? If I’m using say UVW channel 3 in max, how do I access it (or distort it) in mental ray? Is it tex_list[2] or 3? How do I know how many texture coordinate spaces are stored in tex_list?
In principle yes, but unfortunately, max tries to be smart and compact the channel data.
To know which channel goes where, you would need to look up the object data struct, which looks like this in the .mi file:
declare data
“max_ObjectData” (
vector “bvmin”,
vector “bvmax”,
array integer “mapchannels”,
data “particleData”
)
version 7
end declare
This means you need to declare a C++ struct something like this:
struct object_data {
miVector bvmin;
miVector bvmax;
int mapchannels_i;
int mapchannels_n;
miInteger mapchannels[1];
miTag data;
};
Then you aqquire the object data from your shader with something like;
object_data *get_object_data(miState *state)
{
miTag obj_data_tag;
if(mi_query(miQ_GEO_DATA, state, miNULLTAG, &obj_data_tag)) {
data *the_data;
if(mi_query(miQ_DATA_PARAM, NULL, obj_data_tag, &the_data)) {
return theData;
}
}
return NULL;
}
Then you need to dereference this array something like that
object_date *data = get_object_data(state);
int texture_slot = data->mapchannels[data->mapchannels_i + mapchannel;
Then access
state->tex_list[texture_slot];
Warning: all of the above typed in by hand, probably typo-filled and wrong, but should give you the right idea.
/Z