Since the I can’t raise issues on the GitHub C API tracker currently (non Trimble Employees can’t seem to do this), I’ll raise here.
I’ve been struggling to get textures working on my Ruby C Extension for some time. Specifically, I am trying to copy textures from one model to another. All seems to work except that the scale at which the textures are copied over is wrong (they are set to an s_scale and t_scale of 1.0).
I think I have narrowed down the problem to the C API function SUTextureCreateFromFile(). When this function is used to create a texture, the s_scale and t_scale is not saved. Here is some code that can replicate the issue - a Ruby C Extension function:
VALUE test_texture_scales(VALUE self)
{
SUModelRef model = SU_INVALID;
SU(SUApplicationGetActiveModel(&model));
if (SUIsInvalid(model)) {
rb_raise(rb_eTypeError, "invalid model");
}
// Test all materials with textures in model
size_t num_materials = 0;
SUModelGetNumMaterials(model, &num_materials);
SUMaterialRef* materials = new SUMaterialRef[num_materials];
size_t count = 0;
SUModelGetMaterials(model, num_materials, materials, &count);
for (size_t i = 0; i < count; ++i) {
SUMaterialRef material = materials[i];
SUTextureRef texture = SU_INVALID;
SUResult res = SUMaterialGetTexture(material, &texture);
if (res != SU_ERROR_NONE || SUIsInvalid(texture)) {
continue;
}
size_t width = 0;
size_t height = 0;
double s_scale = 0.0;
double t_scale = 0.0;
res = SUTextureGetDimensions(texture, &width, &height, &s_scale, &t_scale);
if (res != SU_ERROR_NONE) {
std::cout << "Failed to get texture dimensions for material " << i << std::endl;
}
SUStringRef file_name = SU_INVALID;
SUStringCreate(&file_name);
SUTextureGetFileName(texture, &file_name);
std::string name_str = GetString(file_name);
std::cout << "In Model Texture: Name:"<< name_str <<" width:" << width << " height:" << height << " s_scale:" << s_scale << " t_scale:" << t_scale << std::endl;
// Prints: In Model Texture: Name:Roofing_Tile_Spanish.jpgx00 width:1392 height:1144 s_scale:0.0333333 t_scale:0.0405594
SUStringRelease(&file_name);
// Now copy texture to a new one
std::string file_path = "/tmp/tmptexture";
res = SUTextureWriteOriginalToFile(texture, file_path.c_str());
assert(res == SU_ERROR_NONE);
SUTextureRef new_texture = SU_INVALID;
res = SUTextureCreateFromFile(&new_texture, file_path.c_str(), s_scale, t_scale);
// Delete the temporary file
const char *file_path_c = file_path.c_str();
int ret = std::remove(file_path_c);
if(ret != 0) {
rb_raise(rb_eTypeError, "failed to delete temporary texture file");
}
// Check the scales are correct:
size_t new_width = 0;
size_t new_height = 0;
double new_s_scale = 0.0;
double new_t_scale = 0.0;
res = SUTextureGetDimensions(new_texture, &new_width, &new_height, &new_s_scale, &new_t_scale);
assert(res == SU_ERROR_NONE);
std::cout << "Copied Texture: Name:"<< name_str <<" width:" << new_width << " height:" << new_height << " s_scale:" << new_s_scale << " t_scale:" << new_t_scale << std::endl;
// Prints: Copied Texture: Name:Roofing_Tile_Spanish.jpgx00 width:1392 height:1144 s_scale:1 t_scale:1
SUTextureRelease(&new_texture);
}
delete [] materials;
return self;
}
I think this is a bug in the API. I have tested this on SU 2024 and 2025. I suspect that someone has accidentally cast the s_scale and t_scale DOUBLES to a SIZE_T type or something. Am currently looking for a workaround.
As of SU 2025, one can use SUTextureSetDimensions() to manually set the s_scale and t_scale. Earlier versions only had SUTextureCreateFromFile as a way to set these, so another method needs to be found for versions 2024 and previous… [EDIT: I don’t think there is a workaround for versions prior to 2025 - this is broken!]