1#include "simple_mesh.h"
4#include <cgv/math/inv.h>
7#include <cgv/media/mesh/obj_reader.h>
8#include <cgv/math/bucket_sort.h>
15std::string simple_mesh_base::get_attribute_name(attribute_type attr)
17 const char* attribute_names[] = {
"position",
"texcoords",
"normal",
"tangent",
"color" };
18 return attribute_names[int(attr)];
23 return attribute_flags[int(attr)];
30 position_indices(smb.position_indices),
31 normal_indices(smb.normal_indices),
32 tex_coord_indices(smb.tex_coord_indices),
34 group_indices(smb.group_indices),
35 group_names(smb.group_names),
36 material_indices(smb.material_indices),
37 materials(smb.materials)
42 position_indices(std::move(smb.position_indices)),
43 normal_indices(std::move(smb.normal_indices)),
44 tex_coord_indices(std::move(smb.tex_coord_indices)),
45 faces(std::move(smb.faces)),
46 group_indices(std::move(smb.group_indices)),
47 group_names(std::move(smb.group_names)),
48 material_indices(std::move(smb.material_indices)),
49 materials(std::move(smb.materials))
55 position_indices=smb.position_indices;
56 normal_indices=smb.normal_indices;
57 tex_coord_indices=smb.tex_coord_indices;
59 group_indices=smb.group_indices;
60 group_names=smb.group_names;
61 material_indices=smb.material_indices;
62 materials = smb.materials;
68 position_indices=std::move(smb.position_indices);
69 normal_indices=std::move(smb.normal_indices);
70 tex_coord_indices=std::move(smb.tex_coord_indices);
71 faces=std::move(smb.faces);
72 group_indices=std::move(smb.group_indices);
73 group_names=std::move(smb.group_names);
74 material_indices=std::move(smb.material_indices);
75 materials = std::move(smb.materials);
81 if (!materials.empty())
82 material_indices.push_back(
idx_type(materials.size()) - 1);
83 if (!group_names.empty())
84 group_indices.push_back(
idx_type(group_names.size()) - 1);
90 position_indices.push_back(position_index);
91 if (normal_index != -1)
92 normal_indices.push_back(normal_index);
93 if (tex_coord_index != -1)
94 tex_coord_indices.push_back(tex_coord_index);
95 return idx_type(position_indices.size());
99 bool nmls = position_indices.size() == normal_indices.size();
100 bool tcs = position_indices.size() == tex_coord_indices.size();
104 while (ci + 1 < cj) {
106 std::swap(position_indices[ci], position_indices[cj]);
108 std::swap(normal_indices[ci], normal_indices[cj]);
110 std::swap(tex_coord_indices[ci], tex_coord_indices[cj]);
117 if (by_group && by_material) {
118 std::vector<idx_type> perm0;
119 cgv::math::bucket_sort(group_indices,
get_nr_groups(), perm0);
123 cgv::math::bucket_sort(group_indices,
get_nr_groups(), perm);
127void simple_mesh_base::merge_indices(std::vector<idx_type>& indices, std::vector<idx4_type>& unique_quadruples,
bool* include_tex_coords_ptr,
bool* include_normals_ptr,
bool* include_tangents_ptr)
const
129 bool include_tex_coords =
false;
130 if (include_tex_coords_ptr)
131 *include_tex_coords_ptr = include_tex_coords = (tex_coord_indices.size() > 0) && *include_tex_coords_ptr;
133 bool include_normals =
false;
134 if (include_normals_ptr)
135 *include_normals_ptr = include_normals = (normal_indices.size() > 0) && *include_normals_ptr;
137 bool include_tangents =
false;
138 if(include_tangents_ptr)
139 *include_tangents_ptr = include_tangents = (tangent_indices.size() > 0) && *include_tangents_ptr;
141 std::map<std::tuple<idx_type, idx_type, idx_type, idx_type>,
idx_type> corner_to_index;
142 for (
idx_type ci = 0; ci < position_indices.size(); ++ci) {
145 (include_tex_coords && ci < tex_coord_indices.size()) ? tex_coord_indices[ci] : 0,
146 (include_normals && ci < normal_indices.size()) ? normal_indices[ci] : 0,
147 (include_tangents && ci < tangent_indices.size()) ? tangent_indices[ci] : 0);
148 std::tuple<idx_type, idx_type, idx_type, idx_type> quadruple(c(0),c(1),c(2),c(3));
150 auto iter = corner_to_index.find(quadruple);
153 if (iter == corner_to_index.end()) {
154 vi =
idx_type(unique_quadruples.size());
155 corner_to_index[quadruple] = vi;
156 unique_quadruples.push_back(c);
161 indices.push_back(vi);
165 const std::vector<idx_type>& vertex_indices, std::vector<idx_type>& triangle_element_buffer,
166 const std::vector<idx_type>* face_permutation_ptr, std::vector<idx3_type>* material_group_start_ptr)
const
171 for (
idx_type fi = 0; fi < faces.size(); ++fi) {
172 idx_type fj = face_permutation_ptr ? face_permutation_ptr->at(fi) : fi;
173 if (material_group_start_ptr) {
174 if (mi != material_indices[fj] || gi != group_indices[fj]) {
175 mi = material_indices[fj];
176 gi = group_indices[fj];
177 material_group_start_ptr->push_back(
idx3_type(mi, gi,
idx_type(triangle_element_buffer.size())));
182 triangle_element_buffer.push_back(vertex_indices.at(ci));
187 triangle_element_buffer.push_back(vertex_indices.at(
begin_corner(fj)));
188 triangle_element_buffer.push_back(vertex_indices.at(ci - 1));
189 triangle_element_buffer.push_back(vertex_indices.at(ci));
197 std::map<std::tuple<idx_type, idx_type>,
idx_type> halfedge_to_count;
198 for (
idx_type fi = 0; fi < faces.size(); ++fi) {
202 idx_type vi = vertex_indices.at(ci);
203 std::tuple<idx_type, idx_type> halfedge(last_vi, vi);
205 std::swap(std::get<0>(halfedge), std::get<1>(halfedge));
208 auto iter = halfedge_to_count.find(halfedge);
211 if (iter == halfedge_to_count.end()) {
212 halfedge_to_count[halfedge] = 1;
213 edge_element_buffer.push_back(last_vi);
214 edge_element_buffer.push_back(vi);
217 ++halfedge_to_count[halfedge];
225 if (position_indices.empty() && (flags & AF_position))
227 if (tex_coord_indices.empty() && (flags &
AF_texcoords))
229 if (normal_indices.empty() && (flags &
AF_normal))
231 if (tangent_indices.empty() && (flags &
AF_tangent))
235 bool include_attribute[5] = { bool(flags&AF_position),bool(flags&
AF_texcoords),
239 uint32_t attribute_size[5] = { 3 * cs,2 * cs,3 * cs,3 * cs,uint32_t(
get_color_size()) };
242 for (
int ai = 0; ai < 5; ++ai)
243 if (include_attribute[ai])
244 vs += attribute_offset[ai];
245 attrib_buffer.resize(vs * unique_quadruples.size());
247 const uint8_t* attrib_ptrs[5] = {
248 include_attribute[0] ? get_attribute_ptr(attribute_type::position) :
nullptr,
249 include_attribute[1] ? get_attribute_ptr(attribute_type::texcoords) :
nullptr,
250 include_attribute[2] ? get_attribute_ptr(attribute_type::normal) :
nullptr,
251 include_attribute[3] ? get_attribute_ptr(attribute_type::tangent) :
nullptr,
252 include_attribute[4] ? get_attribute_ptr(attribute_type::color) :
nullptr
255 for (
auto t : unique_quadruples) {
256 for (
int ai = 0; ai < 5; ++ai)
257 if (include_attribute[ai]) {
258 const uint8_t* src_ptr = attrib_ptrs[ai] + attribute_size[ai] * t[ai & 3];
259 std::copy(src_ptr, src_ptr + attribute_size[ai], &attrib_buffer[loc]);
260 loc += attribute_offset[ai];
266 std::vector<idx_type>& inv,
267 bool link_non_manifold_edges,
268 std::vector<idx_type>* p2c_ptr,
269 std::vector<idx_type>* next_ptr,
270 std::vector<idx_type>* prev_ptr,
271 std::vector<idx_type>* unmatched,
272 std::vector<idx_type>* non_manifold,
273 std::vector<idx_type>* unmatched_elements,
274 std::vector<idx_type>* non_manifold_elements)
const
290 for (
idx_type ci = cb; ci < ce; ++ci) {
293 p2c_ptr->at(pi) = ci;
295 next_ptr->at(cp) = ci;
297 prev_ptr->at(ci) = cp;
298 pis[cp] = std::min(pp, pi);
313 for (
idx_type ci = cb; ci < ce; ++ci) {
315 pis[cp] = std::max(
c2p(cp), pi);
327 for (
idx_type ci = cb; ci < ce; ++ci) {
335 while (i < perm.size()) {
336 idx_type ci = perm[i], pi0 =
c2p(ci), pi1 = pis[ci];
338 while (i + cnt < perm.size()) {
339 idx_type cj = perm[i + cnt], pj0 =
c2p(cj), pj1 = pis[cj];
340 if (std::min(pi0, pi1) == std::min(pj0, pj1) && std::max(pi0, pi1) == std::max(pj0, pj1)) {
348 unmatched->push_back(ci);
349 if (unmatched_elements) {
350 unmatched_elements->push_back(pi0);
351 unmatched_elements->push_back(pi1);
355 inv[perm[i]] = perm[i + 1];
356 inv[perm[i + 1]] = perm[i];
360 if (link_non_manifold_edges) {
362 for (
idx_type k = 0; k < cnt; ++k) {
369 non_manifold->push_back(ci);
370 if (non_manifold_elements) {
371 non_manifold_elements->push_back(pi0);
372 non_manifold_elements->push_back(pi1);
415 c2e[ci] = c2e[inv[ci]] = e;
435 for (
unsigned vi = 0; vi < loader.vertices.size(); ++vi)
436 new_position(loader.vertices[vi]);
437 for (
unsigned ni = 0; ni < loader.normals.size(); ++ni)
438 new_normal(loader.normals[ni]);
439 for (
unsigned ti = 0; ti < loader.texcoords.size(); ++ti)
440 new_tex_coord(loader.texcoords[ti]);
442 for (
unsigned gi = 0; gi < loader.groups.size(); ++gi)
443 new_group(loader.groups[gi].name);
444 if (copy_material_info)
445 for (
unsigned mi = 0; mi < loader.materials.size(); ++mi)
446 ref_material(new_material()) = loader.materials[mi];
447 for (
unsigned fi = 0; fi < loader.faces.size(); ++fi) {
449 const auto& F = loader.faces[fi];
450 if (copy_grp_info && !loader.groups.empty())
451 group_index(fi) = F.group_index;
452 if (copy_material_info && !loader.materials.empty())
453 material_index(fi) = F.material_index;
454 for (
unsigned i = 0; i < F.degree; ++i) {
456 loader.vertex_indices[F.first_vertex_index + i],
457 F.first_normal_index != -1 ? loader.normal_indices[F.first_normal_index + i] : -1,
458 F.first_texcoord_index != -1 ? loader.texcoord_indices[F.first_texcoord_index + i] : -1
491 void process_face(
unsigned vcount,
int *vertices,
int *texcoords,
int *normals)
494 mesh.faces.push_back(idx_type(mesh.position_indices.size()));
500 if (mesh.tex_coord_indices.size() < mesh.position_indices.size())
501 mesh.tex_coord_indices.resize(mesh.position_indices.size(), 0);
504 if (mesh.normal_indices.size() < mesh.position_indices.size())
505 mesh.normal_indices.resize(mesh.position_indices.size(), 0);
507 for (idx_type i = 0; i < vcount; ++i) {
508 mesh.position_indices.push_back(idx_type(vertices[i]));
510 mesh.tex_coord_indices.push_back(idx_type(texcoords[i]));
512 mesh.normal_indices.push_back(idx_type(normals[i]));
518 mesh.group_names.push_back(name);
523 if (idx >= mesh.materials.size())
524 mesh.materials.resize(idx+1);
525 mesh.materials[idx] = mtl;
533 :
simple_mesh_base(sm), positions(sm.positions), normals(sm.normals), tex_coords(sm.tex_coords)
540 :
simple_mesh_base(std::move(sm)), positions(std::move(sm.positions)), normals(std::move(sm.normals)),
541 tex_coords(std::move(sm.tex_coords))
550 positions = sm.positions;
551 normals = sm.normals;
552 tangents = sm.tangents;
553 tex_coords = sm.tex_coords;
562 positions = std::move(sm.positions);
563 normals = std::move(sm.normals);
564 tangents = std::move(sm.tangents);
565 tex_coords = std::move(sm.tex_coords);
577 position_indices.clear();
578 tex_coord_indices.clear();
579 normal_indices.clear();
581 group_indices.clear();
583 material_indices.clear();
589bool read_off(
const std::string& file_name,
591 std::vector<std::vector<uint32_t>>& faces, std::vector<cgv::rgba>& face_colors)
594 if (!cgv::utils::file::read(file_name, content,
true))
596 std::vector<cgv::utils::line> lines;
598 if (!(lines[0] ==
"OFF")) {
599 std::cerr <<
"WARNING: first line in OFF file " << file_name <<
" does not contain 'OFF'" << std::endl;
602 unsigned real_li = 1;
604 for (
unsigned li = 1; li < lines.size(); ++li) {
605 if (lines[li].empty())
607 if (lines[li].begin[0] ==
'#')
610 std::vector<cgv::utils::token> toks;
613 if (toks.size() != 3) {
614 std::cerr <<
"WARNING: second line in OFF file " << file_name <<
" does provide 3 tokens" << std::endl;
618 for (
int i = 0; i < 3; ++i) {
620 std::cerr <<
"WARNING: token " << i <<
" on second line in OFF file " << file_name <<
" is not an integer value" << std::endl;
624 v = I[0]; f = I[1]; e = I[2];
625 std::cout <<
"OFF file " << file_name <<
" found " << v <<
" vertices, " << f <<
" faces, and " << e <<
" edges." << std::endl;
628 if (
int(real_li) < v+3) {
629 if (!(toks.size() == 3 || toks.size() == 6 || toks.size() == 7)) {
630 std::cerr <<
"WARNING: line of vertex " << real_li - 3 <<
" contains " << toks.size() <<
" tokens instead of 3 or 7." << std::endl;
634 for (
unsigned i = 0; i < 3; ++i) {
636 std::cerr <<
"WARNING: line of vertex " << real_li - 3 <<
" no double in XYZ component " << i <<
" but <" << toks[i] <<
">." << std::endl;
641 if (toks.size() >= 6) {
642 double c[4] = { 0,0,0,1 };
643 for (
unsigned i = 0; i+3 < toks.size(); ++i) {
645 std::cerr <<
"WARNING: line of vertex " << real_li - 3 <<
" no double in RGB[A] component " << i <<
" but <" << toks[i+3] <<
">." << std::endl;
649 while (vertex_colors.size() + 1 < positions.size())
650 vertex_colors.push_back(vertex_colors.empty() ?
cgv::rgba(0.5, 0.5, 0.5, 1.0f) : vertex_colors.back());
651 vertex_colors.push_back(
cgv::rgba(
float(c[0]),
float(c[1]),
float(c[2]),
float(1.0-c[3])));
657 std::cerr <<
"WARNING: first token on face " << faces.size() <<
" is not of type integer " << std::endl;
660 if (!(toks.size() == n + 1 || toks.size() == n + 4 || toks.size() == n + 5)) {
661 std::cerr <<
"WARNING: line of face " << faces.size() <<
" contains " << toks.size() <<
" tokens instead of " << n+1 <<
" or " << n+5 << std::endl;
665 auto& face = faces.back();
666 for (
int i = 0; i<n; ++i) {
669 std::cerr <<
"WARNING: token " << i+1 <<
" on face " << faces.size()-1 <<
" is not of type integer " << std::endl;
672 face.push_back(uint32_t(pi));
674 if (toks.size() >= n + 4) {
675 double c[4] = { 0,0,0,1 };
676 for (
unsigned i = 0; i < toks.size()-n-1; ++i) {
678 std::cerr <<
"WARNING: line of vertex " << real_li - 3 <<
" no double in RGBA component " << i <<
" but <" << toks[i + n + 1] <<
">." << std::endl;
682 while (face_colors.size()+1 < faces.size())
683 face_colors.push_back(face_colors.empty() ?
cgv::rgba(0.5, 0.5, 0.5, 1.0f) : face_colors.back());
684 face_colors.push_back(
cgv::rgba(
float(c[0]),
float(c[1]),
float(c[2]),
float(1.0 - c[3])));
703 stl_reader::StlMesh <T, unsigned> mesh(file_name);
706 for (
size_t vi = 0; vi < mesh.
num_vrts(); ++vi)
711 for (
size_t ti = 0; ti < mesh.
num_tris(); ++ti) {
715 for (
size_t ci = 0; ci < 3; ++ci)
716 new_corner(mesh.
tri_corner_ind(ti, ci), has_normals ? (
unsigned)ti : -1);
720 catch (std::exception& e) {
721 std::cout << e.what() << std::endl;
726 ensure_colors(cgv::media::ColorType::CT_RGBA);
727 auto& vertex_colors = *
reinterpret_cast<std::vector<cgv::rgba>*
>(ref_color_data_vector_ptr());
728 std::vector<cgv::rgba> face_colors;
729 std::vector<std::vector<idx_type>> faces;
730 if (!read_off(file_name, ref_positions(), vertex_colors, faces, face_colors))
732 for (
const auto& f : faces) {
739 std::cerr <<
"unknown mesh file extension '*." << ext <<
"'" << std::endl;
747 std::ofstream os(file_name);
750 for (
const auto& p : positions)
751 os <<
"v " << p << std::endl;
752 for (
const auto& t : tex_coords)
753 os <<
"vt " << t << std::endl;
754 for (
const auto& n : normals)
755 os <<
"vn " << n << std::endl;
757 bool nmls = position_indices.size() == normal_indices.size();
758 bool tcs = position_indices.size() == tex_coord_indices.size();
760 for (
idx_type fi = 0; fi < faces.size(); ++fi) {
762 for (
idx_type ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
763 os <<
" " << position_indices[ci] + 1;
768 os << tex_coord_indices[ci] + 1;
770 os <<
"/" << normal_indices[ci] + 1;
782 for (
const auto& p : positions)
794 normal_indices = position_indices;
796 normals.resize(positions.size(),
vec3_type(T(0)));
797 if (use_parallel_implementation) {
798#pragma omp parallel for
799 for (
int fi = 0; fi < int(get_nr_faces()); ++fi) {
801 if (compute_face_normal(fi, nml))
802 for (
idx_type ci = begin_corner(fi); ci < end_corner(fi); ++ci)
803 normal(normal_indices[ci]) += nml;
805#pragma omp parallel for
806 for (
int ni = 0; ni < int(normals.size()); ++ni)
807 normals[ni].normalize();
811 for (
idx_type fi = 0; fi < get_nr_faces(); ++fi)
812 if (compute_face_normal(fi, nml))
813 for (
idx_type ci = begin_corner(fi); ci < end_corner(fi); ++ci)
814 normal(normal_indices[ci]) += nml;
815 for (
auto& n : normals)
822 bool include_tex_coords,
bool include_normals,
823 bool include_tangents, std::vector<T>& attrib_buffer,
824 bool* include_colors_ptr,
int* num_floats_in_vertex)
const
827 include_tex_coords = include_tex_coords && !tex_coord_indices.empty() && !tex_coords.empty();
828 include_normals = include_normals && !normal_indices.empty() && !normals.empty();
829 include_tangents = include_tangents && !tangent_indices.empty() && !tangents.empty();
830 bool include_colors =
false;
831 if (include_colors_ptr)
832 *include_colors_ptr = include_colors = has_colors() && get_nr_colors() > 0 && *include_colors_ptr;
835 unsigned nr_floats = 3;
836 nr_floats += include_tex_coords ? 2 : 0;
837 nr_floats += include_normals ? 3 : 0;
838 nr_floats += include_tangents ? 3 : 0;
839 unsigned color_increment = 0;
840 if (include_colors) {
841 color_increment = (int)ceil((
float)get_color_size() /
sizeof(T));
842 nr_floats += color_increment;
845 if (num_floats_in_vertex)
846 *num_floats_in_vertex = nr_floats;
848 attrib_buffer.resize(nr_floats * unique_quadruples.size());
849 T* data_ptr = &attrib_buffer.front();
850 for (
auto t : unique_quadruples) {
851 *
reinterpret_cast<vec3_type*
>(data_ptr) = positions[t[0]];
853 if (include_tex_coords) {
854 *
reinterpret_cast<vec2_type*
>(data_ptr) = tex_coords[t[1]];
857 if (include_normals) {
858 *
reinterpret_cast<vec3_type*
>(data_ptr) = normals[t[2]];
861 if (include_tangents) {
862 *
reinterpret_cast<vec3_type*
>(data_ptr) = tangents[t[3]];
865 if (include_colors) {
866 put_color(t[0], data_ptr);
867 data_ptr += color_increment;
870 return color_increment;
875 mat3_type inverse_linear_transform = inv(linear_transformation);
876 transform(linear_transformation, translation, inverse_linear_transform);
880 for (
auto& p : positions)
881 p = linear_transform * p + translation;
882 for (
auto& n : normals)
883 n = n * inverse_linear_transform;
884 for(
auto& t : tangents)
885 t = t * inverse_linear_transform;
892 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
893 ctr += position(c2p(ci));
903 vec3_type p0 = position(position_indices[c0]);
904 vec3_type dj = position(position_indices[c0 + 1]) - p0;
906 for (
idx_type ci = c0 + 2; ci < ce; ++ci) {
907 vec3_type di = position(position_indices[ci]) - p0;
908 nml += cross(dj, di);
925 if (construct_normal_indices)
926 normal_indices.clear();
929 for (uint32_t fi = 0; fi < get_nr_faces(); ++fi) {
931 compute_face_normal(fi, nml);
932 uint32_t ni = new_normal(nml);
933 if (construct_normal_indices) {
934 for (
idx_type ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
935 normal_indices.push_back(ni);
942 return normalize(cross(p1 - p0, p2 - p0));
946 if(!has_tex_coords())
949 for(uint32_t fi = 0; fi < get_nr_faces(); ++fi) {
950 std::vector<vec3_type> _P;
951 std::vector<vec2_type> _T;
954 for(ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
955 _P.push_back(position(c2p(ci)));
956 _T.push_back(tex_coord(c2t(ci)));
969 float dir_correction = (delta_uv1.
x() * delta_uv0.
y() - delta_uv1.
y() * delta_uv0.
x()) < 0.0f ? -1.0f : 1.0f;
972 if(delta_uv0.
x() * delta_uv1.
y() == delta_uv0.
y() * delta_uv1.
x()) {
973 delta_uv0.
x() = 0.0f;
974 delta_uv0.
y() = 1.0f;
975 delta_uv1.
x() = 1.0f;
976 delta_uv1.
y() = 0.0f;
979 tng.
x() = delta_uv0.
y() * edge1.
x() - delta_uv1.
y() * edge0.
x();
980 tng.
y() = delta_uv0.
y() * edge1.
y() - delta_uv1.
y() * edge0.
y();
981 tng.
z() = delta_uv0.
y() * edge1.
z() - delta_uv1.
y() * edge0.
z();
982 tng *= dir_correction;
984 std::cout <<
"could not compute tangent for non-triangular face" << std::endl;
988 uint32_t ti = new_tangent(tng);
989 if(construct_tangent_indices) {
990 for(ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
991 tangent_indices.push_back(ti);
999 if (!conway_notation.empty())
1000 construct_conway_polyhedron(conway_notation);
1004 std::vector<uint32_t> c2e;
1005 std::vector<uint32_t> e2c;
1006 std::vector<uint32_t> inv;
1007 std::vector<uint32_t> prev;
1008 std::vector<uint32_t> p2c;
1009 compute_inv(inv,
false, &p2c, 0, &prev);
1010 uint32_t e = compute_c2e(inv, c2e, &e2c);
1013 for (uint32_t ei = 0; ei < e; ++ei) {
1014 uint32_t pi = c2p(e2c[ei]);
1015 uint32_t pj = c2p(inv[e2c[ei]]);
1016 new_M.
new_position(normalize(position(pi) + position(pj)));
1019 for (uint32_t fi = 0; fi < get_nr_faces(); ++fi) {
1021 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1025 for (uint32_t pi = 0; pi < get_nr_positions(); ++pi) {
1026 uint32_t c0 = p2c[pi];
1040 std::vector<uint32_t> inv;
1041 std::vector<uint32_t> prev;
1042 std::vector<uint32_t> p2c;
1043 compute_inv(inv,
false, &p2c, 0, &prev);
1044 uint32_t c = get_nr_corners();
1047 for (uint32_t ci = 0; ci < c; ++ci) {
1048 uint32_t pi = c2p(ci);
1049 uint32_t pj = c2p(inv[ci]);
1050 new_M.
new_position(normalize((1 - lambda) * position(pi) + lambda * position(pj)));
1053 for (uint32_t fi = 0; fi < get_nr_faces(); ++fi) {
1055 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
1061 for (uint32_t pi = 0; pi < get_nr_positions(); ++pi) {
1062 uint32_t c0 = p2c[pi];
1076 std::vector<uint32_t> inv;
1077 std::vector<uint32_t> prev;
1078 std::vector<uint32_t> p2c;
1079 compute_inv(inv,
false, &p2c, 0, &prev);
1080 uint32_t c = get_nr_corners();
1083 for (uint32_t ci = 0; ci < c; ++ci) {
1084 uint32_t pi = c2p(ci);
1085 uint32_t pj = c2p(inv[ci]);
1086 new_M.
new_position(normalize((1 - lambda) * position(pi) + lambda * position(pj)));
1090 for (fi = 0; fi < get_nr_faces(); ++fi) {
1092 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1096 for (fi = 0; fi < get_nr_faces(); ++fi) {
1097 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
1099 uint32_t prev_ci = prev[ci];
1106 for (uint32_t pi = 0; pi < get_nr_positions(); ++pi) {
1107 uint32_t c0 = p2c[pi];
1121 std::vector<uint32_t> c2f;
1122 std::vector<uint32_t> p2c;
1123 std::vector<uint32_t> inv;
1124 std::vector<uint32_t> prev;
1125 compute_inv(inv,
false, &p2c, 0, &prev);
1127 uint32_t f = get_nr_faces();
1130 for (uint32_t fi = 0; fi < f; ++fi) {
1132 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1133 ctr += position(c2p(ci));
1138 for (uint32_t pi = 0; pi < get_nr_positions(); ++pi) {
1139 uint32_t c0 = p2c[pi];
1153 std::vector<uint32_t> c2f;
1154 std::vector<uint32_t> p2c;
1155 std::vector<uint32_t> inv;
1156 std::vector<uint32_t> prev;
1157 compute_inv(inv,
false, &p2c, 0, &prev);
1159 uint32_t v = get_nr_positions();
1160 uint32_t f = get_nr_faces();
1161 uint32_t c = get_nr_corners();
1164 for (uint32_t pi = 0; pi < v; ++pi)
1167 for (uint32_t fi = 0; fi < f; ++fi) {
1169 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1170 ctr += position(c2p(ci));
1176 for (ci = 0; ci < c; ++ci) {
1177 uint32_t pi = c2p(ci);
1178 uint32_t pj = c2p(inv[ci]);
1179 new_M.
new_position(normalize((1 - lambda) * position(pi) + lambda * position(pj)));
1182 for (ci = 0; ci < c; ++ci) {
1183 uint32_t inv_ci = inv[ci];
1184 uint32_t prev_inv_ci = inv[prev[ci]];
1185 uint32_t fi = c2f[ci];
1186 uint32_t pi = c2p(ci);
1192 new_M.
new_corner(prev_inv_ci + v + f, new_fi);
1199 std::vector<uint32_t> c2e;
1200 std::vector<uint32_t> e2c;
1201 std::vector<uint32_t> inv;
1202 std::vector<uint32_t> prev;
1203 std::vector<uint32_t> p2c;
1204 compute_inv(inv,
false, &p2c, 0, &prev);
1205 uint32_t e = compute_c2e(inv, c2e, &e2c);
1206 std::vector<uint32_t> c2f;
1209 uint32_t f = get_nr_faces();
1210 uint32_t v = get_nr_positions();
1213 for (uint32_t pi = 0; pi < v; ++pi)
1217 for (uint32_t fi = 0; fi < f; ++fi) {
1219 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1220 ctr += position(c2p(ci));
1226 for (uint32_t ei = 0; ei < e; ++ei) {
1227 uint32_t ci = e2c[ei];
1228 uint32_t fi = c2f[ci];
1229 uint32_t pi = c2p(ci);
1230 uint32_t cj = inv[ci];
1231 uint32_t fj = c2f[cj];
1232 uint32_t pj = c2p(cj);
1249 if (conway_notation.back() ==
'C' || conway_notation.back() ==
'O') {
1251 static float V[8 * 3] = { -1,-1,+1, +1,-1,+1, -1,+1,+1, +1,+1,+1, -1,-1,-1, +1,-1,-1, -1,+1,-1, +1,+1,-1 };
1252 static float N[6 * 3] = { -1,0,0, +1,0,0, 0,-1,0, 0,+1,0, 0,0,-1, 0,0,+1 };
1253 static int F[6 * 4] = { 0,2,6,4, 1,5,7,3, 0,4,5,1, 2,3,7,6, 4,6,7,5, 0,1,3,2 };
1254 for (
int vi = 0; vi < 8; ++vi)
1255 new_position(normalize(
vec3_type(3, &V[3 * vi])));
1256 for (
int ni = 0; ni < 6; ++ni)
1258 for (
int fi = 0; fi < 6; ++fi) {
1260 for (
int ci = 0; ci < 4; ++ci)
1261 new_corner(F[4 * fi + ci], fi);
1263 if (conway_notation.back() ==
'O')
1266 if (conway_notation.back() ==
'T' || conway_notation.back() ==
'I' || conway_notation.back() ==
'D') {
1267 static const float a = float(1.0 / (2 * sqrt(3.0)));
1268 static const float b = float(1.0 / (3 * sqrt(3.0 / 2)));
1269 static const float V[4 * 3] = { -0.5f, -a, -b, 0.5f, -a, -b, 0,2 * a, -b, 0, 0,2 * b };
1270 static const int F[4 * 3] = { 0,2,1,3,2,0,3,0,1,3,1,2 };
1271 for (
int vi = 0; vi < 4; ++vi)
1272 new_position(normalize(
vec3_type(3, &V[3 * vi])));
1273 for (
int fi = 0; fi < 4; ++fi) {
1275 new_normal(compute_normal(position(F[3 * fi]), position(F[3 * fi + 1]), position(F[3 * fi + 2])));
1276 for (
int ci = 0; ci < 3; ++ci)
1277 new_corner(F[3 * fi + ci], fi);
1279 if (conway_notation.back() !=
'T') {
1282 if (conway_notation.back() ==
'I')
1286 for (
int ci = (
int)conway_notation.size() - 1; ci >= 0; --ci) {
1287 switch (conway_notation[ci]) {
1288 case 't': truncate();
break;
1289 case 'a': ambo();
break;
1290 case 'd': dual();
break;
1291 case 'j': join();
break;
1292 case 'o': ortho();
break;
1293 case 's': snub();
break;
1294 case 'g': gyro();
break;
More advanced text processing for splitting text into lines or tokens.
complete implementation of method actions that only call one method when entering a node
matrix of fixed size dimensions
A vector with zero based index.
T normalize()
normalize the vector using the L2-Norm and return the length
T length() const
length of the vector L2-Norm
const TNumber * vrt_coords(const size_t vi) const
returns an array of 3 floating point values, one for each coordinate of the vertex
size_t num_tris() const
returns the number of triangles in the mesh
const TNumber * raw_normals() const
returns a pointer to the normal array, containing num_tris()*3 entries.
const TIndex tri_corner_ind(const size_t ti, const size_t ci) const
returns the index of the corner with index 0<=ci<3 of triangle ti
size_t num_vrts() const
returns the number of vertices in the mesh
const TNumber * tri_normal(const size_t ti) const
returns an array of 3 floating point values defining the normal of a tri
unsigned int uint32_type
this type provides an 32 bit unsigned integer type
void split_to_tokens(const char *begin, const char *end, std::vector< token > &tokens, const std::string &separators, bool merge_separators, const std::string &open_parenthesis, const std::string &close_parenthesis, const std::string &whitespaces, unsigned int max_nr_tokens)
this function splits a text range into tokens.
bool is_integer(const char *begin, const char *end, int &value)
check if the text range (begin,end( defines an integer value. If yes, store the value in the passed r...
void split_to_lines(const char *global_begin, const char *global_end, std::vector< line > &lines, bool truncate_trailing_spaces)
this function splits a text range at the newline characters into single lines.
char to_lower(char c)
convert char to lower case
bool is_double(const char *begin, const char *end, double &value)
check if the text range (begin,end( defines a double value. If yes, store the value in the passed ref...
Helper functions to process strings.
Provides functions to read stl files into user provided arrays.