Getting to the way it's supposed to be!
This commit is contained in:
557
modules/ufbx/test/check_material.h
Normal file
557
modules/ufbx/test/check_material.h
Normal file
@@ -0,0 +1,557 @@
|
||||
#ifndef UFBXT_CHECK_MATERIAL_H_INCLUDED
|
||||
#define UFBXT_CHECK_MATERIAL_H_INCLUDED
|
||||
|
||||
#include "../ufbx.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static const char *ufbxt_fbx_map_name(ufbx_material_fbx_map map)
|
||||
{
|
||||
switch (map) {
|
||||
case UFBX_MATERIAL_FBX_DIFFUSE_FACTOR: return "diffuse_factor";
|
||||
case UFBX_MATERIAL_FBX_DIFFUSE_COLOR: return "diffuse_color";
|
||||
case UFBX_MATERIAL_FBX_SPECULAR_FACTOR: return "specular_factor";
|
||||
case UFBX_MATERIAL_FBX_SPECULAR_COLOR: return "specular_color";
|
||||
case UFBX_MATERIAL_FBX_SPECULAR_EXPONENT: return "specular_exponent";
|
||||
case UFBX_MATERIAL_FBX_REFLECTION_FACTOR: return "reflection_factor";
|
||||
case UFBX_MATERIAL_FBX_REFLECTION_COLOR: return "reflection_color";
|
||||
case UFBX_MATERIAL_FBX_TRANSPARENCY_FACTOR: return "transparency_factor";
|
||||
case UFBX_MATERIAL_FBX_TRANSPARENCY_COLOR: return "transparency_color";
|
||||
case UFBX_MATERIAL_FBX_EMISSION_FACTOR: return "emission_factor";
|
||||
case UFBX_MATERIAL_FBX_EMISSION_COLOR: return "emission_color";
|
||||
case UFBX_MATERIAL_FBX_AMBIENT_FACTOR: return "ambient_factor";
|
||||
case UFBX_MATERIAL_FBX_AMBIENT_COLOR: return "ambient_color";
|
||||
case UFBX_MATERIAL_FBX_NORMAL_MAP: return "normal_map";
|
||||
case UFBX_MATERIAL_FBX_BUMP: return "bump";
|
||||
case UFBX_MATERIAL_FBX_BUMP_FACTOR: return "bump_factor";
|
||||
case UFBX_MATERIAL_FBX_DISPLACEMENT_FACTOR: return "displacement_factor";
|
||||
case UFBX_MATERIAL_FBX_DISPLACEMENT: return "displacement";
|
||||
case UFBX_MATERIAL_FBX_VECTOR_DISPLACEMENT_FACTOR: return "vector_displacement_factor";
|
||||
case UFBX_MATERIAL_FBX_VECTOR_DISPLACEMENT: return "vector_displacement";
|
||||
}
|
||||
|
||||
ufbxt_assert(0 && "Unhandled PBR map name");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *ufbxt_pbr_map_name(ufbx_material_pbr_map map)
|
||||
{
|
||||
switch (map) {
|
||||
case UFBX_MATERIAL_PBR_BASE_FACTOR: return "base_factor";
|
||||
case UFBX_MATERIAL_PBR_BASE_COLOR: return "base_color";
|
||||
case UFBX_MATERIAL_PBR_ROUGHNESS: return "roughness";
|
||||
case UFBX_MATERIAL_PBR_METALNESS: return "metalness";
|
||||
case UFBX_MATERIAL_PBR_DIFFUSE_ROUGHNESS: return "diffuse_roughness";
|
||||
case UFBX_MATERIAL_PBR_SPECULAR_FACTOR: return "specular_factor";
|
||||
case UFBX_MATERIAL_PBR_SPECULAR_COLOR: return "specular_color";
|
||||
case UFBX_MATERIAL_PBR_SPECULAR_IOR: return "specular_ior";
|
||||
case UFBX_MATERIAL_PBR_SPECULAR_ANISOTROPY: return "specular_anisotropy";
|
||||
case UFBX_MATERIAL_PBR_SPECULAR_ROTATION: return "specular_rotation";
|
||||
case UFBX_MATERIAL_PBR_TRANSMISSION_FACTOR: return "transmission_factor";
|
||||
case UFBX_MATERIAL_PBR_TRANSMISSION_COLOR: return "transmission_color";
|
||||
case UFBX_MATERIAL_PBR_TRANSMISSION_DEPTH: return "transmission_depth";
|
||||
case UFBX_MATERIAL_PBR_TRANSMISSION_SCATTER: return "transmission_scatter";
|
||||
case UFBX_MATERIAL_PBR_TRANSMISSION_SCATTER_ANISOTROPY: return "transmission_scatter_anisotropy";
|
||||
case UFBX_MATERIAL_PBR_TRANSMISSION_DISPERSION: return "transmission_dispersion";
|
||||
case UFBX_MATERIAL_PBR_TRANSMISSION_ROUGHNESS: return "transmission_roughness";
|
||||
case UFBX_MATERIAL_PBR_TRANSMISSION_EXTRA_ROUGHNESS: return "transmission_extra_roughness";
|
||||
case UFBX_MATERIAL_PBR_TRANSMISSION_PRIORITY: return "transmission_priority";
|
||||
case UFBX_MATERIAL_PBR_TRANSMISSION_ENABLE_IN_AOV: return "transmission_enable_in_aov";
|
||||
case UFBX_MATERIAL_PBR_SUBSURFACE_FACTOR: return "subsurface_factor";
|
||||
case UFBX_MATERIAL_PBR_SUBSURFACE_COLOR: return "subsurface_color";
|
||||
case UFBX_MATERIAL_PBR_SUBSURFACE_RADIUS: return "subsurface_radius";
|
||||
case UFBX_MATERIAL_PBR_SUBSURFACE_SCALE: return "subsurface_scale";
|
||||
case UFBX_MATERIAL_PBR_SUBSURFACE_ANISOTROPY: return "subsurface_anisotropy";
|
||||
case UFBX_MATERIAL_PBR_SUBSURFACE_TINT_COLOR: return "subsurface_tint_color";
|
||||
case UFBX_MATERIAL_PBR_SUBSURFACE_TYPE: return "subsurface_type";
|
||||
case UFBX_MATERIAL_PBR_SHEEN_FACTOR: return "sheen_factor";
|
||||
case UFBX_MATERIAL_PBR_SHEEN_COLOR: return "sheen_color";
|
||||
case UFBX_MATERIAL_PBR_SHEEN_ROUGHNESS: return "sheen_roughness";
|
||||
case UFBX_MATERIAL_PBR_COAT_FACTOR: return "coat_factor";
|
||||
case UFBX_MATERIAL_PBR_COAT_COLOR: return "coat_color";
|
||||
case UFBX_MATERIAL_PBR_COAT_ROUGHNESS: return "coat_roughness";
|
||||
case UFBX_MATERIAL_PBR_COAT_IOR: return "coat_ior";
|
||||
case UFBX_MATERIAL_PBR_COAT_ANISOTROPY: return "coat_anisotropy";
|
||||
case UFBX_MATERIAL_PBR_COAT_ROTATION: return "coat_rotation";
|
||||
case UFBX_MATERIAL_PBR_COAT_NORMAL: return "coat_normal";
|
||||
case UFBX_MATERIAL_PBR_COAT_AFFECT_BASE_COLOR: return "coat_affect_base_color";
|
||||
case UFBX_MATERIAL_PBR_COAT_AFFECT_BASE_ROUGHNESS: return "coat_affect_base_roughness";
|
||||
case UFBX_MATERIAL_PBR_THIN_FILM_THICKNESS: return "thin_film_thickness";
|
||||
case UFBX_MATERIAL_PBR_THIN_FILM_IOR: return "thin_film_ior";
|
||||
case UFBX_MATERIAL_PBR_EMISSION_FACTOR: return "emission_factor";
|
||||
case UFBX_MATERIAL_PBR_EMISSION_COLOR: return "emission_color";
|
||||
case UFBX_MATERIAL_PBR_OPACITY: return "opacity";
|
||||
case UFBX_MATERIAL_PBR_INDIRECT_DIFFUSE: return "indirect_diffuse";
|
||||
case UFBX_MATERIAL_PBR_INDIRECT_SPECULAR: return "indirect_specular";
|
||||
case UFBX_MATERIAL_PBR_NORMAL_MAP: return "normal_map";
|
||||
case UFBX_MATERIAL_PBR_TANGENT_MAP: return "tangent_map";
|
||||
case UFBX_MATERIAL_PBR_DISPLACEMENT_MAP: return "displacement_map";
|
||||
case UFBX_MATERIAL_PBR_MATTE_FACTOR: return "matte_factor";
|
||||
case UFBX_MATERIAL_PBR_MATTE_COLOR: return "matte_color";
|
||||
case UFBX_MATERIAL_PBR_AMBIENT_OCCLUSION: return "ambient_occlusion";
|
||||
case UFBX_MATERIAL_PBR_GLOSSINESS: return "glossiness";
|
||||
case UFBX_MATERIAL_PBR_COAT_GLOSSINESS: return "coat_glossiness";
|
||||
case UFBX_MATERIAL_PBR_TRANSMISSION_GLOSSINESS: return "transmission_glossiness";
|
||||
}
|
||||
|
||||
ufbxt_assert(0 && "Unhandled PBR map name");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *ufbxt_material_feature_name(ufbx_material_pbr_map map)
|
||||
{
|
||||
switch (map) {
|
||||
case UFBX_MATERIAL_FEATURE_PBR: return "pbr";
|
||||
case UFBX_MATERIAL_FEATURE_METALNESS: return "metalness";
|
||||
case UFBX_MATERIAL_FEATURE_DIFFUSE: return "diffuse";
|
||||
case UFBX_MATERIAL_FEATURE_SPECULAR: return "specular";
|
||||
case UFBX_MATERIAL_FEATURE_EMISSION: return "emission";
|
||||
case UFBX_MATERIAL_FEATURE_TRANSMISSION: return "transmission";
|
||||
case UFBX_MATERIAL_FEATURE_COAT: return "coat";
|
||||
case UFBX_MATERIAL_FEATURE_SHEEN: return "sheen";
|
||||
case UFBX_MATERIAL_FEATURE_OPACITY: return "opacity";
|
||||
case UFBX_MATERIAL_FEATURE_AMBIENT_OCCLUSION: return "ambient_occlusion";
|
||||
case UFBX_MATERIAL_FEATURE_MATTE: return "matte";
|
||||
case UFBX_MATERIAL_FEATURE_UNLIT: return "unlit";
|
||||
case UFBX_MATERIAL_FEATURE_IOR: return "ior";
|
||||
case UFBX_MATERIAL_FEATURE_DIFFUSE_ROUGHNESS: return "diffuse_roughness";
|
||||
case UFBX_MATERIAL_FEATURE_TRANSMISSION_ROUGHNESS: return "transmission_roughness";
|
||||
case UFBX_MATERIAL_FEATURE_THIN_WALLED: return "thin_walled";
|
||||
case UFBX_MATERIAL_FEATURE_CAUSTICS: return "caustics";
|
||||
case UFBX_MATERIAL_FEATURE_EXIT_TO_BACKGROUND: return "exit_to_background";
|
||||
case UFBX_MATERIAL_FEATURE_INTERNAL_REFLECTIONS: return "internal_reflections";
|
||||
case UFBX_MATERIAL_FEATURE_DOUBLE_SIDED: return "double_sided";
|
||||
case UFBX_MATERIAL_FEATURE_ROUGHNESS_AS_GLOSSINESS: return "roughness_as_glossiness";
|
||||
case UFBX_MATERIAL_FEATURE_COAT_ROUGHNESS_AS_GLOSSINESS: return "coat_roughness_as_glossiness";
|
||||
case UFBX_MATERIAL_FEATURE_TRANSMISSION_ROUGHNESS_AS_GLOSSINESS: return "transmission_roughness_as_glossiness";
|
||||
}
|
||||
|
||||
ufbxt_assert(0 && "Unhandled material feature name");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *ufbxt_shader_type_name(ufbx_shader_type map)
|
||||
{
|
||||
switch (map) {
|
||||
case UFBX_SHADER_UNKNOWN: return "unknown";
|
||||
case UFBX_SHADER_FBX_LAMBERT: return "fbx_lambert";
|
||||
case UFBX_SHADER_FBX_PHONG: return "fbx_phong";
|
||||
case UFBX_SHADER_OSL_STANDARD_SURFACE: return "osl_standard_surface";
|
||||
case UFBX_SHADER_ARNOLD_STANDARD_SURFACE: return "arnold_standard_surface";
|
||||
case UFBX_SHADER_3DS_MAX_PHYSICAL_MATERIAL: return "3ds_max_physical_material";
|
||||
case UFBX_SHADER_3DS_MAX_PBR_METAL_ROUGH: return "3ds_max_pbr_metal_rough";
|
||||
case UFBX_SHADER_3DS_MAX_PBR_SPEC_GLOSS: return "3ds_max_pbr_spec_gloss";
|
||||
case UFBX_SHADER_GLTF_MATERIAL: return "gltf_material";
|
||||
case UFBX_SHADER_SHADERFX_GRAPH: return "shaderfx_graph";
|
||||
case UFBX_SHADER_BLENDER_PHONG: return "blender_phong";
|
||||
case UFBX_SHADER_WAVEFRONT_MTL: return "wavefront_mtl";
|
||||
}
|
||||
|
||||
ufbxt_assert(0 && "Unhandled material feature name");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t ufbxt_tokenize_line(char *buf, size_t buf_len, const char **tokens, size_t max_tokens, const char **p_line, const char *sep_chars)
|
||||
{
|
||||
bool prev_sep = true;
|
||||
|
||||
size_t num_tokens = 0;
|
||||
size_t buf_pos = 0;
|
||||
|
||||
const char *p = *p_line;
|
||||
for (;;) {
|
||||
char c = *p;
|
||||
if (c == '\0' || c == '\n') break;
|
||||
|
||||
bool sep = false;
|
||||
for (const char *s = sep_chars; *s; s++) {
|
||||
if (*s == c) {
|
||||
sep = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sep) {
|
||||
if (prev_sep) {
|
||||
ufbxt_assert(buf_pos < buf_len);
|
||||
buf[buf_pos++] = '\0';
|
||||
|
||||
ufbxt_assert(num_tokens < max_tokens);
|
||||
tokens[num_tokens++] = buf + buf_pos;
|
||||
}
|
||||
|
||||
if (c == '"') {
|
||||
p++;
|
||||
while (*p != '"') {
|
||||
c = *p;
|
||||
if (c == '\\') {
|
||||
p++;
|
||||
switch (*p) {
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case '\\': c = '\\'; break;
|
||||
case '"': c = '"'; break;
|
||||
default:
|
||||
fprintf(stderr, "Bad escape '\\%c'\n", *p);
|
||||
ufbxt_assert(0 && "Bad escape");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ufbxt_assert(buf_pos < buf_len);
|
||||
buf[buf_pos++] = c;
|
||||
p++;
|
||||
}
|
||||
} else {
|
||||
ufbxt_assert(buf_pos < buf_len);
|
||||
buf[buf_pos++] = c;
|
||||
}
|
||||
}
|
||||
prev_sep = sep;
|
||||
p++;
|
||||
}
|
||||
|
||||
ufbxt_assert(buf_pos < buf_len);
|
||||
buf[buf_pos++] = '\0';
|
||||
|
||||
for (size_t i = num_tokens; i < max_tokens; i++) {
|
||||
tokens[i] = "";
|
||||
}
|
||||
|
||||
if (*p == '\n') p += 1;
|
||||
*p_line = p;
|
||||
|
||||
return num_tokens;
|
||||
}
|
||||
|
||||
static bool ufbxt_check_materials(ufbx_scene *scene, const char *spec, const char *filename)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
char line_buf[512];
|
||||
const char *tokens[8];
|
||||
|
||||
char dot_buf[512];
|
||||
const char *dots[8];
|
||||
|
||||
bool seen_materials[256];
|
||||
|
||||
ufbx_material *material = NULL;
|
||||
size_t num_materials = 0;
|
||||
size_t num_props = 0;
|
||||
|
||||
double err_sum = 0.0;
|
||||
double err_max = 0.0;
|
||||
size_t err_num = 0;
|
||||
|
||||
bool material_error = false;
|
||||
bool require_all = false;
|
||||
|
||||
long version = 0;
|
||||
|
||||
int line = 0;
|
||||
while (*spec != '\0') {
|
||||
size_t num_tokens = ufbxt_tokenize_line(line_buf, sizeof(line_buf), tokens, ufbxt_arraycount(tokens), &spec, " \t\r");
|
||||
line++;
|
||||
|
||||
if (num_tokens == 0) continue;
|
||||
|
||||
const char *first_token = tokens[0];
|
||||
size_t num_dots = ufbxt_tokenize_line(dot_buf, sizeof(dot_buf), dots, ufbxt_arraycount(dots), &first_token, ".");
|
||||
|
||||
if (!strcmp(dots[0], "version")) {
|
||||
char *end = NULL;
|
||||
version = strtol(tokens[1], &end, 10);
|
||||
if (!end || *end != '\0') {
|
||||
fprintf(stderr, "%s:%d: Bad value in '%s': '%s'\n", filename, line, tokens[0], tokens[1]);
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
} else if (!strcmp(dots[0], "require")) {
|
||||
if (!strcmp(tokens[1], "all")) {
|
||||
if (scene->materials.count > ufbxt_arraycount(seen_materials)) {
|
||||
fprintf(stderr, "%s:%d: Too many materials in file for 'reqiure all': %zu (max %zu)\n", filename, line,
|
||||
scene->materials.count, (size_t)ufbxt_arraycount(seen_materials));
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
require_all = true;
|
||||
memset(seen_materials, 0, scene->materials.count * sizeof(bool));
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d: Bad require directive: '%s'\n", filename, line, tokens[1]);
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
} else if (!strcmp(dots[0], "material")) {
|
||||
if (*tokens[1] == '\0') {
|
||||
fprintf(stderr, "%s:%d: Expected material name for 'material'\n", filename, line);
|
||||
ok = false;
|
||||
}
|
||||
|
||||
material = ufbx_find_material(scene, tokens[1]);
|
||||
if (!material) {
|
||||
fprintf(stderr, "%s:%d: Material not found: '%s'\n", filename, line, tokens[1]);
|
||||
ok = false;
|
||||
}
|
||||
material_error = !material;
|
||||
|
||||
if (material) {
|
||||
seen_materials[material->typed_id] = true;
|
||||
}
|
||||
|
||||
num_materials++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!material) {
|
||||
if (!material_error) {
|
||||
fprintf(stderr, "%s:%d: Statement '%s' needs to have a material defined\n", filename, line, tokens[0]);
|
||||
}
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
num_props++;
|
||||
|
||||
if (!strcmp(dots[0], "fbx") || !strcmp(dots[0], "pbr")) {
|
||||
ufbx_material_map *map = NULL;
|
||||
if (!strcmp(dots[0], "fbx")) {
|
||||
ufbx_material_fbx_map name = (ufbx_material_fbx_map)UFBX_MATERIAL_FBX_MAP_COUNT;
|
||||
for (size_t i = 0; i < UFBX_MATERIAL_FBX_MAP_COUNT; i++) {
|
||||
const char *str = ufbxt_fbx_map_name((ufbx_material_fbx_map)i);
|
||||
if (!strcmp(dots[1], str)) {
|
||||
name = (ufbx_material_fbx_map)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == (ufbx_material_fbx_map)UFBX_MATERIAL_FBX_MAP_COUNT) {
|
||||
fprintf(stderr, "%s:%d: Unknown FBX material map '%s' in '%s'\n", filename, line, dots[1], tokens[0]);
|
||||
ok = false;
|
||||
} else {
|
||||
map = &material->fbx.maps[name];
|
||||
}
|
||||
} else if (!strcmp(dots[0], "pbr")) {
|
||||
ufbx_material_pbr_map name = (ufbx_material_pbr_map)UFBX_MATERIAL_PBR_MAP_COUNT;
|
||||
for (size_t i = 0; i < UFBX_MATERIAL_PBR_MAP_COUNT; i++) {
|
||||
const char *str = ufbxt_pbr_map_name((ufbx_material_pbr_map)i);
|
||||
if (!strcmp(dots[1], str)) {
|
||||
name = (ufbx_material_pbr_map)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == (ufbx_material_pbr_map)UFBX_MATERIAL_PBR_MAP_COUNT) {
|
||||
fprintf(stderr, "%s:%d: Unknown PBR material map '%s' in '%s'\n", filename, line, dots[1], tokens[0]);
|
||||
ok = false;
|
||||
} else {
|
||||
map = &material->pbr.maps[name];
|
||||
}
|
||||
} else {
|
||||
ufbxt_assert(0 && "Unhandled branch");
|
||||
}
|
||||
|
||||
// Errors reported above, but set ok to false just to be sure..
|
||||
if (!map) {
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(dots[2], "texture")) {
|
||||
size_t tok_start = 1;
|
||||
bool content = false;
|
||||
for (;;) {
|
||||
const char *tok = tokens[tok_start];
|
||||
if (!strcmp(tok, "content")) {
|
||||
content = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
tok_start++;
|
||||
}
|
||||
|
||||
const char *tex_name = tokens[tok_start];
|
||||
if (map->texture) {
|
||||
if (strcmp(map->texture->relative_filename.data, tex_name) != 0) {
|
||||
fprintf(stderr, "%s:%d: Material '%s' %s.%s is different: got '%s', expected '%s'\n", filename, line,
|
||||
material->name.data, dots[0], dots[1], map->texture->relative_filename.data, tex_name);
|
||||
ok = false;
|
||||
}
|
||||
if (content && map->texture->content.size == 0) {
|
||||
fprintf(stderr, "%s:%d: Material '%s' %s.%s expected content for the texture %s\n", filename, line,
|
||||
material->name.data, dots[0], dots[1], map->texture->relative_filename.data);
|
||||
ok = false;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d: Material '%s' %s.%s missing texture, expected '%s'\n", filename, line,
|
||||
material->name.data, dots[0], dots[1], tex_name);
|
||||
ok = false;
|
||||
}
|
||||
} else {
|
||||
size_t tok_start = 1;
|
||||
bool implicit = false;
|
||||
bool widen = false;
|
||||
for (;;) {
|
||||
const char *tok = tokens[tok_start];
|
||||
if (!strcmp(tok, "implicit")) {
|
||||
implicit = true;
|
||||
} else if (!strcmp(tok, "widen")) {
|
||||
widen = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
tok_start++;
|
||||
}
|
||||
|
||||
double ref[4];
|
||||
size_t num_ref = 0;
|
||||
for (; num_ref < 4; num_ref++) {
|
||||
const char *tok = tokens[tok_start + num_ref];
|
||||
if (!*tok) break;
|
||||
|
||||
char *end = NULL;
|
||||
ref[num_ref] = strtod(tok, &end);
|
||||
if (!end || *end != '\0') {
|
||||
fprintf(stderr, "%s:%d: Bad number in '%s': '%s'\n", filename, line, tokens[0], tok);
|
||||
ok = false;
|
||||
num_ref = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_ref == 0) continue;
|
||||
|
||||
if (!implicit && !map->has_value) {
|
||||
fprintf(stderr, "%s:%d: Material '%s' %s.%s not defined in material\n", filename, line,
|
||||
material->name.data, dots[0], dots[1]);
|
||||
ok = false;
|
||||
continue;
|
||||
} else if (implicit && map->has_value) {
|
||||
fprintf(stderr, "%s:%d: Material '%s' %s.%s defined in material, expected implicit\n", filename, line,
|
||||
material->name.data, dots[0], dots[1]);
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!implicit && !widen && (size_t)map->value_components != num_ref) {
|
||||
fprintf(stderr, "%s:%d: Material '%s' %s.%s has wrong number of components: got %zu, expected %zu\n", filename, line,
|
||||
material->name.data, dots[0], dots[1], (size_t)map->value_components, num_ref);
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (widen && map->value_components >= num_ref) {
|
||||
fprintf(stderr, "%s:%d: Material '%s' %s.%s exected to be widened got %zu components, expected %zu\n", filename, line,
|
||||
material->name.data, dots[0], dots[1], (size_t)map->value_components, num_ref);
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
char mat_str[128];
|
||||
char ref_str[128];
|
||||
size_t mat_pos = 0;
|
||||
size_t ref_pos = 0;
|
||||
|
||||
bool equal = true;
|
||||
for (size_t i = 0; i < num_ref; i++) {
|
||||
double mat_value = map->value_vec4.v[i];
|
||||
double ref_value = ref[i];
|
||||
double err = fabs(mat_value - ref_value);
|
||||
if (err > 0.002) {
|
||||
equal = false;
|
||||
}
|
||||
|
||||
err_sum += err;
|
||||
if (err > err_max) err_max = err;
|
||||
err_num += 1;
|
||||
|
||||
if (i > 0) {
|
||||
mat_pos += (size_t)snprintf(mat_str + mat_pos, sizeof(mat_str) - mat_pos, ", ");
|
||||
ref_pos += (size_t)snprintf(ref_str + ref_pos, sizeof(ref_str) - ref_pos, ", ");
|
||||
}
|
||||
|
||||
mat_pos += (size_t)snprintf(mat_str + mat_pos, sizeof(mat_str) - mat_pos, "%.3f", mat_value);
|
||||
ref_pos += (size_t)snprintf(ref_str + ref_pos, sizeof(ref_str) - ref_pos, "%.3f", ref_value);
|
||||
}
|
||||
|
||||
if (!equal) {
|
||||
fprintf(stderr, "%s:%d: Material '%s' %s.%s has wrong value: got (%s), expected (%s)\n", filename, line,
|
||||
material->name.data, dots[0], dots[1], mat_str, ref_str);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (!strcmp(dots[0], "features")) {
|
||||
ufbx_material_feature name = (ufbx_material_feature)UFBX_MATERIAL_FEATURE_COUNT;
|
||||
for (size_t i = 0; i < UFBX_MATERIAL_FEATURE_COUNT; i++) {
|
||||
const char *str = ufbxt_material_feature_name((ufbx_material_feature)i);
|
||||
if (!strcmp(dots[1], str)) {
|
||||
name = (ufbx_material_feature)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == (ufbx_material_feature)UFBX_MATERIAL_FEATURE_COUNT) {
|
||||
fprintf(stderr, "%s:%d: Unknown material feature '%s' in '%s'\n", filename, line, dots[1], tokens[0]);
|
||||
ok = false;
|
||||
}
|
||||
|
||||
ufbx_material_feature_info *feature = &material->features.features[name];
|
||||
|
||||
char *end = NULL;
|
||||
long enabled = strtol(tokens[1], &end, 10);
|
||||
if (!end || *end != '\0') {
|
||||
fprintf(stderr, "%s:%d: Bad value in '%s': '%s'\n", filename, line, tokens[0], tokens[1]);
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (enabled != (long)feature->enabled) {
|
||||
fprintf(stderr, "%s:%d: Material '%s' features.%s mismatch: got %ld, expected %ld\n", filename, line,
|
||||
material->name.data, dots[1], (long)feature->enabled, enabled);
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
} else if (!strcmp(dots[0], "shader_type")) {
|
||||
ufbx_shader_type name = (ufbx_shader_type)UFBX_SHADER_TYPE_COUNT;
|
||||
for (size_t i = 0; i < UFBX_SHADER_TYPE_COUNT; i++) {
|
||||
const char *str = ufbxt_shader_type_name((ufbx_shader_type)i);
|
||||
if (!strcmp(tokens[1], str)) {
|
||||
name = (ufbx_shader_type)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == (ufbx_shader_type)UFBX_SHADER_TYPE_COUNT) {
|
||||
fprintf(stderr, "%s:%d: Unknown shader type '%s' in '%s'\n", filename, line, tokens[1], tokens[0]);
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (material->shader_type != name) {
|
||||
const char *mat_name = ufbxt_shader_type_name(material->shader_type);
|
||||
fprintf(stderr, "%s:%d: Material '%s' shader type mismatch: got '%s', expected '%s'\n", filename, line,
|
||||
material->name.data, mat_name, tokens[1]);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d: Invalid token '%s'\n", filename, line, tokens[0]);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (require_all) {
|
||||
for (size_t i = 0; i < scene->materials.count; i++) {
|
||||
if (!seen_materials[i]) {
|
||||
fprintf(stderr, "%s: 'require all': Material in FBX not described: '%s'\n", filename,
|
||||
scene->materials.data[i]->name.data);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
double avg = err_num > 0 ? err_sum / (double)err_num : 0.0;
|
||||
printf("Checked %zu materials, %zu properties (error avg %.3g, max %.3g, %zu tests)\n", num_materials, num_props, avg, err_max, err_num);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user