1#include "simple_mesh.h"
6#include <cgv/media/mesh/obj_reader.h>
7#include <cgv/math/bucket_sort.h>
14std::string simple_mesh_base::get_attribute_name(attribute_type attr)
16 const char* attribute_names[] = {
"position",
"texcoords",
"normal",
"tangent",
"color" };
17 return attribute_names[int(attr)];
22 return attribute_flags[int(attr)];
29 position_indices(smb.position_indices),
30 normal_indices(smb.normal_indices),
31 tex_coord_indices(smb.tex_coord_indices),
33 group_indices(smb.group_indices),
34 group_names(smb.group_names),
35 material_indices(smb.material_indices),
36 materials(smb.materials)
41 position_indices(std::move(smb.position_indices)),
42 normal_indices(std::move(smb.normal_indices)),
43 tex_coord_indices(std::move(smb.tex_coord_indices)),
44 faces(std::move(smb.faces)),
45 group_indices(std::move(smb.group_indices)),
46 group_names(std::move(smb.group_names)),
47 material_indices(std::move(smb.material_indices)),
48 materials(std::move(smb.materials))
54 position_indices=smb.position_indices;
55 normal_indices=smb.normal_indices;
56 tex_coord_indices=smb.tex_coord_indices;
58 group_indices=smb.group_indices;
59 group_names=smb.group_names;
60 material_indices=smb.material_indices;
61 materials = smb.materials;
67 position_indices=std::move(smb.position_indices);
68 normal_indices=std::move(smb.normal_indices);
69 tex_coord_indices=std::move(smb.tex_coord_indices);
70 faces=std::move(smb.faces);
71 group_indices=std::move(smb.group_indices);
72 group_names=std::move(smb.group_names);
73 material_indices=std::move(smb.material_indices);
74 materials = std::move(smb.materials);
80 if (!materials.empty())
81 material_indices.push_back(
idx_type(materials.size()) - 1);
82 if (!group_names.empty())
83 group_indices.push_back(
idx_type(group_names.size()) - 1);
89 position_indices.push_back(position_index);
90 if (normal_index != -1)
91 normal_indices.push_back(normal_index);
92 if (tex_coord_index != -1)
93 tex_coord_indices.push_back(tex_coord_index);
94 return idx_type(position_indices.size());
98 bool nmls = position_indices.size() == normal_indices.size();
99 bool tcs = position_indices.size() == tex_coord_indices.size();
103 while (ci + 1 < cj) {
105 std::swap(position_indices[ci], position_indices[cj]);
107 std::swap(normal_indices[ci], normal_indices[cj]);
109 std::swap(tex_coord_indices[ci], tex_coord_indices[cj]);
116 if (by_group && by_material) {
117 std::vector<idx_type> perm0;
118 cgv::math::bucket_sort(group_indices,
get_nr_groups(), perm0);
122 cgv::math::bucket_sort(group_indices,
get_nr_groups(), perm);
126void 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
128 bool include_tex_coords =
false;
129 if (include_tex_coords_ptr)
130 *include_tex_coords_ptr = include_tex_coords = (tex_coord_indices.size() > 0) && *include_tex_coords_ptr;
132 bool include_normals =
false;
133 if (include_normals_ptr)
134 *include_normals_ptr = include_normals = (normal_indices.size() > 0) && *include_normals_ptr;
136 bool include_tangents =
false;
137 if(include_tangents_ptr)
138 *include_tangents_ptr = include_tangents = (tangent_indices.size() > 0) && *include_tangents_ptr;
140 std::map<std::tuple<idx_type, idx_type, idx_type, idx_type>,
idx_type> corner_to_index;
141 for (
idx_type ci = 0; ci < position_indices.size(); ++ci) {
144 (include_tex_coords && ci < tex_coord_indices.size()) ? tex_coord_indices[ci] : 0,
145 (include_normals && ci < normal_indices.size()) ? normal_indices[ci] : 0,
146 (include_tangents && ci < tangent_indices.size()) ? tangent_indices[ci] : 0);
147 std::tuple<idx_type, idx_type, idx_type, idx_type> quadruple(c(0),c(1),c(2),c(3));
149 auto iter = corner_to_index.find(quadruple);
152 if (iter == corner_to_index.end()) {
153 vi =
idx_type(unique_quadruples.size());
154 corner_to_index[quadruple] = vi;
155 unique_quadruples.push_back(c);
160 indices.push_back(vi);
164 const std::vector<idx_type>& vertex_indices, std::vector<idx_type>& triangle_element_buffer,
165 const std::vector<idx_type>* face_permutation_ptr, std::vector<idx3_type>* material_group_start_ptr)
const
170 for (
idx_type fi = 0; fi < faces.size(); ++fi) {
171 idx_type fj = face_permutation_ptr ? face_permutation_ptr->at(fi) : fi;
172 if (material_group_start_ptr) {
173 if (mi != material_indices[fj] || gi != group_indices[fj]) {
174 mi = material_indices[fj];
175 gi = group_indices[fj];
176 material_group_start_ptr->push_back(
idx3_type(mi, gi,
idx_type(triangle_element_buffer.size())));
181 triangle_element_buffer.push_back(vertex_indices.at(ci));
186 triangle_element_buffer.push_back(vertex_indices.at(
begin_corner(fj)));
187 triangle_element_buffer.push_back(vertex_indices.at(ci - 1));
188 triangle_element_buffer.push_back(vertex_indices.at(ci));
196 std::map<std::tuple<idx_type, idx_type>,
idx_type> halfedge_to_count;
197 for (
idx_type fi = 0; fi < faces.size(); ++fi) {
201 idx_type vi = vertex_indices.at(ci);
202 std::tuple<idx_type, idx_type> halfedge(last_vi, vi);
204 std::swap(std::get<0>(halfedge), std::get<1>(halfedge));
207 auto iter = halfedge_to_count.find(halfedge);
210 if (iter == halfedge_to_count.end()) {
211 halfedge_to_count[halfedge] = 1;
212 edge_element_buffer.push_back(last_vi);
213 edge_element_buffer.push_back(vi);
216 ++halfedge_to_count[halfedge];
224 if (position_indices.empty() && (flags & AF_position))
226 if (tex_coord_indices.empty() && (flags &
AF_texcoords))
228 if (normal_indices.empty() && (flags &
AF_normal))
230 if (tangent_indices.empty() && (flags &
AF_tangent))
234 bool include_attribute[5] = { bool(flags&AF_position),bool(flags&
AF_texcoords),
238 uint32_t attribute_size[5] = { 3 * cs,2 * cs,3 * cs,3 * cs,uint32_t(
get_color_size()) };
241 for (
int ai = 0; ai < 5; ++ai)
242 if (include_attribute[ai])
243 vs += attribute_offset[ai];
244 attrib_buffer.resize(vs * unique_quadruples.size());
246 const uint8_t* attrib_ptrs[5] = {
247 include_attribute[0] ? get_attribute_ptr(attribute_type::position) :
nullptr,
248 include_attribute[1] ? get_attribute_ptr(attribute_type::texcoords) :
nullptr,
249 include_attribute[2] ? get_attribute_ptr(attribute_type::normal) :
nullptr,
250 include_attribute[3] ? get_attribute_ptr(attribute_type::tangent) :
nullptr,
251 include_attribute[4] ? get_attribute_ptr(attribute_type::color) :
nullptr
254 for (
auto t : unique_quadruples) {
255 for (
int ai = 0; ai < 5; ++ai)
256 if (include_attribute[ai]) {
257 const uint8_t* src_ptr = attrib_ptrs[ai] + attribute_size[ai] * t[ai & 3];
258 std::copy(src_ptr, src_ptr + attribute_size[ai], &attrib_buffer[loc]);
259 loc += attribute_offset[ai];
265 std::vector<idx_type>& inv,
266 bool link_non_manifold_edges,
267 std::vector<idx_type>* p2c_ptr,
268 std::vector<idx_type>* next_ptr,
269 std::vector<idx_type>* prev_ptr,
270 std::vector<idx_type>* unmatched,
271 std::vector<idx_type>* non_manifold,
272 std::vector<idx_type>* unmatched_elements,
273 std::vector<idx_type>* non_manifold_elements)
const
289 for (
idx_type ci = cb; ci < ce; ++ci) {
292 p2c_ptr->at(pi) = ci;
294 next_ptr->at(cp) = ci;
296 prev_ptr->at(ci) = cp;
297 pis[cp] = std::min(pp, pi);
314 pis[cp] = std::max(
c2p(cp), pi);
326 for (
idx_type ci = cb; ci < ce; ++ci) {
334 while (i < perm.size()) {
335 idx_type ci = perm[i], pi0 =
c2p(ci), pi1 = pis[ci];
337 while (i + cnt < perm.size()) {
338 idx_type cj = perm[i + cnt], pj0 =
c2p(cj), pj1 = pis[cj];
339 if (std::min(pi0, pi1) == std::min(pj0, pj1) && std::max(pi0, pi1) == std::max(pj0, pj1)) {
347 unmatched->push_back(ci);
348 if (unmatched_elements) {
349 unmatched_elements->push_back(pi0);
350 unmatched_elements->push_back(pi1);
354 inv[perm[i]] = perm[i + 1];
355 inv[perm[i + 1]] = perm[i];
359 if (link_non_manifold_edges) {
368 non_manifold->push_back(ci);
369 if (non_manifold_elements) {
370 non_manifold_elements->push_back(pi0);
371 non_manifold_elements->push_back(pi1);
414 c2e[ci] = c2e[inv[ci]] = e;
434 for (
unsigned vi = 0; vi < loader.vertices.size(); ++vi)
435 new_position(loader.vertices[vi]);
436 for (
unsigned ni = 0; ni < loader.normals.size(); ++ni)
437 new_normal(loader.normals[ni]);
438 for (
unsigned ti = 0; ti < loader.texcoords.size(); ++ti)
439 new_tex_coord(loader.texcoords[ti]);
441 for (
unsigned gi = 0; gi < loader.groups.size(); ++gi)
442 new_group(loader.groups[gi].name);
443 if (copy_material_info)
444 for (
unsigned mi = 0; mi < loader.materials.size(); ++mi)
445 ref_material(new_material()) = loader.materials[mi];
446 for (
unsigned fi = 0; fi < loader.faces.size(); ++fi) {
448 const auto& F = loader.faces[fi];
449 if (copy_grp_info && !loader.groups.empty())
450 group_index(fi) = F.group_index;
451 if (copy_material_info && !loader.materials.empty())
452 material_index(fi) = F.material_index;
453 for (
unsigned i = 0; i < F.degree; ++i) {
455 loader.vertex_indices[F.first_vertex_index + i],
456 F.first_normal_index != -1 ? loader.normal_indices[F.first_normal_index + i] : -1,
457 F.first_texcoord_index != -1 ? loader.texcoord_indices[F.first_texcoord_index + i] : -1
490 void process_face(
unsigned vcount,
int *vertices,
int *texcoords,
int *normals)
493 mesh.faces.push_back(idx_type(mesh.position_indices.size()));
499 if (mesh.tex_coord_indices.size() < mesh.position_indices.size())
500 mesh.tex_coord_indices.resize(mesh.position_indices.size(), 0);
503 if (mesh.normal_indices.size() < mesh.position_indices.size())
504 mesh.normal_indices.resize(mesh.position_indices.size(), 0);
506 for (idx_type i = 0; i < vcount; ++i) {
507 mesh.position_indices.push_back(idx_type(vertices[i]));
509 mesh.tex_coord_indices.push_back(idx_type(texcoords[i]));
511 mesh.normal_indices.push_back(idx_type(normals[i]));
517 mesh.group_names.push_back(name);
522 if (idx >= mesh.materials.size())
523 mesh.materials.resize(idx+1);
524 mesh.materials[idx] = mtl;
532 :
simple_mesh_base(sm), positions(sm.positions), normals(sm.normals), tex_coords(sm.tex_coords)
539 :
simple_mesh_base(std::move(sm)), positions(std::move(sm.positions)), normals(std::move(sm.normals)),
540 tex_coords(std::move(sm.tex_coords))
549 positions = sm.positions;
550 normals = sm.normals;
551 tangents = sm.tangents;
552 tex_coords = sm.tex_coords;
561 positions = std::move(sm.positions);
562 normals = std::move(sm.normals);
563 tangents = std::move(sm.tangents);
564 tex_coords = std::move(sm.tex_coords);
576 position_indices.clear();
577 tex_coord_indices.clear();
578 normal_indices.clear();
580 group_indices.clear();
582 material_indices.clear();
588bool read_off(
const std::string& file_name,
590 std::vector<std::vector<uint32_t>>& faces, std::vector<cgv::rgba>& face_colors)
593 if (!cgv::utils::file::read(file_name, content,
true))
595 std::vector<cgv::utils::line> lines;
597 if (!(lines[0] ==
"OFF")) {
598 std::cerr <<
"WARNING: first line in OFF file " << file_name <<
" does not contain 'OFF'" << std::endl;
601 unsigned real_li = 1;
603 for (
unsigned li = 1; li < lines.size(); ++li) {
604 if (lines[li].empty())
606 if (lines[li].begin[0] ==
'#')
609 std::vector<cgv::utils::token> toks;
612 if (toks.size() != 3) {
613 std::cerr <<
"WARNING: second line in OFF file " << file_name <<
" does provide 3 tokens" << std::endl;
617 for (
int i = 0; i < 3; ++i) {
619 std::cerr <<
"WARNING: token " << i <<
" on second line in OFF file " << file_name <<
" is not an integer value" << std::endl;
623 v = I[0]; f = I[1]; e = I[2];
624 std::cout <<
"OFF file " << file_name <<
" found " << v <<
" vertices, " << f <<
" faces, and " << e <<
" edges." << std::endl;
627 if (
int(real_li) < v+3) {
628 if (!(toks.size() == 3 || toks.size() == 6 || toks.size() == 7)) {
629 std::cerr <<
"WARNING: line of vertex " << real_li - 3 <<
" contains " << toks.size() <<
" tokens instead of 3 or 7." << std::endl;
633 for (
unsigned i = 0; i < 3; ++i) {
635 std::cerr <<
"WARNING: line of vertex " << real_li - 3 <<
" no double in XYZ component " << i <<
" but <" << toks[i] <<
">." << std::endl;
640 if (toks.size() >= 6) {
641 double c[4] = { 0,0,0,1 };
642 for (
unsigned i = 0; i+3 < toks.size(); ++i) {
644 std::cerr <<
"WARNING: line of vertex " << real_li - 3 <<
" no double in RGB[A] component " << i <<
" but <" << toks[i+3] <<
">." << std::endl;
648 while (vertex_colors.size() + 1 < positions.size())
649 vertex_colors.push_back(vertex_colors.empty() ?
cgv::rgba(0.5, 0.5, 0.5, 1.0f) : vertex_colors.back());
650 vertex_colors.push_back(
cgv::rgba(
float(c[0]),
float(c[1]),
float(c[2]),
float(1.0-c[3])));
656 std::cerr <<
"WARNING: first token on face " << faces.size() <<
" is not of type integer " << std::endl;
659 if (!(toks.size() == n + 1 || toks.size() == n + 4 || toks.size() == n + 5)) {
660 std::cerr <<
"WARNING: line of face " << faces.size() <<
" contains " << toks.size() <<
" tokens instead of " << n+1 <<
" or " << n+5 << std::endl;
664 auto& face = faces.back();
665 for (
int i = 0; i<n; ++i) {
668 std::cerr <<
"WARNING: token " << i+1 <<
" on face " << faces.size()-1 <<
" is not of type integer " << std::endl;
671 face.push_back(uint32_t(pi));
673 if (toks.size() >= n + 4) {
674 double c[4] = { 0,0,0,1 };
675 for (
unsigned i = 0; i < toks.size()-n-1; ++i) {
677 std::cerr <<
"WARNING: line of vertex " << real_li - 3 <<
" no double in RGBA component " << i <<
" but <" << toks[i + n + 1] <<
">." << std::endl;
681 while (face_colors.size()+1 < faces.size())
682 face_colors.push_back(face_colors.empty() ?
cgv::rgba(0.5, 0.5, 0.5, 1.0f) : face_colors.back());
683 face_colors.push_back(
cgv::rgba(
float(c[0]),
float(c[1]),
float(c[2]),
float(1.0 - c[3])));
702 stl_reader::StlMesh <T, unsigned> mesh(file_name);
705 for (
size_t vi = 0; vi < mesh.
num_vrts(); ++vi)
710 for (
size_t ti = 0; ti < mesh.
num_tris(); ++ti) {
714 for (
size_t ci = 0; ci < 3; ++ci)
715 new_corner(mesh.
tri_corner_ind(ti, ci), has_normals ? (
unsigned)ti : -1);
719 catch (std::exception& e) {
720 std::cout << e.what() << std::endl;
725 ensure_colors(cgv::media::ColorType::CT_RGBA);
726 auto& vertex_colors = *
reinterpret_cast<std::vector<cgv::rgba>*
>(ref_color_data_vector_ptr());
727 std::vector<cgv::rgba> face_colors;
728 std::vector<std::vector<idx_type>> faces;
729 if (!read_off(file_name, ref_positions(), vertex_colors, faces, face_colors))
731 for (
const auto& f : faces) {
738 std::cerr <<
"unknown mesh file extension '*." << ext <<
"'" << std::endl;
746 std::ofstream os(file_name);
749 for (
const auto& p : positions)
750 os <<
"v " << p << std::endl;
751 for (
const auto& t : tex_coords)
752 os <<
"vt " << t << std::endl;
753 for (
const auto& n : normals)
754 os <<
"vn " << n << std::endl;
756 bool nmls = position_indices.size() == normal_indices.size();
757 bool tcs = position_indices.size() == tex_coord_indices.size();
759 for (
idx_type fi = 0; fi < faces.size(); ++fi) {
761 for (
idx_type ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
762 os <<
" " << position_indices[ci] + 1;
767 os << tex_coord_indices[ci] + 1;
769 os <<
"/" << normal_indices[ci] + 1;
781 for (
const auto& p : positions)
793 normal_indices = position_indices;
795 normals.resize(positions.size(),
vec3_type(T(0)));
796 if (use_parallel_implementation) {
797#pragma omp parallel for
798 for (
int fi = 0; fi < int(get_nr_faces()); ++fi) {
800 if (compute_face_normal(fi, nml))
801 for (
idx_type ci = begin_corner(fi); ci < end_corner(fi); ++ci)
802 normal(normal_indices[ci]) += nml;
804#pragma omp parallel for
805 for (
int ni = 0; ni < int(normals.size()); ++ni)
806 normals[ni].normalize();
810 for (
idx_type fi = 0; fi < get_nr_faces(); ++fi)
811 if (compute_face_normal(fi, nml))
812 for (
idx_type ci = begin_corner(fi); ci < end_corner(fi); ++ci)
813 normal(normal_indices[ci]) += nml;
814 for (
auto& n : normals)
821 bool include_tex_coords,
bool include_normals,
822 bool include_tangents, std::vector<T>& attrib_buffer,
823 bool* include_colors_ptr,
int* num_floats_in_vertex)
const
826 include_tex_coords = include_tex_coords && !tex_coord_indices.empty() && !tex_coords.empty();
827 include_normals = include_normals && !normal_indices.empty() && !normals.empty();
828 include_tangents = include_tangents && !tangent_indices.empty() && !tangents.empty();
829 bool include_colors =
false;
830 if (include_colors_ptr)
831 *include_colors_ptr = include_colors = has_colors() && get_nr_colors() > 0 && *include_colors_ptr;
834 unsigned nr_floats = 3;
835 nr_floats += include_tex_coords ? 2 : 0;
836 nr_floats += include_normals ? 3 : 0;
837 nr_floats += include_tangents ? 3 : 0;
838 unsigned color_increment = 0;
839 if (include_colors) {
840 color_increment = (int)ceil((
float)get_color_size() /
sizeof(T));
841 nr_floats += color_increment;
844 if (num_floats_in_vertex)
845 *num_floats_in_vertex = nr_floats;
847 attrib_buffer.resize(nr_floats * unique_quadruples.size());
848 T* data_ptr = &attrib_buffer.front();
849 for (
auto t : unique_quadruples) {
850 *
reinterpret_cast<vec3_type*
>(data_ptr) = positions[t[0]];
852 if (include_tex_coords) {
853 *
reinterpret_cast<vec2_type*
>(data_ptr) = tex_coords[t[1]];
856 if (include_normals) {
857 *
reinterpret_cast<vec3_type*
>(data_ptr) = normals[t[2]];
860 if (include_tangents) {
861 *
reinterpret_cast<vec3_type*
>(data_ptr) = tangents[t[3]];
864 if (include_colors) {
865 put_color(t[0], data_ptr);
866 data_ptr += color_increment;
869 return color_increment;
874 mat3_type inverse_linear_transform = cgv::math::inverse(linear_transformation);
875 transform(linear_transformation, translation, inverse_linear_transform);
879 for (
auto& p : positions)
880 p = linear_transform * p + translation;
881 for (
auto& n : normals)
882 n = n * inverse_linear_transform;
883 for(
auto& t : tangents)
884 t = t * inverse_linear_transform;
891 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
892 ctr += position(c2p(ci));
902 vec3_type p0 = position(position_indices[c0]);
903 vec3_type dj = position(position_indices[c0 + 1]) - p0;
905 for (
idx_type ci = c0 + 2; ci < ce; ++ci) {
906 vec3_type di = position(position_indices[ci]) - p0;
907 nml += cross(dj, di);
924 if (construct_normal_indices)
925 normal_indices.clear();
928 for (uint32_t fi = 0; fi < get_nr_faces(); ++fi) {
930 compute_face_normal(fi, nml);
931 uint32_t ni = new_normal(nml);
932 if (construct_normal_indices) {
933 for (
idx_type ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
934 normal_indices.push_back(ni);
941 return normalize(cross(p1 - p0, p2 - p0));
945 if(!has_tex_coords())
948 for(uint32_t fi = 0; fi < get_nr_faces(); ++fi) {
949 std::vector<vec3_type> _P;
950 std::vector<vec2_type> _T;
953 for(ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
954 _P.push_back(position(c2p(ci)));
955 _T.push_back(tex_coord(c2t(ci)));
968 float dir_correction = (delta_uv1.
x() * delta_uv0.
y() - delta_uv1.
y() * delta_uv0.
x()) < 0.0f ? -1.0f : 1.0f;
971 if(delta_uv0.
x() * delta_uv1.
y() == delta_uv0.
y() * delta_uv1.
x()) {
972 delta_uv0.
x() = 0.0f;
973 delta_uv0.
y() = 1.0f;
974 delta_uv1.
x() = 1.0f;
975 delta_uv1.
y() = 0.0f;
978 tng.
x() = delta_uv0.
y() * edge1.
x() - delta_uv1.
y() * edge0.
x();
979 tng.
y() = delta_uv0.
y() * edge1.
y() - delta_uv1.
y() * edge0.
y();
980 tng.
z() = delta_uv0.
y() * edge1.
z() - delta_uv1.
y() * edge0.
z();
981 tng *= dir_correction;
983 std::cout <<
"could not compute tangent for non-triangular face" << std::endl;
987 uint32_t ti = new_tangent(tng);
988 if(construct_tangent_indices) {
989 for(ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
990 tangent_indices.push_back(ti);
998 if (!conway_notation.empty())
999 construct_conway_polyhedron(conway_notation);
1003 std::vector<uint32_t> c2e;
1004 std::vector<uint32_t> e2c;
1005 std::vector<uint32_t> inv;
1006 std::vector<uint32_t> prev;
1007 std::vector<uint32_t> p2c;
1008 compute_inv(inv,
false, &p2c, 0, &prev);
1009 uint32_t e = compute_c2e(inv, c2e, &e2c);
1012 for (uint32_t ei = 0; ei < e; ++ei) {
1013 uint32_t pi = c2p(e2c[ei]);
1014 uint32_t pj = c2p(inv[e2c[ei]]);
1015 new_M.
new_position(normalize(position(pi) + position(pj)));
1018 for (uint32_t fi = 0; fi < get_nr_faces(); ++fi) {
1020 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1024 for (uint32_t pi = 0; pi < get_nr_positions(); ++pi) {
1025 uint32_t c0 = p2c[pi];
1039 std::vector<uint32_t> inv;
1040 std::vector<uint32_t> prev;
1041 std::vector<uint32_t> p2c;
1042 compute_inv(inv,
false, &p2c, 0, &prev);
1043 uint32_t c = get_nr_corners();
1046 for (uint32_t ci = 0; ci < c; ++ci) {
1047 uint32_t pi = c2p(ci);
1048 uint32_t pj = c2p(inv[ci]);
1049 new_M.
new_position(normalize((1 - lambda) * position(pi) + lambda * position(pj)));
1052 for (uint32_t fi = 0; fi < get_nr_faces(); ++fi) {
1054 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
1060 for (uint32_t pi = 0; pi < get_nr_positions(); ++pi) {
1061 uint32_t c0 = p2c[pi];
1075 std::vector<uint32_t> inv;
1076 std::vector<uint32_t> prev;
1077 std::vector<uint32_t> p2c;
1078 compute_inv(inv,
false, &p2c, 0, &prev);
1079 uint32_t c = get_nr_corners();
1082 for (uint32_t ci = 0; ci < c; ++ci) {
1083 uint32_t pi = c2p(ci);
1084 uint32_t pj = c2p(inv[ci]);
1085 new_M.
new_position(normalize((1 - lambda) * position(pi) + lambda * position(pj)));
1089 for (fi = 0; fi < get_nr_faces(); ++fi) {
1091 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1095 for (fi = 0; fi < get_nr_faces(); ++fi) {
1096 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
1098 uint32_t prev_ci = prev[ci];
1105 for (uint32_t pi = 0; pi < get_nr_positions(); ++pi) {
1106 uint32_t c0 = p2c[pi];
1120 std::vector<uint32_t> c2f;
1121 std::vector<uint32_t> p2c;
1122 std::vector<uint32_t> inv;
1123 std::vector<uint32_t> prev;
1124 compute_inv(inv,
false, &p2c, 0, &prev);
1126 uint32_t f = get_nr_faces();
1129 for (uint32_t fi = 0; fi < f; ++fi) {
1131 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1132 ctr += position(c2p(ci));
1137 for (uint32_t pi = 0; pi < get_nr_positions(); ++pi) {
1138 uint32_t c0 = p2c[pi];
1152 std::vector<uint32_t> c2f;
1153 std::vector<uint32_t> p2c;
1154 std::vector<uint32_t> inv;
1155 std::vector<uint32_t> prev;
1156 compute_inv(inv,
false, &p2c, 0, &prev);
1158 uint32_t v = get_nr_positions();
1159 uint32_t f = get_nr_faces();
1160 uint32_t c = get_nr_corners();
1163 for (uint32_t pi = 0; pi < v; ++pi)
1166 for (uint32_t fi = 0; fi < f; ++fi) {
1168 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1169 ctr += position(c2p(ci));
1175 for (ci = 0; ci < c; ++ci) {
1176 uint32_t pi = c2p(ci);
1177 uint32_t pj = c2p(inv[ci]);
1178 new_M.
new_position(normalize((1 - lambda) * position(pi) + lambda * position(pj)));
1181 for (ci = 0; ci < c; ++ci) {
1182 uint32_t inv_ci = inv[ci];
1183 uint32_t prev_inv_ci = inv[prev[ci]];
1184 uint32_t fi = c2f[ci];
1185 uint32_t pi = c2p(ci);
1191 new_M.
new_corner(prev_inv_ci + v + f, new_fi);
1198 std::vector<uint32_t> c2e;
1199 std::vector<uint32_t> e2c;
1200 std::vector<uint32_t> inv;
1201 std::vector<uint32_t> prev;
1202 std::vector<uint32_t> p2c;
1203 compute_inv(inv,
false, &p2c, 0, &prev);
1204 uint32_t e = compute_c2e(inv, c2e, &e2c);
1205 std::vector<uint32_t> c2f;
1208 uint32_t f = get_nr_faces();
1209 uint32_t v = get_nr_positions();
1212 for (uint32_t pi = 0; pi < v; ++pi)
1216 for (uint32_t fi = 0; fi < f; ++fi) {
1218 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1219 ctr += position(c2p(ci));
1225 for (uint32_t ei = 0; ei < e; ++ei) {
1226 uint32_t ci = e2c[ei];
1227 uint32_t fi = c2f[ci];
1228 uint32_t pi = c2p(ci);
1229 uint32_t cj = inv[ci];
1230 uint32_t fj = c2f[cj];
1231 uint32_t pj = c2p(cj);
1248 if (conway_notation.back() ==
'C' || conway_notation.back() ==
'O') {
1250 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 };
1251 static float N[6 * 3] = { -1,0,0, +1,0,0, 0,-1,0, 0,+1,0, 0,0,-1, 0,0,+1 };
1252 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 };
1253 for (
int vi = 0; vi < 8; ++vi)
1254 new_position(normalize(
vec3_type(3, &V[3 * vi])));
1255 for (
int ni = 0; ni < 6; ++ni)
1257 for (
int fi = 0; fi < 6; ++fi) {
1259 for (
int ci = 0; ci < 4; ++ci)
1260 new_corner(F[4 * fi + ci], fi);
1262 if (conway_notation.back() ==
'O')
1265 if (conway_notation.back() ==
'T' || conway_notation.back() ==
'I' || conway_notation.back() ==
'D') {
1266 static const float a = float(1.0 / (2 * sqrt(3.0)));
1267 static const float b = float(1.0 / (3 * sqrt(3.0 / 2)));
1268 static const float V[4 * 3] = { -0.5f, -a, -b, 0.5f, -a, -b, 0,2 * a, -b, 0, 0,2 * b };
1269 static const int F[4 * 3] = { 0,2,1,3,2,0,3,0,1,3,1,2 };
1270 for (
int vi = 0; vi < 4; ++vi)
1271 new_position(normalize(
vec3_type(3, &V[3 * vi])));
1272 for (
int fi = 0; fi < 4; ++fi) {
1274 new_normal(compute_normal(position(F[3 * fi]), position(F[3 * fi + 1]), position(F[3 * fi + 2])));
1275 for (
int ci = 0; ci < 3; ++ci)
1276 new_corner(F[3 * fi + ci], fi);
1278 if (conway_notation.back() !=
'T') {
1281 if (conway_notation.back() ==
'I')
1285 for (
int ci = (
int)conway_notation.size() - 1; ci >= 0; --ci) {
1286 switch (conway_notation[ci]) {
1287 case 't': truncate();
break;
1288 case 'a': ambo();
break;
1289 case 'd': dual();
break;
1290 case 'j': join();
break;
1291 case 'o': ortho();
break;
1292 case 's': snub();
break;
1293 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 & z()
return third component
T & y()
return second component
T normalize()
normalize the vector using the L2-Norm and return the length
T length() const
length of the vector L2-Norm
T & x()
return first component
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.