scimesh 0.3.4
Headless CPU-only 3D software renderer for scientific mesh visualization
Loading...
Searching...
No Matches
transforms.cpp
Go to the documentation of this file.
3#include <glm/gtc/matrix_transform.hpp>
4#include <cmath>
5
6namespace scimesh {
7
8namespace {
9
20void transform_normals(Mesh &mesh, const Mat4 &matrix) {
21 if (!mesh.has_normals()) {
22 return;
23 }
24
25 glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(matrix)));
26 bool usable = true;
27 for (int col = 0; col < 3 && usable; ++col) {
28 for (int row = 0; row < 3 && usable; ++row) {
29 if (!std::isfinite(normal_matrix[col][row])) {
30 usable = false;
31 }
32 }
33 }
34 if (!usable) {
35 normal_matrix = glm::mat3(matrix);
36 }
37
38 for (auto &n : mesh.normals) {
40 float len = glm::length(transformed);
41 if (len > 1e-12f) {
42 n = transformed / len;
43 }
44 }
45}
46
47} // anonymous namespace
48
49void translate_mesh(Mesh &mesh, const Vec3 &translation) {
50 Mat4 m = glm::translate(Mat4(1.0f), translation);
51 for (auto &v : mesh.vertices) {
52 v = transform_point(m, v);
53 }
54 // Translation does not change directions, so normals stay valid as they are.
55}
56
57void scale_mesh(Mesh &mesh, const Vec3 &scale) {
58 Mat4 m = glm::scale(Mat4(1.0f), scale);
59 for (auto &v : mesh.vertices) {
60 v = transform_point(m, v);
61 }
62 transform_normals(mesh, m);
63}
64
65void scale_mesh(Mesh &mesh, float uniform_scale) {
67}
68
69void rotate_mesh(Mesh &mesh, float angle_radians, const Vec3 &axis) {
70 Mat4 m = glm::rotate(Mat4(1.0f), angle_radians, axis);
71 for (auto &v : mesh.vertices) {
72 v = transform_point(m, v);
73 }
74 transform_normals(mesh, m);
75}
76
77void transform_mesh(Mesh &mesh, const Mat4 &matrix) {
78 for (auto &v : mesh.vertices) {
80 }
82}
83
84Mesh mesh_from_fs(const std::vector<float> &fs_vertices,
85 const std::vector<uint32_t> &fs_faces,
86 const std::vector<float> &per_vertex_values,
87 const std::vector<uint8_t> &rgb_bytes,
89 Mesh out;
90 size_t nv = fs_vertices.size() / 3;
91 out.vertices.reserve(nv);
92
93 bool have_values = !per_vertex_values.empty();
94 bool have_rgb = !rgb_bytes.empty();
95
96 for (size_t i = 0; i < nv; i++) {
97 out.vertices.push_back(Vec3(
98 fs_vertices[i * 3],
99 fs_vertices[i * 3 + 1],
100 fs_vertices[i * 3 + 2]));
101
102 if (have_values && std::isnan(per_vertex_values[i])) {
103 // NaN marks "no data" (e.g. the medial wall in FreeSurfer brain
104 // surfaces). With detect_transparency such vertices become holes
105 // (alpha 0) instead of opaque white ones - the renderer then shows
106 // whatever is behind them.
107 out.colors.push_back(Color(1.0f, 1.0f, 1.0f,
108 detect_transparency ? 0.0f : 1.0f));
109 } else if (have_rgb) {
110 out.colors.push_back(Color(
111 rgb_bytes[i * 3] / 255.0f,
112 rgb_bytes[i * 3 + 1] / 255.0f,
113 rgb_bytes[i * 3 + 2] / 255.0f,
114 1.0f));
115 }
116 }
117
118 size_t nf = fs_faces.size() / 3;
119 out.triangles.reserve(nf);
120 for (size_t i = 0; i < nf; i++) {
121 out.triangles.push_back(Triangle{
122 fs_faces[i * 3],
123 fs_faces[i * 3 + 1],
124 fs_faces[i * 3 + 2]});
125 }
126
127 // Transparent vertices (NaN per-vertex values with detect_transparency) need
128 // the renderer's blended pass.
129 out.update_transparency();
130
131 return out;
132}
133
134void flip_uvs(Mesh &mesh) {
135 for (Vec2 &uv : mesh.uvs) {
136 uv.y = 1.0f - uv.y;
137 }
138}
139
140} // namespace scimesh
Low-level math utilities for the rendering pipeline.
glm::vec2 Vec2
2-component floating-point vector (xy).
Definition types.h:32
glm::mat4 Mat4
4×4 floating-point matrix.
Definition types.h:65
void flip_uvs(Mesh &mesh)
Flip the texture coordinates of a mesh vertically (v → 1 − v).
glm::vec3 Vec3
3-component floating-point vector (xyz).
Definition types.h:46
Vec3 transform_point(const Mat4 &m, const Vec3 &p)
Transform a point by a 4×4 matrix (with implicit w=1).
Definition math_utils.h:60
void scale_mesh(Mesh &mesh, const Vec3 &scale)
Scale a mesh non-uniformly along each axis.
void rotate_mesh(Mesh &mesh, float angle_radians, const Vec3 &axis)
Rotate a mesh around an arbitrary axis.
Mesh mesh_from_fs(const std::vector< float > &fs_vertices, const std::vector< uint32_t > &fs_faces, const std::vector< float > &per_vertex_values, const std::vector< uint8_t > &rgb_bytes, bool detect_transparency)
Convert a FreeSurfer-format mesh (flat vertex/face arrays) to a scimesh Mesh.
void transform_mesh(Mesh &mesh, const Mat4 &matrix)
Apply an arbitrary 4×4 transformation matrix to a mesh.
void translate_mesh(Mesh &mesh, const Vec3 &translation)
Translate (move) a mesh by a displacement vector.
An RGBA color with floating-point components.
Definition types.h:88
A 3D triangle mesh using an indexed face set representation.
Definition mesh.h:76
std::vector< Vec3 > vertices
3D vertex positions.
Definition mesh.h:86
std::vector< Vec2 > uvs
Per-vertex texture coordinates (UVs).
Definition mesh.h:148
A triangle defined by three vertex indices.
Definition types.h:127
int x
Left edge of the bitmap, in image pixels.
Definition text.cpp:223
Mesh transformation functions: translate, scale, rotate, and general matrix transforms.