PDA

View Full Version : MR material to shader & coding syntax


-Vormav-
06-13-2005, 08:16 PM
For starters, I have a (hopefully) simple question on C++ coding syntax. Basically, I'm trying to figure out how to change the variable name I'm trying to access based on some text or integer value... Kinda hard to explain, so let me give an example:

string text1, text2, text3, text4, text5;
int i;
for(i = 1; i <=5; i++) {
}

Now let's say that within my for loop, I want to access the respective text string, depending on what value of i I'm at. Yes, I am well aware of arrays. I'm just curious to see if this can be done in this language.
In php, it might have looked something like this:

string $text1, $text2, $text3, $text4, $text5, $thevar;
int $i;
for($i = 1; $i<=5; i++) {
$thevar = "text" . $i;
echo ${$thevar};
}

So, is there any similar syntax rule for c++, for passing a string value as the variable name that you're trying to access?


And the second question is related to MR (figured I might as well just throw both questions into one topic). Basically, I'm trying to find out what all is needed to be able to pass material output to a shader, to the effect of something along Max's "material to shader" map. It's easy enough to pass output from a shader to my shader - it's just passed to the shader as an miColor variable, through which you can easily access the rgba values all separately. However, to pass material values to a shader, you use miTag vars(unless I've completely misread the documentation).
So basically, once I have passed a material to my shader as some miTag, how do I go about accessing the rgba output of that material within my shader? I don't exactly understand how the material is being stored in the miTag.

gga
06-13-2005, 09:53 PM
1) No, albeit you can do something similar with array pointers.

string text1,text2,text3,text4,text5;
string* ptr[] = { &text1, &text2, &text3, &text4, &text5 };
for (i =0; i < 5; ++i) {
const string& current = *(ptr[i]);
// ... do something with current
}


Obviously, for this simple example, you might as well just use a single string array, instead of dealing with pointers.

2) You misread the docs. There is no difference between shader/material in mray. Shaders can have any output. Usually this is an miColor, but it can also be a complex struct in mray (maya materials do that, for example). You can hook the whole struct to another struct input or you can individually hook the members of the struct individually.
If you attach a shader as an miTag (which may be a 3dmax convention), this is basically the equivalent of a C pointer to the shader. This is usually only done in volume shaders to allow volume shaders use shading networks of material shaders.
You can then invoke the shader using any of the mi_call_* like mi_call_shader_x functions. The output value (be it an miColor, struct or what not) of the shader is returned as a pointer in that function.

-Vormav-
06-14-2005, 12:08 AM
1) No, albeit you can do something similar with array pointers.

string text1,text2,text3,text4,text5;
string* ptr[] = { &text1, &text2, &text3, &text4, &text5 };
for (i =0; i < 5; ++i) {
const string& current = *(ptr[i]);
// ... do something with current
}


Obviously, for this simple example, you might as well just use a single string array, instead of dealing with pointers.
Thanks. I don't have the greatest understanding of working with pointers yet, but I kinda figured it would come down to something like this.
On a similar note, though, can you form arrays of miColor variables, or would you have to place the different elements of the miColor (rgba) all into separate arrays? I'm not entirely sure if an "miColor *colors[x];" statement would be legal in MR.



2) You misread the docs. There is no difference between shader/material in mray. Shaders can have any output. Usually this is an miColor, but it can also be a complex struct in mray (maya materials do that, for example). You can hook the whole struct to another struct input or you can individually hook the members of the struct individually.
If you attach a shader as an miTag (which may be a 3dmax convention), this is basically the equivalent of a C pointer to the shader. This is usually only done in volume shaders to allow volume shaders use shading networks of material shaders.
You can then invoke the shader using any of the mi_call_* like mi_call_shader_x functions. The output value (be it an miColor, struct or what not) of the shader is returned as a pointer in that function.
The problem I'm having is that I've been trying to develop a base material with color slots to which you can automatically place other materials into. I suppose that half of the problem is that I'm working with the 3dsmax mental ray connection, but Max will only allow me to place materials (the standard DGS 'Material(physics_phen)' and 'mental ray material', for example) in my shader's slots if I've declared these slots within the .mi file as materials instead of colors. They've still been declared in my shader source as miColor. And it seems that when the mi file has them declared as materials instead of colors (regardless of whether the material's output is technically miColor), the colors don't transfer over to the shader. I don't get any errors, but colors certainly aren't transferring. I just kind of figured that there was an extra step needed to be able to access those color values? :blush: I mean, considering that I'll need to take some of Max's default materials into account, which are going to rely on the 'material to shader' connection to work with MR, I'll probably need to end up writing a phenomenon that uses 'material to shader' to get around the problem, but it'd be nice to figure out why some of the default materials that SHOULD have their colors transferring aren't working out.

gga
06-17-2005, 07:53 AM
Thanks. I don't have the greatest understanding of working with pointers yet, but I kinda figured it would come down to something like this.
On a similar note, though, can you form arrays of miColor variables, or would you have to place the different elements of the miColor (rgba) all into separate arrays? I'm not entirely sure if an "miColor *colors[x];" statement would be legal in MR..

Somewhat. If the [x] is an actual number, like, say, 10, then yes, it is a legal statement. If it is a variable, it isn't. That is:

miColor* colors[10];

That means an array of 10 pointers to ten colors. By default the pointers remain undefined.
However, if what you want is just an array of 10 colors, the syntax is then just:

miColor colors[10];

Finally, if you want a varying number of elements in the array, using a variable, unfortunately C/C++ does not offer a nice syntax for this. For doing that, you need to allocate and deallocate memory manually. In mental ray, that is usually done using the mi_mem_allocate and mi_mem_release functions, albeit you can also just use C++ new operator (which I recommend you use instead, as the syntax is simpler). Thus, you would do:


int n = 20; // set this to whatever, dynamically or with a formula if you want.
miColor* colors = new miColor[n];

// you can then refer to colors[0] or colors[3] or colors[n-1] here to store a color or
// operate on it.
// Indexing beyond the array (ie. n or higher) and you can crash the program


// At the end, somewhere in your code you need to deallocate the memory.
// You do this with:
delete [] colors;


If you want to allocate a varying number of pointers, the allocating/deallocating syntax is then:

miColor** colors = new miColor*[n];
// and then each element (the pointer) also has to probably be allocated, like:
for ( int i = 0; i < n; ++i)
{
colors[i] = new miColor;
}

// ...deallocate the stuff...
for ( int i = 0; i < n; ++i)
{
delete colors[i];
}
delete [] colors;


--------
Overall, this is explained in more detail in most C++ books. Pointers and memory allocation is what makes C and C++ so powerful, but also the source of most headaches (and bugs) in most code.


The problem I'm having is that I've been trying to develop a base material with color slots to which you can automatically place other materials into. I suppose that half of the problem is that I'm working with the 3dsmax mental ray connection, but Max will only allow me to place materials (the standard DGS 'Material(physics_phen)' and 'mental ray material', for example) in my shader's slots if I've declared these slots within the .mi file as materials instead of colors. They've still been declared in my shader source as miColor. And it seems that when the mi file has them declared as materials instead of colors (regardless of whether the material's output is technically miColor), the colors don't transfer over to the shader. I don't get any errors, but colors certainly aren't transferring. I just kind of figured that there was an extra step needed to be able to access those color values? :blush: I mean, considering that I'll need to take some of Max's default materials into account, which are going to rely on the 'material to shader' connection to work with MR, I'll probably need to end up writing a phenomenon that uses 'material to shader' to get around the problem, but it'd be nice to figure out why some of the default materials that SHOULD have their colors transferring aren't working out.

Yes, that seems like a 3dmax limitation. In the .mi file, there should usually be an apply statement that specifies how a shader can be used. For example, something like:

declare shader
color "myshader" (
color "param"
)
apply material, texture
version 1
end declare

The apply statement can be set to multiple things. It is likely that the 3dmax connection only allows hooking shaders that have "apply texture" set in their definition. You might want to try if the 3dmax stuff is smart enough to parse a double apply statement like the one above and thus then modify the physics_phen to follow that.
If not, then yes, what you will need to do in your shader is use the tag of that material parameter and call it using mi_call_shader_x.

CGTalk Moderation
06-17-2005, 07:53 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.