commit 109941ccf0eb44d83fb12c250c79fd2e97882cb5
parent 9c19d9a02bf07a4248d90e6ffa6cb19b9f1df4f7
Author: vaplv <vaplv@free.fr>
Date: Sun, 13 Jul 2014 17:12:59 +0200
Parse the mm, imchan, o, s, t, bm and texres map options
Diffstat:
| M | src/aw.c | | | 38 | ++++++++++++++++++++++++++++++++++++++ |
| M | src/aw_c.h | | | 10 | ++++++++++ |
| M | src/aw_mtl.c | | | 104 | ++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
| M | src/aw_obj.c | | | 59 | +++++++++++++++++++---------------------------------------- |
4 files changed, 136 insertions(+), 75 deletions(-)
diff --git a/src/aw.c b/src/aw.c
@@ -1,5 +1,8 @@
+#define _POSIX_C_SOURCE 200112L /* strtok_r support */
+
#include "aw_c.h"
#include <rsys/mem_allocator.h>
+#include <string.h>
/*******************************************************************************
* Local functions
@@ -45,3 +48,38 @@ error:
}
goto exit;
}
+
+enum aw_result
+parse_floatX
+ (float* f,
+ const unsigned int count_min,
+ const unsigned int count_max,
+ const float range_min,
+ const float range_max,
+ const float default_value,
+ char** tk_ctxt)
+{
+ size_t i;
+ ASSERT(f && count_min <= count_max && range_min <= range_max && tk_ctxt);
+ ASSERT(default_value >= range_min && default_value <= range_max);
+
+ FOR_EACH(i, 0, count_max) {
+ char* real;
+ enum aw_result res;
+ if(NULL == (real = strtok_r(NULL, " ", tk_ctxt)))
+ break;
+ res = string_to_float(real, f + i);
+ if(res != AW_OK)
+ return res;
+ if(f[i] < range_min || f[i] > range_max)
+ return AW_BAD_ARGUMENT;
+ }
+ if(i < count_min)
+ return AW_BAD_ARGUMENT;
+
+ FOR_EACH(i, i, count_max)
+ f[i] = default_value;
+
+ return AW_OK;
+}
+
diff --git a/src/aw_c.h b/src/aw_c.h
@@ -38,5 +38,15 @@ read_file
const char* filename,
char** file);
+extern LOCAL_SYM enum aw_result
+parse_floatX
+ (float* f,
+ const unsigned int count_min,
+ const unsigned int count_max,
+ const float range_min,
+ const float range_max,
+ const float default_value,
+ char** tk_ctxt);
+
#endif /* AW_C_H */
diff --git a/src/aw_mtl.c b/src/aw_mtl.c
@@ -29,6 +29,12 @@ color_copy(struct color* dst, const struct color* src)
/*******************************************************************************
* Map helper data structure
******************************************************************************/
+enum map_type {
+ MAP_COMMON = BIT(0),
+ MAP_SCALAR = BIT(1),
+ MAP_BUMP = MAP_SCALAR | BIT(2)
+};
+
enum map_flag {
MAP_BLEND_U = BIT(0),
MAP_BLEND_V = BIT(1),
@@ -55,6 +61,7 @@ struct map {
float scale[3]; /* Texcoord scale */
float turbulence[3]; /* Texcoord turbulence */
size_t resolution;
+ float bump_multiplier;
};
static FINLINE void
@@ -84,6 +91,7 @@ map_copy_pod__(struct map* dst, const struct map* src)
f3_set(dst->scale, src->scale);
f3_set(dst->turbulence, src->turbulence);
dst->resolution = src->resolution;
+ dst->bump_multiplier = src->bump_multiplier;
}
static FINLINE int
@@ -111,13 +119,13 @@ struct material {
struct color diffuse;
struct color specular;
struct color transmission;
- float specular_exp;
+ float specexp;
float refraction_id;
size_t illumination; /* Illumination model identifier */
struct map ambient_map;
struct map diffuse_map;
struct map specular_map;
- struct map specular_exp_map;
+ struct map specexp_map;
struct map bump_map;
};
@@ -129,7 +137,7 @@ material_init(struct mem_allocator* allocator, struct material* mtl)
map_init(allocator, &mtl->ambient_map);
map_init(allocator, &mtl->diffuse_map);
map_init(allocator, &mtl->specular_map);
- map_init(allocator, &mtl->specular_exp_map);
+ map_init(allocator, &mtl->specexp_map);
map_init(allocator, &mtl->bump_map);
}
@@ -141,7 +149,7 @@ material_release(struct material* mtl)
map_release(&mtl->ambient_map);
map_release(&mtl->diffuse_map);
map_release(&mtl->specular_map);
- map_release(&mtl->specular_exp_map);
+ map_release(&mtl->specexp_map);
map_release(&mtl->bump_map);
}
@@ -153,7 +161,7 @@ material_copy_pod__(struct material* dst, const struct material* src)
color_copy(&dst->diffuse, &src->diffuse);
color_copy(&dst->specular, &src->specular);
color_copy(&dst->transmission, &src->transmission);
- dst->specular_exp = src->specular_exp;
+ dst->specexp = src->specexp;
dst->refraction_id = src->refraction_id;
dst->illumination = src->illumination;
}
@@ -168,7 +176,7 @@ material_copy(struct material* dst, const struct material* src)
return -1;
if(map_copy(&dst->specular_map, &src->specular_map))
return -1;
- if(map_copy(&dst->specular_exp_map, &src->specular_exp_map))
+ if(map_copy(&dst->specexp_map, &src->specexp_map))
return -1;
if(map_copy(&dst->bump_map, &src->bump_map))
return -1;
@@ -187,7 +195,7 @@ material_copy_and_release(struct material* dst, struct material* src)
return -1;
if(map_copy_and_release(&dst->specular_map, &src->specular_map))
return -1;
- if(map_copy_and_release(&dst->specular_exp_map, &src->specular_exp_map))
+ if(map_copy_and_release(&dst->specexp_map, &src->specexp_map))
return -1;
if(map_copy_and_release(&dst->bump_map, &src->bump_map))
return -1;
@@ -282,22 +290,6 @@ parse_color(struct color* col, char** word_tk)
}
static INLINE enum aw_result
-parse_float
- (float* f, const float range_min, const float range_max, char** word_tk)
-{
- char* word;
- enum aw_result res = AW_OK;
- ASSERT(f && word_tk && range_min < range_max);
-
- word = strtok_r(NULL, "\n", word_tk);
- if(AW_OK != (res = string_to_float(word, f)))
- return res;
- if(range_min > *f || range_max < *f)
- return AW_BAD_ARGUMENT;
- return AW_OK;
-}
-
-static INLINE enum aw_result
parse_size_t
(size_t* s, const size_t range_min, const size_t range_max, char** word_tk)
{
@@ -332,8 +324,37 @@ parse_bool_option
return AW_OK;
}
+static FINLINE enum aw_result
+parse_imfchan_option(enum map_channel* channel, char** tk_ctxt)
+{
+ char* word;
+ ASSERT(channel && tk_ctxt);
+ word = strtok_r(NULL, " ", tk_ctxt);
+ if(!word)
+ return AW_BAD_ARGUMENT;
+ if(!strcmp(word, "r")) {
+ *channel = MAP_CHANNEL_RED;
+ } else if(!strcmp(word, "g")) {
+ *channel = MAP_CHANNEL_GREEN;
+ } else if(!strcmp(word, "b")) {
+ *channel = MAP_CHANNEL_BLUE;
+ } else if(!strcmp(word, "m")) {
+ *channel = MAP_CHANNEL_MATTE;
+ } else if(!strcmp(word, "l")) {
+ *channel = MAP_CHANNEL_LUMINANCE;
+ } else if(!strcmp(word, "z")) {
+ *channel = MAP_CHANNEL_DEPTH;
+ } else {
+ return AW_BAD_ARGUMENT;
+ }
+ return AW_OK;
+}
+
static enum aw_result
-parse_map(struct map* map, char** tk_ctxt)
+parse_map
+ (struct map* map,
+ const enum map_type type,
+ char** tk_ctxt)
{
char* word;
ASSERT(map && tk_ctxt);
@@ -350,15 +371,26 @@ parse_map(struct map* map, char** tk_ctxt)
res = parse_bool_option(&map->mask_options, MAP_COLOR_CORRECTION,tk_ctxt);
} else if(!strcmp(word, "-clamp")) {
res = parse_bool_option(&map->mask_options, MAP_CLAMP, tk_ctxt);
- } else if(!strcmp(word, "-imfchan")) { /* Scalar texture channel */
- /* res = parse_imfchan(&map->channel, tk_ctxt); */
+ } else if(!strcmp(word, "-imfchan") && (type & MAP_SCALAR)) {
+ res = parse_imfchan_option(&map->channel, tk_ctxt);
} else if(!strcmp(word, "-mm")) { /* Image bias and scale */
- /* res = parse_float TODO */
+ res = parse_floatX
+ (&map->texture_bias, 1, 1, -FLT_MAX, FLT_MAX, 0.f, tk_ctxt);
+ if(res == AW_OK) {
+ res = parse_floatX
+ (&map->texture_scale, 1, 1, -FLT_MAX, FLT_MAX, 0.f, tk_ctxt);
+ }
} else if(!strcmp(word, "-o")) { /* Texcoord offset */
+ res = parse_floatX(map->origin, 1, 3, -FLT_MAX, FLT_MAX, 0.f, tk_ctxt);
} else if(!strcmp(word, "-s")) { /* Texcoord scale */
+ res = parse_floatX(map->scale, 1, 3, -FLT_MAX, FLT_MAX, 1.f, tk_ctxt);
} else if(!strcmp(word, "-t")) { /* Texcoord turbulence */
+ res = parse_floatX(map->turbulence, 1, 3,-FLT_MAX, FLT_MAX, 0.f, tk_ctxt);
} else if(!strcmp(word, "-texres")) { /* Texture resolution */
- } else if(!strcmp(word, "-bm")) { /* Bump multiplier */
+ res = parse_size_t(&map->resolution, 1, SIZE_MAX, tk_ctxt);
+ } else if(!strcmp(word, "-bm") && (type == MAP_BUMP)) {/* Bump multiplier */
+ res = parse_floatX
+ (&map->bump_multiplier, 1, 1, -FLT_MAX, FLT_MAX, 0.f, tk_ctxt);
} else {
do {
if(str_append(&map->filename, word))
@@ -399,21 +431,23 @@ parse_mtl_file(struct aw_mtl* mtl, const char* path, char* content)
} else if(!strcmp(word, "Tf")) { /* Transimission filter */
res = parse_color(&mtl->newmtl->transmission, &word_tk);
} else if(!strcmp(word, "Ns")) { /* Specular exponent */
- res = parse_float(&mtl->newmtl->specular_exp, 0.f, FLT_MAX, &word_tk);
+ res = parse_floatX
+ (&mtl->newmtl->specexp, 1, 1, 0.f, FLT_MAX, 0.f, &word_tk);
} else if(!strcmp(word, "Ni")) { /* Refraction index */
- res = parse_float(&mtl->newmtl->refraction_id, 0.001f, 10.f, &word_tk);
+ res = parse_floatX
+ (&mtl->newmtl->refraction_id, 1, 1, 0.001f, 10.f, 0.f, &word_tk);
} else if(!strcmp(word, "illum")) { /* Illumination model */
res = parse_size_t(&mtl->newmtl->illumination, 0, 10, &word_tk);
} else if(!strcmp(word, "map_Ka")) { /* Ambient texture */
- res = parse_map(&mtl->newmtl->ambient_map, &word_tk);
+ res = parse_map(&mtl->newmtl->ambient_map, MAP_COMMON, &word_tk);
} else if(!strcmp(word, "map_Kd")) { /* Diffuse texture */
- res = parse_map(&mtl->newmtl->diffuse_map, &word_tk);
+ res = parse_map(&mtl->newmtl->diffuse_map, MAP_COMMON, &word_tk);
} else if(!strcmp(word, "map_Ks")) { /* Specular texture */
- res = parse_map(&mtl->newmtl->specular_map, &word_tk);
+ res = parse_map(&mtl->newmtl->specular_map, MAP_COMMON, &word_tk);
} else if(!strcmp(word, "map_Ns")) { /* Specular exponent texture */
- res = parse_map(&mtl->newmtl->specular_exp_map, &word_tk);
+ res = parse_map(&mtl->newmtl->specexp_map, MAP_SCALAR, &word_tk);
} else if(!strcmp(word, "bump")) { /* Bump map */
- res = parse_map(&mtl->newmtl->bump_map, &word_tk);
+ res = parse_map(&mtl->newmtl->bump_map, MAP_BUMP, &word_tk);
} else {
res = AW_OK;
fprintf(stderr, "%s:%lu: warning: ignored or malformed directive %s\n",
diff --git a/src/aw_obj.c b/src/aw_obj.c
@@ -161,48 +161,27 @@ flush_smooth_group(struct aw_obj* obj)
}
static enum aw_result
-parse_floatX
- (char** word_tk,
- const unsigned count_min,
- const unsigned count_max,
+parse_floatX_in_darray
+ (struct darray_float* darray,
+ const unsigned int count_min,
+ const unsigned int count_max,
const float default_value,
- struct darray_float* dst)
+ char** tk_ctxt)
{
- unsigned i;
- enum aw_result res = AW_OK;
- ASSERT(word_tk && dst && count_min <= count_max);
-
- FOR_EACH(i, 0, count_max) {
- char* real;
- float f;
- if(NULL == (real = strtok_r(NULL, " ", word_tk)))
- break;
- res = string_to_float(real, &f);
- if(res != AW_OK)
- goto error;
- if(darray_float_push_back(dst, &f)) {
- res = AW_MEMORY_ERROR;
- goto error;
- }
- }
- if(i < count_min) {
- res = AW_BAD_ARGUMENT;
- goto error;
- }
+ enum aw_result res;
+ size_t i;
+ ASSERT(darray);
- FOR_EACH(i, i, count_max) {
- if(darray_float_push_back(dst, &default_value)) {
- res = AW_MEMORY_ERROR;
- goto error;
- }
- }
+ i = darray_float_size_get(darray);
+ if(darray_float_resize(darray, i + count_max))
+ return AW_MEMORY_ERROR;
-exit:
+ res = parse_floatX
+ (darray_float_data_get(darray) + i,
+ count_min, count_max, -FLT_MAX, FLT_MAX, default_value, tk_ctxt);
+ if(res != AW_OK)
+ darray_float_resize(darray, i);
return res;
-error:
- FOR_EACH_REVERSE(i, i, 0)
- darray_float_pop_back(dst);
- goto exit;
}
static enum aw_result
@@ -438,11 +417,11 @@ parse_obj_file(struct aw_obj* obj, const char* path, char* content)
if(word[0] == '#') { /* Comment */
break;
} else if(!strcmp(word, "v")) { /* Vertex position */
- res = parse_floatX(&word_tk, 3, 4, 1.f, &obj->positions);
+ res = parse_floatX_in_darray(&obj->positions, 3, 4, 1.f, &word_tk);
} else if(!strcmp(word, "vn")) { /* Vertex normal */
- res = parse_floatX(&word_tk, 3, 3, 0.f, &obj->normals);
+ res = parse_floatX_in_darray(&obj->normals, 3, 3, 0.f, &word_tk);
} else if(!strcmp(word, "vt")) { /* Vertex texture coordinates */
- res = parse_floatX(&word_tk, 1, 3, 0.f, &obj->texcoords);
+ res = parse_floatX_in_darray(&obj->texcoords, 1, 3, 0.f, &word_tk);
} else if(!strcmp(word, "f") || !strcmp(word, "fo")) { /* face element */
res = parse_face(obj, &word_tk);
} else if(!strcmp(word, "g")) { /* Grouping */