forked from blender/blender
WIP: uv-simple-select #1
@ -152,21 +152,67 @@ static void geom_add_uv_vertex(const char *p, const char *end, GlobalVertices &r
|
|||||||
r_global_vertices.uv_vertices.append(uv);
|
r_global_vertices.uv_vertices.append(uv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void geom_add_edge(Geometry *geom,
|
/**
|
||||||
|
* Parse vertex index and transform to non-negative, zero-based.
|
||||||
|
* Sets r_index to the index or INT32_MAX on error.
|
||||||
|
* Index is transformed and bounds-checked using n_vertices,
|
||||||
|
* which specifies the number of vertices that have been read before.
|
||||||
|
* Returns updated p.
|
||||||
|
*/
|
||||||
|
static const char *parse_vertex_index(const char *p, const char *end, size_t n_elems, int &r_index)
|
||||||
|
{
|
||||||
|
p = parse_int(p, end, INT32_MAX, r_index, false);
|
||||||
|
if (r_index != INT32_MAX) {
|
||||||
|
r_index += r_index < 0 ? n_elems : -1;
|
||||||
|
if (r_index < 0 || r_index >= n_elems) {
|
||||||
|
fprintf(stderr, "Invalid vertex index %i (valid range [0, %zu))\n", r_index, n_elems);
|
||||||
|
r_index = INT32_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a polyline and add its line segments as loose edges.
|
||||||
|
* We support the following polyline specifications:
|
||||||
|
* - "l v1/vt1 v2/vt2 ..."
|
||||||
|
* - "l v1 v2 ..."
|
||||||
|
* If a line only has one vertex (technically not allowed by the spec),
|
||||||
|
* no line is created, but the vertex will be added to
|
||||||
|
* the mesh even if it is unconnected.
|
||||||
|
*/
|
||||||
|
static void geom_add_polyline(Geometry *geom,
|
||||||
const char *p,
|
const char *p,
|
||||||
const char *end,
|
const char *end,
|
||||||
GlobalVertices &r_global_vertices)
|
GlobalVertices &r_global_vertices)
|
||||||
{
|
{
|
||||||
int edge_v1, edge_v2;
|
int last_vertex_index;
|
||||||
p = parse_int(p, end, -1, edge_v1);
|
p = drop_whitespace(p, end);
|
||||||
p = parse_int(p, end, -1, edge_v2);
|
p = parse_vertex_index(p, end, r_global_vertices.vertices.size(), last_vertex_index);
|
||||||
/* Always keep stored indices non-negative and zero-based. */
|
|
||||||
edge_v1 += edge_v1 < 0 ? r_global_vertices.vertices.size() : -1;
|
if (last_vertex_index == INT32_MAX) {
|
||||||
edge_v2 += edge_v2 < 0 ? r_global_vertices.vertices.size() : -1;
|
fprintf(stderr, "Skipping invalid OBJ polyline.\n");
|
||||||
BLI_assert(edge_v1 >= 0 && edge_v2 >= 0);
|
return;
|
||||||
geom->edges_.append({uint(edge_v1), uint(edge_v2)});
|
}
|
||||||
geom->track_vertex_index(edge_v1);
|
geom->track_vertex_index(last_vertex_index);
|
||||||
geom->track_vertex_index(edge_v2);
|
|
||||||
|
while (p < end) {
|
||||||
|
int vertex_index;
|
||||||
|
|
||||||
|
/* Lines can contain texture coordinate indices, just ignore them. */
|
||||||
|
p = drop_non_whitespace(p, end);
|
||||||
|
/* Skip whitespace to get to the next vertex. */
|
||||||
|
p = drop_whitespace(p, end);
|
||||||
|
|
||||||
|
p = parse_vertex_index(p, end, r_global_vertices.vertices.size(), vertex_index);
|
||||||
|
if (vertex_index == INT32_MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
geom->edges_.append({uint(last_vertex_index), uint(vertex_index)});
|
||||||
|
geom->track_vertex_index(vertex_index);
|
||||||
|
last_vertex_index = vertex_index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void geom_add_polygon(Geometry *geom,
|
static void geom_add_polygon(Geometry *geom,
|
||||||
@ -548,7 +594,7 @@ void OBJParser::parse(Vector<std::unique_ptr<Geometry>> &r_all_geometries,
|
|||||||
}
|
}
|
||||||
/* Faces. */
|
/* Faces. */
|
||||||
else if (parse_keyword(p, end, "l")) {
|
else if (parse_keyword(p, end, "l")) {
|
||||||
geom_add_edge(curr_geom, p, end, r_global_vertices);
|
geom_add_polyline(curr_geom, p, end, r_global_vertices);
|
||||||
}
|
}
|
||||||
/* Objects. */
|
/* Objects. */
|
||||||
else if (parse_keyword(p, end, "o")) {
|
else if (parse_keyword(p, end, "o")) {
|
||||||
|
@ -869,4 +869,13 @@ TEST_F(obj_importer_test, import_split_options_none)
|
|||||||
import_and_check("split_options.obj", expect, std::size(expect), 0);
|
import_and_check("split_options.obj", expect, std::size(expect), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(obj_importer_test, import_polylines)
|
||||||
|
{
|
||||||
|
Expectation expect[] = {
|
||||||
|
{"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
|
||||||
|
{"OBpolylines", OB_MESH, 13, 8, 0, 0, float3(1, 0, 0), float3(.7, .7, 2)},
|
||||||
|
};
|
||||||
|
import_and_check("polylines.obj", expect, std::size(expect), 0);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::io::obj
|
} // namespace blender::io::obj
|
||||||
|
Loading…
Reference in New Issue
Block a user