Textures and Mappings
Windows only
Overview
Broadly speaking, there are six concepts that are important to understand when dealing with materials, textures, and mappings:
- Texture Bitmap: A bitmap image, usually saved in a file.
- Texture Coordinates: In Rhino these are 2d and 3d points that are saved in an
ON_Mesh
in them_T[]
orm_TC[]
arrays. They should always be set by a texture mapping and never modified directly. - Texture Mapping: A function that sets texture coordinates. Persistent texture mappings are stored in
CRhinoDoc::m_texture_mapping_table[]
. - Surface parameters: A set of 2d points stored in an
ON_Mesh
in them_S[]
array. They are used by the surface parameter mapping. - Render Material: A collection of rendering color and shading information, including the names of texture bitmaps. Rendering materials are stored in
CRhinoDoc::m_material_table[]
. - Object Attributes: Attributes of a Rhino object, including the rendering materials and texture mappings the object uses, are stored in the
CRhinoObjectAttributes
class returned byCRhinoObject::Attributes()
.
Sample
The following sample creates a material with a bitmap texture, then modifies a mesh object’s attributes, sets up surface parameters and applies a surface parameter mapping so the bitmap is projected onto the mesh along the world Z axis…
CRhinoDoc* pDoc = context.Document();
if (nullptr == pDoc)
return CRhinoCommand::failure;
CRhinoDoc& doc = *pDoc;
// Id of the currently active render plug-in
const UUID renderPlugInId = RhinoApp().CurrentRenderPlugIn()->PlugInID();
// Create a material with a texture bitmap
ON_Texture tex;
tex.m_image_file_reference.SetFullPath(L"C:/my-texture-folder/sample-texture.bmp", true);
tex.m_bOn = true;
tex.m_type = ON_Texture::TYPE::bitmap_texture;
tex.m_mode = ON_Texture::MODE::modulate_texture;
tex.m_mapping_channel_id = 1;
ON_Material mat;
mat.m_diffuse.SetRGB(150, 0, 0);
mat.m_specular.SetRGB(200, 200, 200);
mat.m_shine = 0.5 * ON_Material::MaxShine;
mat.AddTexture(tex);
int mat_index = doc.m_material_table.AddMaterial(mat);
if (mat_index < 0)
return CRhinoCommand::failure;
// Select a mesh to modify
CRhinoGetObject go;
go.SetGeometryFilter(ON::mesh_object);
go.SetCommandPrompt(L"Select a mesh");
go.GetObjects(1, 1);
if (CRhinoCommand::success != go.CommandResult())
return go.CommandResult();
const CRhinoMeshObject* mesh0_object =
CRhinoMeshObject::Cast(go.Object(0).Object());
if (0 == mesh0_object)
return CRhinoCommand::failure;
const ON_Mesh* mesh0 = mesh0_object->Mesh();
if (0 == mesh0)
return CRhinoCommand::failure;
// Copy the mesh
ON_Mesh* mesh1 = new ON_Mesh(*mesh0);
ON_BoundingBox bbox = mesh1->BoundingBox();
ON_Interval x_extents(bbox.m_min.x, bbox.m_max.x);
ON_Interval y_extents(bbox.m_min.y, bbox.m_max.y);
// Set up surface parameters.
// They will be used by a surface parameter mapping.
const int vertex_count = mesh1->m_V.Count();
mesh1->m_S.Reserve(vertex_count);
mesh1->m_S.SetCount(0);
for (int vi = 0; vi < vertex_count; vi++)
{
const ON_3dPoint& V = mesh0->m_V[vi];
ON_2dPoint& tc = mesh1->m_S.AppendNew();
tc.x = (float)x_extents.NormalizedParameterAt(V.x);
tc.y = (float)y_extents.NormalizedParameterAt(V.y);
}
// Adjust surface packing settings so that surface parameter
// mapping will create vertex coordinates 1-to-1 with the
// surface parameters.
mesh1->m_srf_domain[0].Set(0.0, 1.0);
mesh1->m_srf_domain[1].Set(0.0, 1.0);
mesh1->m_srf_scale[0] = 0.0;
mesh1->m_srf_scale[1] = 0.0;
mesh1->m_packed_tex_domain[0].Set(0.0, 1.0);
mesh1->m_packed_tex_domain[1].Set(0.0, 1.0);
mesh1->m_packed_tex_rotate = false;
// Update the mesh
CRhinoMeshObject* mesh1_object = new CRhinoMeshObject();
mesh1_object->SetMesh(mesh1);
doc.ReplaceObject(CRhinoObjRef(mesh0_object), mesh1_object);
// Make a copy of the object attributes in order to apply some changes
ON_3dmObjectAttributes att = mesh1_object->Attributes();
// Update the object to use the new material
att.m_material_index = mat_index;
att.SetMaterialSource(ON::material_from_object);
// Add new texture mapping to the document texture mapping table
const int textureMappingIndex = doc.m_texture_mapping_table.AddTextureMapping(ON_TextureMapping::SurfaceParameterTextureMapping);
// Look up the mapping id of the newly added texture mapping
const UUID textureMappingId = doc.m_texture_mapping_table[textureMappingIndex].Id();
// Remove all texture mappings from the object attributes
att.m_rendering_attributes.m_mappings.Destroy();
// Add the newly added texture mapping on the mapping channel that the texture uses
att.m_rendering_attributes.AddMappingChannel(renderPlugInId, tex.m_mapping_channel_id, textureMappingId);
// Apply the modified attributes to the mesh object
doc.ModifyObjectAttributes(CRhinoObjRef(mesh1_object), att);
doc.Redraw();