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...
this header is dependency free
Helper functions to process strings.
Provides functions to read stl files into user provided arrays.