Lagrange
Loading...
Searching...
No Matches
generate_subdivided_sphere.h
1/*
2 * Copyright 2020 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13#include <lagrange/Mesh.h>
14#include <lagrange/attributes/attribute_utils.h>
15#include <lagrange/create_mesh.h>
16#include <lagrange/legacy/inline.h>
17#include <lagrange/primitive/generation_utils.h>
18#include <lagrange/subdivision/mesh_subdivision.h>
19
20namespace lagrange {
21namespace primitive {
22LAGRANGE_LEGACY_INLINE
23namespace legacy {
24
25template <typename MeshType>
26std::unique_ptr<MeshType> generate_subdivided_sphere(
27 const MeshType& base_shape,
28 const typename MeshType::Scalar radius,
29 const Eigen::Matrix<typename MeshType::Scalar, 3, 1>& center = {0, 0, 0},
30 const typename MeshType::Index num_subdivisions = 0)
31{
32 static_assert(MeshTrait<MeshType>::is_mesh(), "Input type is not Mesh");
33
34 using VertexArray = typename MeshType::VertexArray;
35 using VertexType = typename MeshType::VertexType;
36 using UVArray = typename MeshType::UVArray;
37 using Scalar = typename MeshType::Scalar;
38
39 la_runtime_assert(radius >= 0.0, "Invalid radius: " + std::to_string(radius));
41 num_subdivisions >= 0,
42 "Invalid number of subdivisions: " + std::to_string(num_subdivisions));
43
44 auto mesh = create_mesh(base_shape.get_vertices(), base_shape.get_facets());
45
46 if (num_subdivisions == 0) {
47 // Copy over UVs if any
48 if (base_shape.is_uv_initialized()) {
49 mesh->initialize_uv(base_shape.get_uv(), base_shape.get_uv_indices());
50 }
51 lagrange::set_uniform_semantic_label(*mesh, PrimitiveSemanticLabel::SIDE);
52 return mesh;
53 }
54
55 subdivision::SubdivisionScheme scheme_type;
56
57 switch (mesh->get_vertex_per_facet()) {
58 case 3:
59 // Triangle Mesh
60 scheme_type = subdivision::SubdivisionScheme::SCHEME_LOOP;
61 break;
62 case 4:
63 // Quad Mesh
64 scheme_type = subdivision::SubdivisionScheme::SCHEME_CATMARK;
65 break;
66 default: scheme_type = subdivision::SubdivisionScheme::SCHEME_CATMARK;
67 }
68
69 auto subdivided_mesh =
70 subdivision::subdivide_mesh<MeshType, MeshType>(*mesh, scheme_type, num_subdivisions);
71
72 VertexArray subdiv_vertices;
73 subdivided_mesh->export_vertices(subdiv_vertices);
74
75 const VertexType base_center =
76 0.5 * (subdiv_vertices.colwise().minCoeff() + subdiv_vertices.colwise().maxCoeff());
77
78 constexpr Scalar comparison_tol = 1e-5;
79 const VertexArray centered_vertices = subdiv_vertices.rowwise() - base_center;
80
81 if (centered_vertices.norm() > comparison_tol) {
82 subdiv_vertices =
83 (centered_vertices.rowwise().normalized() * radius).rowwise() + center.transpose();
84 } else {
85 subdiv_vertices = centered_vertices.rowwise() + center.transpose();
86 }
87 subdivided_mesh->import_vertices(subdiv_vertices);
88
89 UVArray uvs = compute_spherical_uv_mapping<MeshType>(*subdivided_mesh, center);
90 subdivided_mesh->add_corner_attribute("uv");
91 subdivided_mesh->set_corner_attribute("uv", uvs);
92 map_corner_attribute_to_indexed_attribute(*subdivided_mesh, "uv");
93 subdivided_mesh->remove_corner_attribute("uv");
94 assert(subdivided_mesh->is_uv_initialized());
95
96 // Set uniform semantic label
97 lagrange::set_uniform_semantic_label(*subdivided_mesh, PrimitiveSemanticLabel::SIDE);
98
99 return subdivided_mesh;
100}
101
102} // namespace legacy
103} // namespace primitive
104} // namespace lagrange
Index get_vertex_per_facet() const
Retrieves the number of vertex per facet in a regular mesh.
Definition SurfaceMesh.cpp:2336
@ Scalar
Mesh attribute must have exactly 1 channel.
Definition AttributeFwd.h:56
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:174
Main namespace for Lagrange.
auto create_mesh(const Eigen::MatrixBase< DerivedV > &vertices, const Eigen::MatrixBase< DerivedF > &facets)
This function create a new mesh given the vertex and facet arrays by copying data into the Mesh objec...
Definition create_mesh.h:39