The Material Library offers a way to rapidly load, maintain, manipulate and customized sophisticated materials in the HOOPS 3DF environment. The Material Library consists of two main components: HMaterialLibrary and Material Resources. To interact with the Material Library, use the HMaterialLibrary class. This class works in conjunction with the Material Library resources package that can be downloaded from the Developer Zone. The Material Resources package is a collection of materials and environments developed by a team of artists, shader experts, and engineering industry veterans. You can learn more about the collection of materials in our Material Resources section.
The HMaterialLibrary class works in concert with the resource package to give you the ability to enhance the visual appearance of your 3D models in a dynamic and highly interactive way. Complex and sophisticated materials can be loaded into the library rapidly. Once imported into the library, materials can be customized.
NOTE: In general, materials can only be applied to shells. Other geometry such as polygons and primitives can have some basic attributes (such as color) applied at the segment level but cannot use the more advanced materials such as textures and shaders.
The HMaterialLibrary class load and maintains materials in the Material Library. It exposes methods to manipulate and apply materials to models. To load materials into the Material Library and apply them to a model, follow these simple steps:
The following code sample show how these steps might be implemented:
HMaterialLibrary hmat; const char *material_name = "car_panel_walnut"; const char *environment_name = "environment_snow"; /*************************/ /* 1. Register Materials */ /*************************/ hmat.RegisterMaterials (H_FORMAT_TEXT ("%s%s", "C:/HOOPS-1800/datasets/", "materials")); /***************************************/ /* 2. Get Material & Environment Lists */ /***************************************/ const char *list = hmat.GetMaterialList(); if (list == NULL) return; const char *env_list = hmat.GetEnvironmentList(); if (env_list == NULL) return; //checking if the environment_snow is in the materials library if (strstr(env_list, environment_name) == NULL) return; /**********************/ /* 3. Set Environment */ /**********************/ hmat.SetEnvironment (environment_name); HC_Open_Segment_By_Key(m_pHView->GetModelKey()); { HC_Set_Color ("faces = green, text = red"); HC_Set_Visibility ("faces, no edges, no vertices"); //checking if the car_panel_walnut is in the materials library if (strstr(list, material_name) == NULL) return; HC_Open_Segment (""); { /*******************/ /* 4. Apply Styles */ /*******************/ hmat.ApplyStyles(); HC_POINT center = { 1, 1, 1 }; HC_Insert_Sphere(center, 2, NULL, NULL ); /*********************/ /* 5. Apply Material */ /*********************/ hmat.ApplyMaterial (material_name); } HC_Close_Segment (); } HC_Close_Segment (); /*******************/ /* 6. Render Scene */ /*******************/ HC_Update_Display();
In the Material Library, you can load any number of environments. However, only one environment takes effect in a scene. To set the current environment, call HMaterialLibrary::SetEnvironment passing the name of the environment. Recall that the name of an environment, like a material, is the name of the directory in which the environment_index.dat file and associated resources reside. Then open the top level segment of your model's segment tree and call HMaterialLibrary::ApplyStyles. This will ensure that any lighting information defined in the enviroment will be used in the scene. Once you set this information, subsequent calls to HMaterialLibrary::ApplyMaterial will use the environment currently set.
CHANNEL: ENVIRONMENT SOURCE: environment2
The record above does not name a specific environment name. Instead it specificies which cubemap to use for a given environment. Naming the cube map allows you the flexibilty to change environments on demand.
Let's take a look at an example of how this flexiblity in specifying an environment can be useful. Let's say you have a car model. If you have defined a material like car paint, you might want to apply the paint to a car that is in the mountains or a canyon. Both the mountains and canyon environments have cubemaps for a sunny day and stormy weather identified as CUBEMAP0 and CUBEMAP1, respectively. The following is how the enviroment_index.dat might look for the mountains environment:
CHANNEL: CUBEMAP0 SOURCE: sunny CHANNEL: CUBEMAP1 SOURCE: stormy
If your goal is to show off the car paint, then you will want to use the cube map that depicts sunny weather (you might use the stormy weather environment in an animation that shows how your car model has excellent handling with its all-weather tires). Thus your material specification would include this record for the environment specification:
CHANNEL: ENVIRONMENT SOURCE: environment0
During application usage, whether the environment is mountains or canyon, the cube map that reflects off the car paint is the sunny weather cube map.
One of the most useful features of the Materail Library is its dynamic loading capability. In the Material Library, you can load a material and use it in your scene. If the material's resources and/or the shader code changes, you can update the directory with the new files and call HMaterialLibrary::ReloadMaterial passing the material name. At render time, the changes will be reflected in the scene with no need for recompiling.
Another capability of the HMaterialLibrary is to change the default values of specific variables in customer shader code dynamically. These variables are called tweakables. For example, let's say we have a material called brass. Once we load the brass material, we can access whether brass has a tweakable variable and then change its default value. The example below shows how a variable can be tweaked via methods in the HMaterialLibrary:
HMaterialLibrary hmat; const char *material_name = "brass"; const char *environment_name = "environment_snow"; char tweakable_name[512], tweakable_type[64]; int tweakable_count = 0; //register materials hmat.RegisterMaterials (H_FORMAT_TEXT ("%s%s", "C:/HOOPS-1900/datasets/", "materials")); const char *list = hmat.GetMaterialList(); if (list == NULL) return; //checking if the environment_snow is in the materials library const char *env_list = hmat.GetEnvironmentList(); if (env_list == NULL) return; if (strstr(env_list, environment_name) == NULL) return; //setting the current environment to environment_snow hmat.SetEnvironment (environment_name); HC_Open_Segment_By_Key(m_pHView->GetModelKey()); { HC_Set_Color ("faces = green, text = red"); HC_Set_Visibility ("faces, no edges, no vertices"); //checking if brass is in the material library if (strstr(list, material_name) == NULL) return; HC_Open_Segment (""); { hmat.ApplyStyles(); HPoint center(0,0,0); HPoint axis(0,1,0); HPoint ref(0,0,1); HUtilityGeometryCreation::CreateSphere(center, 1.0,20,axis,ref); hmat.ApplyMaterial (material_names[0]); //Seeing if there are any tweakable values in the brass material if (!hmat.GetTweakablesCount (material_name, &tweakables_count)) return; for (i = 0 ; i < tweakables_count ; i++) { if (hmat.GetTweakableByIndex (material_name, i, tweakable_name, tweakable_type)) { //looking for the my_tweak variable if (streq (tweakable_name, "my_tweak")) { //Changing the default value of the my_tweak variable if (!hmat.Tweak (material_name, i, 1.0, 1.0, 1.0)) return; } } } } HC_Close_Segment (); } HC_Close_Segment (); HC_Update_Display();
In the code above, we use several key methods in HMaterialLibrary to change the my_tweak variable. To begin, we first find out if there are any tweakable variables for a given material using the HMaterialLibrary::GetTweakablesCount. If it returns a number greater than zero, then we can iterate through the tweakable variable list using HMaterialLibrary::GetTweakableByIndex to find our my_tweak variable and the tweakable_type of variable it is. The tweakable_type tells us how many values we can change. For my_tweak, it is float3. So when we called HMaterialLibrary::Tweak, we know change three float values for the my_tweak variable.