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> vertex_indices;
266 std::vector<idx4_type> unique_quadruples;
268 bool include_tex_coords = tex_coord_indices !=
nullptr;
269 bool include_normals = normal_indices !=
nullptr;
270 bool include_tangents = tangent_indices !=
nullptr;
272 merge_indices(vertex_indices, unique_quadruples, &include_tex_coords, &include_normals, &include_tangents);
274 std::vector<idx_type> triangle_element_buffer;
277 constexpr size_t position_index = 0;
278 constexpr size_t tex_coord_index = 1;
279 constexpr size_t normal_index = 2;
280 constexpr size_t tangent_index = 3;
282 for(
size_t i = 0; i < triangle_element_buffer.size(); i += 3) {
283 idx4_type i0 = unique_quadruples[triangle_element_buffer[i + 0]];
284 idx4_type i1 = unique_quadruples[triangle_element_buffer[i + 1]];
285 idx4_type i2 = unique_quadruples[triangle_element_buffer[i + 2]];
287 position_indices.emplace_back(i0[position_index], i1[position_index], i2[position_index]);
289 if(include_tex_coords)
290 tex_coord_indices->emplace_back(i0[tex_coord_index], i1[tex_coord_index], i2[tex_coord_index]);
293 normal_indices->emplace_back(i0[normal_index], i1[normal_index], i2[normal_index]);
296 tangent_indices->emplace_back(i0[tangent_index], i1[tangent_index], i2[tangent_index]);
300 std::vector<idx_type>& inv,
301 bool link_non_manifold_edges,
302 std::vector<idx_type>* p2c_ptr,
303 std::vector<idx_type>* next_ptr,
304 std::vector<idx_type>* prev_ptr,
305 std::vector<idx_type>* unmatched,
306 std::vector<idx_type>* non_manifold,
307 std::vector<idx_type>* unmatched_elements,
308 std::vector<idx_type>* non_manifold_elements)
const
327 p2c_ptr->at(pi) = ci;
329 next_ptr->at(cp) = ci;
331 prev_ptr->at(ci) = cp;
332 pis[cp] = std::min(pp, pi);
347 for (
idx_type ci = cb; ci < ce; ++ci) {
349 pis[cp] = std::max(
c2p(cp), pi);
361 for (
idx_type ci = cb; ci < ce; ++ci) {
369 while (i < perm.size()) {
370 idx_type ci = perm[i], pi0 =
c2p(ci), pi1 = pis[ci];
372 while (i + cnt < perm.size()) {
374 if (std::min(pi0, pi1) == std::min(pj0, pj1) && std::max(pi0, pi1) == std::max(pj0, pj1)) {
382 unmatched->push_back(ci);
383 if (unmatched_elements) {
384 unmatched_elements->push_back(pi0);
385 unmatched_elements->push_back(pi1);
389 inv[perm[i]] = perm[i + 1];
390 inv[perm[i + 1]] = perm[i];
394 if (link_non_manifold_edges) {
396 for (
idx_type k = 0; k < cnt; ++k) {
403 non_manifold->push_back(ci);
404 if (non_manifold_elements) {
405 non_manifold_elements->push_back(pi0);
406 non_manifold_elements->push_back(pi1);
449 c2e[ci] = c2e[inv[ci]] = e;
469 for (
unsigned vi = 0; vi < loader.vertices.size(); ++vi)
470 new_position(loader.vertices[vi]);
471 for (
unsigned ni = 0; ni < loader.normals.size(); ++ni)
472 new_normal(loader.normals[ni]);
473 for (
unsigned ti = 0; ti < loader.texcoords.size(); ++ti)
474 new_tex_coord(loader.texcoords[ti]);
476 for (
unsigned gi = 0; gi < loader.groups.size(); ++gi)
477 new_group(loader.groups[gi].name);
478 if (copy_material_info)
479 for (
unsigned mi = 0; mi < loader.materials.size(); ++mi)
480 ref_material(new_material()) = loader.materials[mi];
481 for (
unsigned fi = 0; fi < loader.faces.size(); ++fi) {
483 const auto& F = loader.faces[fi];
484 if (copy_grp_info && !loader.groups.empty())
485 group_index(fi) = F.group_index;
486 if (copy_material_info && !loader.materials.empty())
487 material_index(fi) = F.material_index;
488 for (
unsigned i = 0; i < F.degree; ++i) {
490 loader.vertex_indices[F.first_vertex_index + i],
491 F.first_normal_index != -1 ? loader.normal_indices[F.first_normal_index + i] : -1,
492 F.first_texcoord_index != -1 ? loader.texcoord_indices[F.first_texcoord_index + i] : -1
525 void process_face(
unsigned vcount,
int *vertices,
int *texcoords,
int *normals)
528 mesh.faces.push_back(idx_type(mesh.position_indices.size()));
534 if (mesh.tex_coord_indices.size() < mesh.position_indices.size())
535 mesh.tex_coord_indices.resize(mesh.position_indices.size(), 0);
538 if (mesh.normal_indices.size() < mesh.position_indices.size())
539 mesh.normal_indices.resize(mesh.position_indices.size(), 0);
541 for (idx_type i = 0; i < vcount; ++i) {
542 mesh.position_indices.push_back(idx_type(vertices[i]));
544 mesh.tex_coord_indices.push_back(idx_type(texcoords[i]));
546 mesh.normal_indices.push_back(idx_type(normals[i]));
552 mesh.group_names.push_back(name);
557 if (idx >= mesh.materials.size())
558 mesh.materials.resize(idx+1);
559 mesh.materials[idx] = mtl;
567 :
simple_mesh_base(sm), positions(sm.positions), normals(sm.normals), tex_coords(sm.tex_coords)
574 :
simple_mesh_base(std::move(sm)), positions(std::move(sm.positions)), normals(std::move(sm.normals)),
575 tex_coords(std::move(sm.tex_coords))
584 positions = sm.positions;
585 normals = sm.normals;
586 tangents = sm.tangents;
587 tex_coords = sm.tex_coords;
596 positions = std::move(sm.positions);
597 normals = std::move(sm.normals);
598 tangents = std::move(sm.tangents);
599 tex_coords = std::move(sm.tex_coords);
611 position_indices.clear();
612 tex_coord_indices.clear();
613 normal_indices.clear();
615 group_indices.clear();
617 material_indices.clear();
623bool read_off(
const std::string& file_name,
625 std::vector<std::vector<uint32_t>>& faces, std::vector<cgv::rgba>& face_colors)
628 if (!cgv::utils::file::read(file_name, content,
true))
630 std::vector<cgv::utils::line> lines;
632 if (!(lines[0] ==
"OFF")) {
633 std::cerr <<
"WARNING: first line in OFF file " << file_name <<
" does not contain 'OFF'" << std::endl;
636 unsigned real_li = 1;
638 for (
unsigned li = 1; li < lines.size(); ++li) {
639 if (lines[li].empty())
641 if (lines[li].begin[0] ==
'#')
644 std::vector<cgv::utils::token> toks;
647 if (toks.size() != 3) {
648 std::cerr <<
"WARNING: second line in OFF file " << file_name <<
" does provide 3 tokens" << std::endl;
652 for (
int i = 0; i < 3; ++i) {
654 std::cerr <<
"WARNING: token " << i <<
" on second line in OFF file " << file_name <<
" is not an integer value" << std::endl;
658 v = I[0]; f = I[1]; e = I[2];
659 std::cout <<
"OFF file " << file_name <<
" found " << v <<
" vertices, " << f <<
" faces, and " << e <<
" edges." << std::endl;
662 if (
int(real_li) < v+3) {
663 if (!(toks.size() == 3 || toks.size() == 6 || toks.size() == 7)) {
664 std::cerr <<
"WARNING: line of vertex " << real_li - 3 <<
" contains " << toks.size() <<
" tokens instead of 3 or 7." << std::endl;
668 for (
unsigned i = 0; i < 3; ++i) {
670 std::cerr <<
"WARNING: line of vertex " << real_li - 3 <<
" no double in XYZ component " << i <<
" but <" << toks[i] <<
">." << std::endl;
675 if (toks.size() >= 6) {
676 double c[4] = { 0,0,0,1 };
677 for (
unsigned i = 0; i+3 < toks.size(); ++i) {
679 std::cerr <<
"WARNING: line of vertex " << real_li - 3 <<
" no double in RGB[A] component " << i <<
" but <" << toks[i+3] <<
">." << std::endl;
683 while (vertex_colors.size() + 1 < positions.size())
684 vertex_colors.push_back(vertex_colors.empty() ?
cgv::rgba(0.5, 0.5, 0.5, 1.0f) : vertex_colors.back());
685 vertex_colors.push_back(
cgv::rgba(
float(c[0]),
float(c[1]),
float(c[2]),
float(1.0-c[3])));
691 std::cerr <<
"WARNING: first token on face " << faces.size() <<
" is not of type integer " << std::endl;
694 if (!(toks.size() == n + 1 || toks.size() == n + 4 || toks.size() == n + 5)) {
695 std::cerr <<
"WARNING: line of face " << faces.size() <<
" contains " << toks.size() <<
" tokens instead of " << n+1 <<
" or " << n+5 << std::endl;
699 auto& face = faces.back();
700 for (
int i = 0; i<n; ++i) {
703 std::cerr <<
"WARNING: token " << i+1 <<
" on face " << faces.size()-1 <<
" is not of type integer " << std::endl;
706 face.push_back(uint32_t(pi));
708 if (toks.size() >= n + 4) {
709 double c[4] = { 0,0,0,1 };
710 for (
unsigned i = 0; i < toks.size()-n-1; ++i) {
712 std::cerr <<
"WARNING: line of vertex " << real_li - 3 <<
" no double in RGBA component " << i <<
" but <" << toks[i + n + 1] <<
">." << std::endl;
716 while (face_colors.size()+1 < faces.size())
717 face_colors.push_back(face_colors.empty() ?
cgv::rgba(0.5, 0.5, 0.5, 1.0f) : face_colors.back());
718 face_colors.push_back(
cgv::rgba(
float(c[0]),
float(c[1]),
float(c[2]),
float(1.0 - c[3])));
737 stl_reader::StlMesh <T, unsigned> mesh(file_name);
740 for (
size_t vi = 0; vi < mesh.
num_vrts(); ++vi)
745 for (
size_t ti = 0; ti < mesh.
num_tris(); ++ti) {
749 for (
size_t ci = 0; ci < 3; ++ci)
750 new_corner(mesh.
tri_corner_ind(ti, ci), has_normals ? (
unsigned)ti : -1);
754 catch (std::exception& e) {
755 std::cout << e.what() << std::endl;
760 ensure_colors(cgv::media::ColorType::CT_RGBA);
761 auto& vertex_colors = *
reinterpret_cast<std::vector<cgv::rgba>*
>(ref_color_data_vector_ptr());
762 std::vector<cgv::rgba> face_colors;
763 std::vector<std::vector<idx_type>> faces;
764 if (!read_off(file_name, ref_positions(), vertex_colors, faces, face_colors))
766 for (
const auto& f : faces) {
773 std::cerr <<
"unknown mesh file extension '*." << ext <<
"'" << std::endl;
781 std::ofstream os(file_name);
784 for (
const auto& p : positions)
785 os <<
"v " << p << std::endl;
786 for (
const auto& t : tex_coords)
787 os <<
"vt " << t << std::endl;
788 for (
const auto& n : normals)
789 os <<
"vn " << n << std::endl;
791 bool nmls = position_indices.size() == normal_indices.size();
792 bool tcs = position_indices.size() == tex_coord_indices.size();
794 for (
idx_type fi = 0; fi < faces.size(); ++fi) {
796 for (
idx_type ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
797 os <<
" " << position_indices[ci] + 1;
802 os << tex_coord_indices[ci] + 1;
804 os <<
"/" << normal_indices[ci] + 1;
816 for (
const auto& p : positions)
828 normal_indices = position_indices;
830 normals.resize(positions.size(),
vec3_type(T(0)));
831 if (use_parallel_implementation) {
832#pragma omp parallel for
833 for (
int fi = 0; fi < int(get_nr_faces()); ++fi) {
835 if (compute_face_normal(fi, nml))
836 for (
idx_type ci = begin_corner(fi); ci < end_corner(fi); ++ci)
837 normal(normal_indices[ci]) += nml;
839#pragma omp parallel for
840 for (
int ni = 0; ni < int(normals.size()); ++ni)
841 normals[ni].normalize();
845 for (
idx_type fi = 0; fi < get_nr_faces(); ++fi)
846 if (compute_face_normal(fi, nml))
847 for (
idx_type ci = begin_corner(fi); ci < end_corner(fi); ++ci)
848 normal(normal_indices[ci]) += nml;
849 for (
auto& n : normals)
856 bool include_tex_coords,
bool include_normals,
857 bool include_tangents, std::vector<T>& attrib_buffer,
858 bool* include_colors_ptr,
int* num_floats_in_vertex)
const
861 include_tex_coords = include_tex_coords && !tex_coord_indices.empty() && !tex_coords.empty();
862 include_normals = include_normals && !normal_indices.empty() && !normals.empty();
863 include_tangents = include_tangents && !tangent_indices.empty() && !tangents.empty();
864 bool include_colors =
false;
865 if (include_colors_ptr)
866 *include_colors_ptr = include_colors = has_colors() && get_nr_colors() > 0 && *include_colors_ptr;
869 unsigned nr_floats = 3;
870 nr_floats += include_tex_coords ? 2 : 0;
871 nr_floats += include_normals ? 3 : 0;
872 nr_floats += include_tangents ? 3 : 0;
873 unsigned color_increment = 0;
874 if (include_colors) {
875 color_increment = (int)ceil((
float)get_color_size() /
sizeof(T));
876 nr_floats += color_increment;
879 if (num_floats_in_vertex)
880 *num_floats_in_vertex = nr_floats;
882 attrib_buffer.resize(nr_floats * unique_quadruples.size());
883 T* data_ptr = &attrib_buffer.front();
884 for (
auto t : unique_quadruples) {
885 *
reinterpret_cast<vec3_type*
>(data_ptr) = positions[t[0]];
887 if (include_tex_coords) {
888 *
reinterpret_cast<vec2_type*
>(data_ptr) = tex_coords[t[1]];
891 if (include_normals) {
892 *
reinterpret_cast<vec3_type*
>(data_ptr) = normals[t[2]];
895 if (include_tangents) {
896 *
reinterpret_cast<vec3_type*
>(data_ptr) = tangents[t[3]];
899 if (include_colors) {
900 put_color(t[0], data_ptr);
901 data_ptr += color_increment;
904 return color_increment;
909 mat3_type inverse_linear_transform = cgv::math::inverse(linear_transformation);
910 transform(linear_transformation, translation, inverse_linear_transform);
914 for (
auto& p : positions)
915 p = linear_transform * p + translation;
916 for (
auto& n : normals)
917 n = n * inverse_linear_transform;
918 for(
auto& t : tangents)
919 t = t * inverse_linear_transform;
926 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
927 ctr += position(c2p(ci));
937 vec3_type p0 = position(position_indices[c0]);
938 vec3_type dj = position(position_indices[c0 + 1]) - p0;
940 for (
idx_type ci = c0 + 2; ci < ce; ++ci) {
941 vec3_type di = position(position_indices[ci]) - p0;
942 nml += cross(dj, di);
959 if (construct_normal_indices)
960 normal_indices.clear();
963 for (uint32_t fi = 0; fi < get_nr_faces(); ++fi) {
965 compute_face_normal(fi, nml);
966 uint32_t ni = new_normal(nml);
967 if (construct_normal_indices) {
968 for (
idx_type ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
969 normal_indices.push_back(ni);
976 return normalize(cross(p1 - p0, p2 - p0));
980 if(!has_tex_coords())
983 for(uint32_t fi = 0; fi < get_nr_faces(); ++fi) {
984 std::vector<vec3_type> _P;
985 std::vector<vec2_type> _T;
988 for(ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
989 _P.push_back(position(c2p(ci)));
990 _T.push_back(tex_coord(c2t(ci)));
1003 float dir_correction = (delta_uv1.
x() * delta_uv0.
y() - delta_uv1.
y() * delta_uv0.
x()) < 0.0f ? -1.0f : 1.0f;
1006 if(delta_uv0.
x() * delta_uv1.
y() == delta_uv0.
y() * delta_uv1.
x()) {
1007 delta_uv0.
x() = 0.0f;
1008 delta_uv0.
y() = 1.0f;
1009 delta_uv1.
x() = 1.0f;
1010 delta_uv1.
y() = 0.0f;
1013 tng.
x() = delta_uv0.
y() * edge1.
x() - delta_uv1.
y() * edge0.
x();
1014 tng.
y() = delta_uv0.
y() * edge1.
y() - delta_uv1.
y() * edge0.
y();
1015 tng.
z() = delta_uv0.
y() * edge1.
z() - delta_uv1.
y() * edge0.
z();
1016 tng *= dir_correction;
1018 std::cout <<
"could not compute tangent for non-triangular face" << std::endl;
1022 uint32_t ti = new_tangent(tng);
1023 if(construct_tangent_indices) {
1024 for(ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
1025 tangent_indices.push_back(ti);
1033 if (!conway_notation.empty())
1034 construct_conway_polyhedron(conway_notation);
1038 std::vector<uint32_t> c2e;
1039 std::vector<uint32_t> e2c;
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 e = compute_c2e(inv, c2e, &e2c);
1047 for (uint32_t ei = 0; ei < e; ++ei) {
1048 uint32_t pi = c2p(e2c[ei]);
1049 uint32_t pj = c2p(inv[e2c[ei]]);
1050 new_M.
new_position(normalize(position(pi) + 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)
1059 for (uint32_t pi = 0; pi < get_nr_positions(); ++pi) {
1060 uint32_t c0 = p2c[pi];
1074 std::vector<uint32_t> inv;
1075 std::vector<uint32_t> prev;
1076 std::vector<uint32_t> p2c;
1077 compute_inv(inv,
false, &p2c, 0, &prev);
1078 uint32_t c = get_nr_corners();
1081 for (uint32_t ci = 0; ci < c; ++ci) {
1082 uint32_t pi = c2p(ci);
1083 uint32_t pj = c2p(inv[ci]);
1084 new_M.
new_position(normalize((1 - lambda) * position(pi) + lambda * position(pj)));
1087 for (uint32_t fi = 0; fi < get_nr_faces(); ++fi) {
1089 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
1095 for (uint32_t pi = 0; pi < get_nr_positions(); ++pi) {
1096 uint32_t c0 = p2c[pi];
1110 std::vector<uint32_t> inv;
1111 std::vector<uint32_t> prev;
1112 std::vector<uint32_t> p2c;
1113 compute_inv(inv,
false, &p2c, 0, &prev);
1114 uint32_t c = get_nr_corners();
1117 for (uint32_t ci = 0; ci < c; ++ci) {
1118 uint32_t pi = c2p(ci);
1119 uint32_t pj = c2p(inv[ci]);
1120 new_M.
new_position(normalize((1 - lambda) * position(pi) + lambda * position(pj)));
1124 for (fi = 0; fi < get_nr_faces(); ++fi) {
1126 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1130 for (fi = 0; fi < get_nr_faces(); ++fi) {
1131 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci) {
1133 uint32_t prev_ci = prev[ci];
1140 for (uint32_t pi = 0; pi < get_nr_positions(); ++pi) {
1141 uint32_t c0 = p2c[pi];
1155 std::vector<uint32_t> c2f;
1156 std::vector<uint32_t> p2c;
1157 std::vector<uint32_t> inv;
1158 std::vector<uint32_t> prev;
1159 compute_inv(inv,
false, &p2c, 0, &prev);
1161 uint32_t f = get_nr_faces();
1164 for (uint32_t fi = 0; fi < f; ++fi) {
1166 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1167 ctr += position(c2p(ci));
1172 for (uint32_t pi = 0; pi < get_nr_positions(); ++pi) {
1173 uint32_t c0 = p2c[pi];
1187 std::vector<uint32_t> c2f;
1188 std::vector<uint32_t> p2c;
1189 std::vector<uint32_t> inv;
1190 std::vector<uint32_t> prev;
1191 compute_inv(inv,
false, &p2c, 0, &prev);
1193 uint32_t v = get_nr_positions();
1194 uint32_t f = get_nr_faces();
1195 uint32_t c = get_nr_corners();
1198 for (uint32_t pi = 0; pi < v; ++pi)
1201 for (uint32_t fi = 0; fi < f; ++fi) {
1203 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1204 ctr += position(c2p(ci));
1210 for (ci = 0; ci < c; ++ci) {
1211 uint32_t pi = c2p(ci);
1212 uint32_t pj = c2p(inv[ci]);
1213 new_M.
new_position(normalize((1 - lambda) * position(pi) + lambda * position(pj)));
1216 for (ci = 0; ci < c; ++ci) {
1217 uint32_t inv_ci = inv[ci];
1218 uint32_t prev_inv_ci = inv[prev[ci]];
1219 uint32_t fi = c2f[ci];
1220 uint32_t pi = c2p(ci);
1226 new_M.
new_corner(prev_inv_ci + v + f, new_fi);
1233 std::vector<uint32_t> c2e;
1234 std::vector<uint32_t> e2c;
1235 std::vector<uint32_t> inv;
1236 std::vector<uint32_t> prev;
1237 std::vector<uint32_t> p2c;
1238 compute_inv(inv,
false, &p2c, 0, &prev);
1239 uint32_t e = compute_c2e(inv, c2e, &e2c);
1240 std::vector<uint32_t> c2f;
1243 uint32_t f = get_nr_faces();
1244 uint32_t v = get_nr_positions();
1247 for (uint32_t pi = 0; pi < v; ++pi)
1251 for (uint32_t fi = 0; fi < f; ++fi) {
1253 for (uint32_t ci = begin_corner(fi); ci < end_corner(fi); ++ci)
1254 ctr += position(c2p(ci));
1260 for (uint32_t ei = 0; ei < e; ++ei) {
1261 uint32_t ci = e2c[ei];
1262 uint32_t fi = c2f[ci];
1263 uint32_t pi = c2p(ci);
1264 uint32_t cj = inv[ci];
1265 uint32_t fj = c2f[cj];
1266 uint32_t pj = c2p(cj);
1283 if (conway_notation.back() ==
'C' || conway_notation.back() ==
'O') {
1285 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 };
1286 static float N[6 * 3] = { -1,0,0, +1,0,0, 0,-1,0, 0,+1,0, 0,0,-1, 0,0,+1 };
1287 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 };
1288 for (
int vi = 0; vi < 8; ++vi)
1289 new_position(normalize(
vec3_type(3, &V[3 * vi])));
1290 for (
int ni = 0; ni < 6; ++ni)
1292 for (
int fi = 0; fi < 6; ++fi) {
1294 for (
int ci = 0; ci < 4; ++ci)
1295 new_corner(F[4 * fi + ci], fi);
1297 if (conway_notation.back() ==
'O')
1300 if (conway_notation.back() ==
'T' || conway_notation.back() ==
'I' || conway_notation.back() ==
'D') {
1301 static const float a = float(1.0 / (2 * sqrt(3.0)));
1302 static const float b = float(1.0 / (3 * sqrt(3.0 / 2)));
1303 static const float V[4 * 3] = { -0.5f, -a, -b, 0.5f, -a, -b, 0,2 * a, -b, 0, 0,2 * b };
1304 static const int F[4 * 3] = { 0,2,1,3,2,0,3,0,1,3,1,2 };
1305 for (
int vi = 0; vi < 4; ++vi)
1306 new_position(normalize(
vec3_type(3, &V[3 * vi])));
1307 for (
int fi = 0; fi < 4; ++fi) {
1309 new_normal(compute_normal(position(F[3 * fi]), position(F[3 * fi + 1]), position(F[3 * fi + 2])));
1310 for (
int ci = 0; ci < 3; ++ci)
1311 new_corner(F[3 * fi + ci], fi);
1313 if (conway_notation.back() !=
'T') {
1316 if (conway_notation.back() ==
'I')
1320 for (
int ci = (
int)conway_notation.size() - 1; ci >= 0; --ci) {
1321 switch (conway_notation[ci]) {
1322 case 't': truncate();
break;
1323 case 'a': ambo();
break;
1324 case 'd': dual();
break;
1325 case 'j': join();
break;
1326 case 'o': ortho();
break;
1327 case 's': snub();
break;
1328 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.