HomeKontakt und Impressum
ProjektePluginsTutorials

// Thomas Helzle 2005
// Feel free to use this code, but there is NO warranty that it is correct!
// Please tell me about any errors you may find!

//First declare some variables:

double Dot = 0.0;
miMatrix* GoalMatrixP;
miVector GoalDirection = {0.0, 0.0, 0.0};

// Next retrieve the 3 parts of the Goal object reference from the SPDL:
// The first is an offset into an array of data, the next is the number of
// objects in the array and the last is the array of object-tags itself:

miInteger i_objects = in_pParams->i_objects;
miInteger n_objects = in_pParams->n_objects;
miTag *objects = &in_pParams->objects[i_objects];

// next we retrieve the global coordinates of the Goal object with mi_query.
// Since I know in this case that there is only one Goal, I hardcoded it to
// "objects[0]" instead of a loop over n_objects (I use an object picker
// in "single mode") but be careful if you work with multiple objects!

mi_query(miQ_INST_LOCAL_TO_GLOBAL, NULL, objects[0], &GoalMatrixP)

// Now we have the matrix which contains the coordinates, let's extract
// the position values. If you imagine the 16 values of the matrix as
// 4 rows and 4 columns from left to right and top to bottom, the
// lowest row is the position where only the first three values are used.
// The array starts at [0], so [12]-[14] are our x, y and z values:

GoalDirection.x = (*GoalMatrixP)[12];
GoalDirection.y = (*GoalMatrixP)[13];
GoalDirection.z = (*GoalMatrixP)[14];

// One of my problems was that weird "pointer to an array" and setting
// the parentheses correctly. First I did left them out but then the
// brackets take precedence over the "*".
// Now convert that world position to "internal space":

mi_point_from_world(state, &GoalDirection, &GoalDirection);

// Then subtract the current sample points position from the Goal position
// to get the resulting direction vector:

GoalDirection.x -= state->point.x;
GoalDirection.y -= state->point.y;
GoalDirection.z -= state->point.z;

// This vector is then "normalized" which means that it's length is set to 1.0

mi_vector_normalize(&GoalDirection);

// And finally the Dot product between the surface normal and the GoalDirection
// is taken and modified a bit for an easy to use direction value between 0 and 1.
// Otherwise it would be between -1 and 1.

Dot = (mi_vector_dot(&state->normal, &GoalDirection) + 1.0) * 0.5;

// That's it. Now do with this value whatever you like :-)

Directions please?! ;-)

For a material shader, I wanted to be able to get the direction from the current sample point towards an object in the scene, like a Null etc. Since I was new to Mental Ray programming, I had a hard time finding the right combination of commands, since the SDK is extremely brief in some areas like mi_query and all the database stuff and especially dealing with objects in the scene.

With the help of Alan Jones I was finally able to get it working. And since there is so little information about Mental Ray programming in XSI on the web, I thought it would be nice to make it available for everyone while it is fresh. :-)

Maybe someone else hits the same wall.

If you have questions, ideas for improvements etc. feel free to mail me: