MaxwellHair
Description
This extension enables maxwell to render hair. The data describing the guidelines is stored inside the extension in the .mxs file. Hairs can have all the same number of points or different point counts.
Besides generating its own geometry, this extension can generate also its own UV coordinates, using two types of UV generators. The first one generates lengthwise U's and it is useful for mapping different colors from the root to the tip. The second one generates hair-root UVs. It reads a user supplied array and assigns each hair a UV pair from the array. This is useful for mapping colors to the hairs depending on where the hair grows.
There is also the possibility to map a color for each point, exporting the corresponding array of vertex colors.
Example of how to create a MaxwellHair object, add a uv channel, and set its custom type to lengthwise U.
CextensionManager* extensionManager = CextensionManager::instance(); CgeometryProceduralExtension* geomProcExtension = extensionManager->createGeometryProceduralExtension( "MaxwellHair" ); //Get the extension container. When using this method of getting the container, //nearly all parameters have default values, and there is no need to explicitly set them. MXparamList* hairParams = geomProcExtension->getExtensionData(); CextensionManager* extensionManager = CextensionManager::instance(); CgeometryProceduralExtension* geomProcExtension = extensionManager->createGeometryProceduralExtension( "MaxwellHair" ); //Get the extension container. When using this method of getting the container, //nearly all parameters have default values, and there is no need to explicitly set them. MXparamList* hairParams = geomProcExtension->getExtensionData(); //Fill the required data, let's create a couple of hairs with three points each //If the first hair had two points and the third three points, numPointsPerHair would be an //array with two elements, i.e., numPointsPerHair[ 0 ] = 2; and numPointsPerHair[ 1 ] = 3; int numHairs = 2; int numPointsPerHair = 3; hairParams->setByteArray( "HAIR_GUIDES_COUNT", ( unsigned char* )&numHairs, sizeof( int ) ); hairParams->setByteArray( "HAIR_GUIDES_POINT_COUNT", ( unsigned char* )&numPointsPerHair, 1*sizeof( int ) ); float *points = new float[ numHairs*numPointsPerHair*3 ]; //First hair guide points[ 0 ] = 0.0;points[ 1 ] = 0.0;points[ 2 ] = 0.0; points[ 3 ] = 0.0;points[ 4 ] = 1.0;points[ 5 ] = 0.0; points[ 6 ] = 0.0;points[ 7 ] = 2.0;points[ 8 ] = 1.0; //Second hair guide points[ 9 ] = 1.0;points[ 10 ] = 0.0;points[ 11 ] = 0.0; points[ 12 ] = 1.0;points[ 13 ] = 1.0;points[ 14 ] = 0.0; points[ 15 ] = 2.0;points[ 16 ] = 2.0;points[ 17 ] = 0.0; hairParams->setFloatArray( "HAIR_POINTS", points, numHairs*numPointsPerHair*3 ); //Tip and root radius double root = 0.1; hairParams->setDouble( "Root Radius", &root ); double tip = 0.04; hairParams->setDouble( "Tip Radius", &tip ); //Add the procedural object to the scene Cmaxwell::Cobject obj = scene->createGeometryProceduralObject( "My two hairs", hairParams ); //Let´s add a uv channel... dword uvIndex; //returned uv channel index. Use this index in the texture map properties to access its uvs byte isOk = obj.addChannelUVW( uvIndex ); // uvIndex will be set to the actual uv channel number of the object. //...and set it to a custom UV generator, 0, in this case,lengthwise U obj.generateCustomUVW( uvIndex, 0 ); //Now assign a material and set the first BSDF reflectance0º color a texture driven by uv channel 'uvIndex' //This uv channel, since it is a one-valued channel, stores its value in the U coordinate....
Parameters
Name | Type | Description |
---|---|---|
int | Number of hairs | |
int* | Number of points of each hair strand | |
float* | Hair guides points | |
float* | Hair guides points for motion blur | |
"Root Radius" | double | Radius at the root |
"Tip Radius" | double | Radius at the tip |
"HAIR_FLAG_ROOT_UVS" | byte | Root UV's available or not |
"HAIR_ROOT_UVS" | float* | Array of root UV's |
"HAIR_FLAG_VERTEX_COLORS" | byte | Vertex colors available or not |
"HAIR_VERTEX_COLORS" | float* | Array of vertex colors |
"HAIR_FLAG_ROOT_UVS_1" | byte | Root UV's 1 available or not |
"HAIR_ROOT_UVS_1" | float* | Array 1 of root UV's |
"HAIR_FLAG_ROOT_UVS_2" | byte | Root UV's 2 available or not |
"HAIR_ROOT_UVS_2" | float* | Array 2 of root UV's |
"HAIR_FLAG_ROOT_UVS_3" | byte | Root UV's 3 available or not |
"HAIR_ROOT_UVS_3" | float* | Array 3 of root UV's |
"HAIR_FLAG_ROOT_UVS_4" | byte | Root UV's 4 available or not |
"HAIR_ROOT_UVS_4" | float* | Array 4 of root UV's |
"HAIR_FLAG_ROOT_UVS_5" | byte | Root UV's 5 available or not |
"HAIR_ROOT_UVS_5" | float* | Array 5 of root UV's |
"HAIR_FLAG_ROOT_UVS_6" | byte | Root UV's 6 available or not |
"HAIR_ROOT_UVS_6" | float* | Array 6 of root UV's |
"HAIR_FLAG_ROOT_UVS_7" | byte | Root UV's 7 available or not |
"HAIR_ROOT_UVS_7" | float* | Array 7 of root UV's |
"HAIR_FLAG_ROOT_UVS_8" | byte | Root UV's 8 available or not |
"HAIR_ROOT_UVS_8" | float* | Array 8 of root UV's |
"HAIR_FLAG_ROOT_UVS_9" | byte | Root UV's 9 available or not |
"HAIR_ROOT_UVS_9" | float* | Array 9 of root UV's |
"HAIR_FLAG_ROOT_UVS_10" | byte | Root UV's 10 available or not |
"HAIR_ROOT_UVS_10" | float* | Array 10 of root UV's |
Custom UV Generators
Name | Index |
---|---|
"lengthwise U" | 0 |
"hair root UV" | 1 |
"radial U" | 2 |
"HAIR_ROOT_UVS_1" | 3 |
"HAIR_ROOT_UVS_2" | 4 |
"HAIR_ROOT_UVS_3" | 5 |
"HAIR_ROOT_UVS_4" | 6 |
"HAIR_ROOT_UVS_5" | 7 |
"HAIR_ROOT_UVS_6" | 8 |
"HAIR_ROOT_UVS_7" | 9 |
"HAIR_ROOT_UVS_8" | 10 |
"HAIR_ROOT_UVS_9" | 11 |
"HAIR_ROOT_UVS_10" | 12 |
"HAIR_GUIDES_COUNT"
Number of hairs of the object.
Example:
int numHairs = 2; hairParams->setByteArray( "HAIR_GUIDES_COUNT", ( unsigned char* )&numHairs, sizeof( int ) );
"HAIR_GUIDES_POINT_COUNT"
Number of points of each hair. It is an integer array. If it has only one element, it is the number of points of all hairs. If it is an array of numHairs elements, each element is the number of points of the corresponding hair.
Example:
int numHairs = 2; int numPointsPerHair[ 2 ]; numPointsPerHair[ 0 ] = 2; and numPointsPerHair[ 1 ] = 3; hairParams->setByteArray( "HAIR_GUIDES_POINT_COUNT", ( unsigned char* )numPointsPerHair, numHairs*sizeof( int ) );
"HAIR_POINTS"
Linear array with all guides points: x0 y0 z0 x1 y1 z1....It is a float array. It has 3*numHairs*numPointsPerHair elements if the number of points per hair is constant or 3*numHairs*Sum(numPointsPerHair_i) if the number of points per hair is not constant. First come all the points of the first guide, from root to tip, then the second guide, etc etc, up to the last guide.
Example:
int numHairs = 2; int numPointsPerHair = 3; float *points = new float[ numHairs*numPointsPerHair*3 ]; //First hair points[ 0 ] = 0.0;points[ 1 ] = 0.0;points[ 2 ] = 0.0; points[ 3 ] = 0.0;points[ 4 ] = 1.0;points[ 5 ] = 0.0; points[ 6 ] = 0.0;points[ 7 ] = 2.0;points[ 8 ] = 1.0; //Second hair points[ 9 ] = 1.0;points[ 10 ] = 0.0;points[ 11 ] = 0.0; points[ 12 ] = 1.0;points[ 13 ] = 1.0;points[ 14 ] = 0.0; points[ 15 ] = 2.0;points[ 16 ] = 2.0;points[ 17 ] = 0.0; hairParams->setFloatArray( "HAIR_POINTS", points, numHairs*numPointsPerHair*3 );
"HAIR_POINTS_MB"
Linear array with all guides points but displaced to their end position to calculate motion blur. It must have the same size as "HAIR_POINTS".
"Root Radius" "Tip Radius"
Radius at the root and tip of the hair guides.
Example:
//Tip and root radius double root = 0.1; hairParams->setDouble( "Root Radius", &root ); double tip = 0.04; hairParams->setDouble( "Tip Radius", &tip );
"HAIR_FLAG_ROOT_UVS"
Flag indicating if the root uvs array is present or not. It is an array of length 1.
Example:
byte flag = 1; extParam->setByteArray( "HAIR_FLAG_ROOT_UVS, &flag, 1 );
"HAIR_ROOT_UVS"
Linear array of uv coordinates at each hair root: u0 v0 u1 v1 u2 v2..., its length is 2*numberOfHairs.
Example:
int numHairs = 3; float uv[ 2*3 ]; uv[0] = 0.0; uv[1] = 0.0; uv[2] = 0.3; uv[3] = 0.2; uv[4] = 0.1; uv[5] = 0.99; extParam->setFloatArray( "HAIR_ROOT_UVS", uv, 2*numHairs );
"HAIR_FLAG_VERTEX_COLORS"
Flag indicating if the hair vertex colors array is present or not. It is an array of length 1.
Example:
byte flag = 1; extParam->setByteArray( "HAIR_FLAG_VERTEX_COLORS", &flag, 1 );
"HAIR_VERTEX_COLORS"
Linear array of color (rgb) at each vertex of the hair guides: r0 g0 b0 r1 g1 b1 r2 g2 b2...., its length is 3*numberOfPoints.
Example:
int numHairs = 2; int numPointsPerHair = 3; float rgb[ 3*2*3 ]; rgb[ 0 ] = 0.1; rgb[ 1 ] = 0.6; rgb[ 2 ] = 0.1; rgb[ 3 ] = 0.5; rgb[ 4 ] = 0.2; rgb[ 5 ] = 0.4; rgb[ 6 ] = 0.0; rgb[ 7 ] = 0.6; rgb[ 8 ] = 0.9; rgb[ 9 ] = 0.8; rgb[ 10 ] = 0.3; rgb[ 11 ] = 0.0; rgb[ 12 ] = 0.2; rgb[ 13 ] = 0.5; rgb[ 14 ] = 0.8; rgb[ 15 ] = 0.1; rgb[ 16 ] = 0.1; rgb[ 17 ] = 0.6; extParam->setFloatArray( "HAIR_VERTEX_COLORS", rgb, 3*2*3 );
"HAIR_FLAG_ROOT_UVS_1" to "HAIR_FLAG_ROOT_UVS_10"
Flag indicating whether root uvs arrays 1 to 10 are present or not. They are a byte array of length 1.
"HAIR_ROOT_UVS_1" to "HAIR_ROOT_UVS_10"
Linear arrays of uv coordinates at each hair root: u0 v0 u1 v1 u2 v2..., their length is 2*numberOfHairs.