commit 8b3a01bfe49ec6870a8293c174db2f699976ec4b
parent ac865761ffd7007d8ac75386dc4a3ac46d1213fc
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 22 Nov 2016 15:38:08 +0100
Parse and load the anchors of an entity
Diffstat:
5 files changed, 352 insertions(+), 46 deletions(-)
diff --git a/cmake/parser/CMakeLists.txt b/cmake/parser/CMakeLists.txt
@@ -35,6 +35,7 @@ set(PARSER_FILES_INC
solstice_entity.h
solstice_material.h
solstice_parser.h
+ solstice_pivot.h
solstice_shape.h
solstice_sun.h)
diff --git a/src/parser/solstice_entity.h b/src/parser/solstice_entity.h
@@ -16,8 +16,9 @@
#ifndef SOLSTICE_ENTITY_H
#define SOLSTICE_ENTITY_H
-#include "solstice_shape.h"
#include "solstice_geometry.h"
+#include "solstice_pivot.h"
+#include "solstice_shape.h"
#include <rsys/double3.h>
#include <rsys/dynamic_array.h>
@@ -27,10 +28,14 @@
struct solstice_entity_id { size_t i; };
-#define DARRAY_NAME child
+#define DARRAY_NAME child_id
#define DARRAY_DATA struct solstice_entity_id
#include <rsys/dynamic_array.h>
+#define DARRAY_NAME anchor_id
+#define DARRAY_DATA struct solstice_anchor_id
+#include <rsys/dynamic_array.h>
+
/* Declare the hash table that map an entity name to the index of its in memory
* solstice representation. */
#define HTABLE_NAME str2sols
@@ -41,7 +46,7 @@ struct solstice_entity_id { size_t i; };
#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release
#define HTABLE_KEY_FUNCTOR_EQ str_eq
#define HTABLE_KEY_FUNCTOR_HASH str_hash
-#define HTABLE_DATA struct solstice_entity_id
+#define HTABLE_DATA size_t
#include <rsys/hash_table.h>
struct solstice_entity {
@@ -52,8 +57,10 @@ struct solstice_entity {
struct solstice_geometry_id geometry;
/* Internal data. Should not be acceded directly. */
+ struct htable_str2sols str2anchors;
struct htable_str2sols str2children;
- struct darray_child children; /* List of children nodes */
+ struct darray_anchor_id anchors; /* List of anchors */
+ struct darray_child_id children; /* List of children nodes */
};
static INLINE void
@@ -65,8 +72,10 @@ solstice_entity_init
d3_splat(entity->translation, 0);
entity->geometry.i = SIZE_MAX;
str_init(allocator, &entity->name);
+ htable_str2sols_init(allocator, &entity->str2anchors);
htable_str2sols_init(allocator, &entity->str2children);
- darray_child_init(allocator, &entity->children);
+ darray_anchor_id_init(allocator, &entity->anchors);
+ darray_child_id_init(allocator, &entity->children);
}
static INLINE void
@@ -74,8 +83,10 @@ solstice_entity_release(struct solstice_entity* entity)
{
ASSERT(entity);
str_release(&entity->name);
+ htable_str2sols_release(&entity->str2anchors);
htable_str2sols_release(&entity->str2children);
- darray_child_release(&entity->children);
+ darray_anchor_id_release(&entity->anchors);
+ darray_child_id_release(&entity->children);
}
static INLINE res_T
@@ -89,9 +100,13 @@ solstice_entity_copy
dst->geometry = src->geometry;
res = str_copy(&dst->name, &src->name);
if(res != RES_OK) return res;
+ res = htable_str2sols_copy(&dst->str2anchors, &src->str2anchors);
+ if(res != RES_OK) return res;
res = htable_str2sols_copy(&dst->str2children, &src->str2children);
if(res != RES_OK) return res;
- res = darray_child_copy(&dst->children, &src->children);
+ res = darray_anchor_id_copy(&dst->anchors, &src->anchors);
+ if(res != RES_OK) return res;
+ res = darray_child_id_copy(&dst->children, &src->children);
if(res != RES_OK) return res;
return RES_OK;
}
@@ -107,25 +122,43 @@ solstice_entity_copy_and_release
dst->geometry = src->geometry;
res = str_copy_and_release(&dst->name, &src->name);
if(res != RES_OK) return res;
+ res = htable_str2sols_copy_and_release(&dst->str2anchors, &src->str2anchors);
+ if(res != RES_OK) return res;
res = htable_str2sols_copy_and_release(&dst->str2children, &src->str2children);
if(res != RES_OK) return res;
- res = darray_child_copy_and_release(&dst->children, &src->children);
+ res = darray_anchor_id_copy_and_release(&dst->anchors, &src->anchors);
+ if(res != RES_OK) return res;
+ res = darray_child_id_copy_and_release(&dst->children, &src->children);
if(res != RES_OK) return res;
return RES_OK;
}
static INLINE size_t
+solstice_entity_get_anchors_count(const struct solstice_entity* entity)
+{
+ ASSERT(entity);
+ return darray_anchor_id_size_get(&entity->anchors);
+}
+
+static INLINE struct solstice_anchor_id
+solstice_entity_get_anchor(const struct solstice_entity* entity, const size_t i)
+{
+ ASSERT(entity && i < solstice_entity_get_anchors_count(entity));
+ return darray_anchor_id_cdata_get(&entity->anchors)[i];
+}
+
+static INLINE size_t
solstice_entity_get_children_count(const struct solstice_entity* entity)
{
ASSERT(entity);
- return darray_child_size_get(&entity->children);
+ return darray_child_id_size_get(&entity->children);
}
static INLINE struct solstice_entity_id
solstice_entity_get_child(const struct solstice_entity* entity, const size_t i)
{
ASSERT(entity && i < solstice_entity_get_children_count(entity));
- return darray_child_cdata_get(&entity->children)[i];
+ return darray_child_id_cdata_get(&entity->children)[i];
}
#endif /* SOLSTICE_ENTITY_H */
diff --git a/src/parser/solstice_parser.c b/src/parser/solstice_parser.c
@@ -18,6 +18,7 @@
#include "solstice_entity.h"
#include "solstice_material.h"
#include "solstice_parser.h"
+#include "solstice_pivot.h"
#include "solstice_shape.h"
#include "solstice_sun.h"
@@ -125,6 +126,15 @@
#define DARRAY_FUNCTOR_COPY_AND_RELEASE solstice_entity_copy_and_release
#include <rsys/dynamic_array.h>
+/* Declare the array of anchors */
+#define DARRAY_NAME anchor
+#define DARRAY_DATA struct solstice_anchor
+#define DARRAY_FUNCTOR_INIT solstice_anchor_init
+#define DARRAY_FUNCTOR_RELEASE solstice_anchor_release
+#define DARRAY_FUNCTOR_COPY solstice_anchor_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE solstice_anchor_copy_and_release
+#include <rsys/dynamic_array.h>
+
/* Declare the hash table that maps the address of a YAML node to the id of its
* in memory representation. */
#define HTABLE_NAME yaml2sols
@@ -169,6 +179,9 @@ struct solstice_parser {
struct htable_str2sols str2entities;
struct darray_entity entities;
+ /* Anchors */
+ struct darray_anchor anchors;
+
ref_T ref;
struct mem_allocator* allocator;
};
@@ -256,10 +269,13 @@ parser_clear(struct solstice_parser* parser)
solstice_sun_clear(&parser->sun);
parser->sun_key = 0;
- /* Tree */
+ /* Entitiies */
htable_yaml2sols_clear(&parser->yaml2entities);
htable_str2sols_clear(&parser->str2entities);
darray_entity_clear(&parser->entities);
+
+ /* Anchors */
+ darray_anchor_clear(&parser->anchors);
}
static void
@@ -298,11 +314,14 @@ parser_release(ref_T* ref)
/* Sun */
solstice_sun_release(&parser->sun);
- /* Tree */
+ /* Entities */
htable_yaml2sols_release(&parser->yaml2entities);
htable_str2sols_release(&parser->str2entities);
darray_entity_release(&parser->entities);
+ /* Anchors */
+ darray_anchor_release(&parser->anchors);
+
MEM_RM(parser->allocator, parser);
}
@@ -1932,8 +1951,7 @@ entity_register_name
const size_t isolent)
{
struct solstice_entity* solent;
- struct solstice_entity_id* pisolent;
- struct solstice_entity_id id;
+ size_t* pisolent;
res_T res = RES_OK;
ASSERT(parser && htable);
ASSERT(isolent < darray_entity_size_get(&parser->entities));
@@ -1948,8 +1966,7 @@ entity_register_name
return RES_BAD_ARG;
}
- id.i = isolent;
- res = htable_str2sols_set(htable, &solent->name, &id);
+ res = htable_str2sols_set(htable, &solent->name, &isolent);
if(res != RES_OK) {
log_err(parser, entity, "could not register the entity.\n");
return res;
@@ -1958,67 +1975,229 @@ entity_register_name
}
static res_T
-parse_children
+anchor_register_name
+ (struct solstice_parser* parser,
+ const yaml_node_t* anchor,
+ struct htable_str2sols* htable,
+ const size_t isolanchor)
+{
+ struct solstice_anchor* solanchor;
+ size_t* pisolanchor;
+ res_T res = RES_OK;
+ ASSERT(parser && htable);
+ ASSERT(isolanchor < darray_anchor_size_get(&parser->anchors));
+
+ solanchor = darray_anchor_data_get(&parser->anchors) + isolanchor;
+
+ pisolanchor = htable_str2sols_find(htable, &solanchor->name);
+ if(pisolanchor) {
+ log_err(parser, anchor,
+ "an anchor with the name `%s' is already defined in the cunrrent context.\n",
+ str_cget(&solanchor->name));
+ return RES_BAD_ARG;
+ }
+
+ res = htable_str2sols_set(htable, &solanchor->name, &isolanchor);
+ if(res != RES_OK) {
+ log_err(parser, anchor, "could not register the anchor.\n");
+ return res;
+ }
+ return RES_OK;
+}
+
+static res_T
+parse_identifier_string
+ (struct solstice_parser* parser,
+ yaml_node_t* name,
+ struct str* str)
+{
+ res_T res = RES_OK;
+ ASSERT(parser && name && str);
+
+ res = parse_string(parser, name, str);
+ if(res != RES_OK) goto error;
+
+ if(strchr(str_cget(str), '.')) {
+ log_err(parser, name, "invalid character `.' in the name `%s'.\n",
+ str_cget(str));
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_anchor
(struct solstice_parser* parser,
yaml_document_t* doc,
- const yaml_node_t* children,
+ const yaml_node_t* anchor,
struct htable_str2sols* htable,
- struct darray_child* entities)
+ struct solstice_anchor_id* out_isolanchor)
{
+ enum { NAME, POSITION };
+ struct solstice_anchor* solanchor = NULL;
+ size_t isolanchor = SIZE_MAX;
intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
res_T res = RES_OK;
- ASSERT(doc && children && htable && entities);
+ ASSERT(parser && anchor && out_isolanchor);
- if(children->type != YAML_SEQUENCE_NODE) {
- log_err(parser, children, "expect a list of entities.\n");
+ if(anchor->type == YAML_MAPPING_NODE) {
+ log_err(parser, anchor, "expect an anchor definition.\n");
res = RES_BAD_ARG;
goto error;
}
- n = children->data.sequence.items.top - children->data.sequence.items.start;
- res = darray_child_resize(entities, (size_t)n);
+ /* Allocate the anchor */
+ isolanchor = darray_anchor_size_get(&parser->anchors);
+ res = darray_anchor_resize(&parser->anchors, isolanchor + 1);
if(res != RES_OK) {
- log_err(parser, children, "could not allocate the children list.\n");
+ log_err(parser, anchor, "could not allocate the anchor.\n");
goto error;
}
+ solanchor = darray_anchor_data_get(&parser->anchors) + isolanchor;
+ n = anchor->data.mapping.pairs.top - anchor->data.mapping.pairs.start;
FOR_EACH(i, 0, n) {
- struct solstice_entity_id* entity_id = darray_child_data_get(entities) + i;
- yaml_node_t* child;
+ yaml_node_t* key;
+ yaml_node_t* val;
- child = yaml_document_get_node(doc, children->data.sequence.items.start[i]);
- res = parse_entity(parser, doc, child, htable, entity_id);
+ key = yaml_document_get_node(doc, anchor->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, anchor->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect an anchor attribute.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, "the anchor "Name" is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "name")) {
+ SETUP_MASK(NAME, "name");
+ res = parse_identifier_string(parser, val, &solanchor->name);
+ } else if(!strcmp((char*)key->data.scalar.value, "position")) {
+ SETUP_MASK(POSITION, "position");
+ res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solanchor->position);
+ } else {
+ log_err(parser, key, "unknown anchor parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
if(res != RES_OK) goto error;
+ #undef SETUP_MASK
}
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, anchor, "the anchor "Name" is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(NAME, "name");
+ CHECK_PARAM(POSITION, "position");
+ #undef CHECK_PARAM
+
+ res = anchor_register_name(parser, anchor, htable, isolanchor);
+ if(res != RES_OK) goto error;
+
exit:
+ out_isolanchor->i = isolanchor;
return res;
error:
- darray_child_clear(entities);
+ if(solanchor) {
+ darray_anchor_pop_back(&parser->anchors);
+ isolanchor = SIZE_MAX;
+ }
goto exit;
}
static res_T
-parse_entity_name
+parse_anchors
(struct solstice_parser* parser,
- yaml_node_t* name,
- struct str* str)
+ yaml_document_t* doc,
+ const yaml_node_t* anchors,
+ struct htable_str2sols* htable,
+ struct darray_anchor_id* solanchors)
{
+ intptr_t i, n;
res_T res = RES_OK;
- ASSERT(parser && name && str);
+ ASSERT(parser && anchors);
- res = parse_string(parser, name, str);
- if(res != RES_OK) goto error;
+ if(anchors->type != YAML_SEQUENCE_NODE) {
+ log_err(parser, anchors, "expect a list of anchors.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
- if(strchr(str_cget(str), '.')) {
- log_err(parser, name, "invalid character `.' in the entity name `%s'.\n",
- str_cget(str));
+ n = anchors->data.sequence.items.top - anchors->data.sequence.items.start;
+ res = darray_anchor_id_resize(solanchors, (size_t)n);
+ if(res != RES_OK) {
+ log_err(parser, anchors, "could not allocate the anchors list.\n");
+ goto error;
+ }
+
+ FOR_EACH(i, 0, n) {
+ struct solstice_anchor_id* anchor_id;
+ yaml_node_t* anchor;
+
+ anchor_id = darray_anchor_id_data_get(solanchors)+i;
+ anchor = yaml_document_get_node(doc, anchors->data.sequence.items.start[i]);
+ res = parse_anchor(parser, doc, anchor, htable, anchor_id);
+ if(res != RES_OK) goto error;
+ }
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_children
+ (struct solstice_parser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* children,
+ struct htable_str2sols* htable,
+ struct darray_child_id* entities)
+{
+ intptr_t i, n;
+ res_T res = RES_OK;
+ ASSERT(parser && children && htable && entities);
+
+ if(children->type != YAML_SEQUENCE_NODE) {
+ log_err(parser, children, "expect a list of entities.\n");
+ res = RES_BAD_ARG;
goto error;
}
+ n = children->data.sequence.items.top - children->data.sequence.items.start;
+ res = darray_child_id_resize(entities, (size_t)n);
+ if(res != RES_OK) {
+ log_err(parser, children, "could not allocate the children list.\n");
+ goto error;
+ }
+
+ FOR_EACH(i, 0, n) {
+ struct solstice_entity_id* entity_id = darray_child_id_data_get(entities) + i;
+ yaml_node_t* child;
+
+ child = yaml_document_get_node(doc, children->data.sequence.items.start[i]);
+ res = parse_entity(parser, doc, child, htable, entity_id);
+ if(res != RES_OK) goto error;
+ }
+
exit:
return res;
error:
+ darray_child_id_clear(entities);
goto exit;
}
@@ -2030,7 +2209,7 @@ parse_entity
struct htable_str2sols* htable,
struct solstice_entity_id* out_isolent)
{
- enum { CHILDREN, DATA, NAME, TRANSFORM };
+ enum { ANCHORS, CHILDREN, DATA, NAME, TRANSFORM };
struct solstice_entity* solent = NULL;
const size_t *pisolent;
size_t isolent = SIZE_MAX;
@@ -2085,7 +2264,11 @@ parse_entity
} \
mask |= BIT(Flag); \
} (void)0
- if(!strcmp((char*)key->data.scalar.value, "children")) {
+ if(!strcmp((char*)key->data.scalar.value, "anchors")) {
+ SETUP_MASK(ANCHORS, "anchors");
+ res = parse_anchors
+ (parser, doc, val, &solent->str2anchors, &solent->anchors);
+ } else if(!strcmp((char*)key->data.scalar.value, "children")) {
SETUP_MASK(CHILDREN, "children");
res = parse_children
(parser, doc, val, &solent->str2children, &solent->children);
@@ -2094,7 +2277,7 @@ parse_entity
res = parse_geometry(parser, doc, val, &solent->geometry);
} else if(!strcmp((char*)key->data.scalar.value, "name")) {
SETUP_MASK(NAME, "name");
- res = parse_entity_name(parser, val, &solent->name);
+ res = parse_identifier_string(parser, val, &solent->name);
} else if(!strcmp((char*)key->data.scalar.value, "pivot")) {
SETUP_MASK(DATA, "data");
res = parse_pivot(parser, doc, val);
@@ -2650,11 +2833,14 @@ solstice_parser_create
solstice_sun_init(mem_allocator, &parser->sun);
- /* Tree */
+ /* Entities */
htable_yaml2sols_init(mem_allocator, &parser->yaml2entities);
htable_str2sols_init(mem_allocator, &parser->str2entities);
darray_entity_init(mem_allocator, &parser->entities);
+ /* Anchors */
+ darray_anchor_init(mem_allocator, &parser->anchors);
+
exit:
*out_parser = parser;
return res;
@@ -2820,14 +3006,14 @@ solstice_parser_find_entity
tk = strtok(cstr, ".");
htable = &parser->str2entities;
while(tk) {
- struct solstice_entity_id* pientity;
+ size_t* pientity;
str_set(&str_tk, tk);
pientity = htable_str2sols_find(htable, &str_tk);
if(!pientity) {
tk = NULL;
} else {
tk = strtok(NULL, ".");
- entity = darray_entity_data_get(&parser->entities) + pientity->i;
+ entity = darray_entity_data_get(&parser->entities) + *pientity;
htable = &entity->str2children;
}
}
diff --git a/src/parser/solstice_parser.h b/src/parser/solstice_parser.h
@@ -187,8 +187,10 @@ solstice_entity_iterator_eq
static FINLINE struct solstice_entity_id
solstice_entity_iterator_get(struct solstice_entity_iterator* it)
{
+ struct solstice_entity_id id;
ASSERT(it);
- return *htable_str2sols_iterator_data_get(&it->it__);
+ id.i = *htable_str2sols_iterator_data_get(&it->it__);
+ return id;
}
/*******************************************************************************
diff --git a/src/parser/solstice_pivot.h b/src/parser/solstice_pivot.h
@@ -0,0 +1,84 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SOLSTICE_PIVOT_H
+#define SOLSTICE_PIVOT_H
+
+#include <rsys/double3.h>
+
+enum solstice_target_type {
+ SOLSTICE_TARGET_ANCHOR,
+ SOLSTICE_TARGET_DIRECTION,
+ SOLSTICE_TARGET_POSITION,
+ SOLSTICE_TARGET_SUN
+};
+
+struct solstice_anchor_id { size_t i; };
+
+struct solstice_anchor {
+ struct str name;
+ double position[3];
+};
+
+static INLINE void
+solstice_anchor_init
+ (struct mem_allocator* allocator, struct solstice_anchor* anchor)
+{
+ ASSERT(anchor);
+ str_init(allocator, &anchor->name);
+}
+
+static INLINE void
+solstice_anchor_release(struct solstice_anchor* anchor)
+{
+ ASSERT(anchor);
+ str_release(&anchor->name);
+}
+
+static INLINE res_T
+solstice_anchor_copy
+ (struct solstice_anchor* dst, const struct solstice_anchor* src)
+{
+ ASSERT(dst && src);
+ d3_set(dst->position, src->position);
+ return str_copy(&dst->name, &src->name);
+}
+
+static INLINE res_T
+solstice_anchor_copy_and_release
+ (struct solstice_anchor* dst, struct solstice_anchor* src)
+{
+ ASSERT(dst && src);
+ d3_set(dst->position, src->position);
+ return str_copy_and_release(&dst->name, &src->name);
+}
+
+struct solstice_pivot {
+ double point[3];
+ double normal[3];
+ double position[3];
+ double rotation[3];
+ enum solstice_target_type target_type;
+ union {
+ double position[3]; /* World space position */
+ double direction[3]; /* World space direction */
+ struct solstice_anchor_id anchor;
+ } target;
+};
+
+struct solstice_pivot_id { size_t i; };
+
+#endif /* SOLSTICE_PIVOT_H */
+