Skip to content

Commit

Permalink
updated
Browse files Browse the repository at this point in the history
  • Loading branch information
xelatihy committed Jan 31, 2024
1 parent d99e935 commit 24b2407
Show file tree
Hide file tree
Showing 2 changed files with 272 additions and 272 deletions.
272 changes: 272 additions & 0 deletions libs/yocto/yocto_math.h
Original file line number Diff line number Diff line change
Expand Up @@ -1258,6 +1258,67 @@ inline pair<vec3f, vec3f> quad_tangents_fromuv(vec3f p0, vec3f p1, vec3f p2,

} // namespace yocto

// -----------------------------------------------------------------------------
// COMPUTATION OF PER_VERTEX PROPERTIES
// -----------------------------------------------------------------------------
namespace yocto {

// Compute per-vertex normals/tangents for lines/triangles/quads.
inline vector<vec3f> lines_tangents(
const vector<vec2i>& lines, const vector<vec3f>& positions);
inline vector<vec3f> triangles_normals(
const vector<vec3i>& triangles, const vector<vec3f>& positions);
inline vector<vec3f> quads_normals(
const vector<vec4i>& quads, const vector<vec3f>& positions);
// Update normals and tangents
inline void lines_tangents(vector<vec3f>& tangents, const vector<vec2i>& lines,
const vector<vec3f>& positions);
inline void triangles_normals(vector<vec3f>& normals,
const vector<vec3i>& triangles, const vector<vec3f>& positions);
inline void quads_normals(vector<vec3f>& normals, const vector<vec4i>& quads,
const vector<vec3f>& positions);

// Compute per-vertex tangent space for triangle meshes.
// Tangent space is defined by a four component vector.
// The first three components are the tangent with respect to the u texcoord.
// The fourth component is the sign of the tangent wrt the v texcoord.
// Tangent frame is useful in normal mapping.
inline vector<vec4f> triangle_tangent_spaces(const vector<vec3i>& triangles,
const vector<vec3f>& positions, const vector<vec3f>& normals,
const vector<vec2f>& texcoords);

} // namespace yocto

// -----------------------------------------------------------------------------
// COMPUTATION OF VERTEX PROPERTIES
// -----------------------------------------------------------------------------
namespace yocto {

// Flip vertex normals
inline vector<vec3f> flip_normals(const vector<vec3f>& normals);
// Flip face orientation
inline vector<vec3i> flip_triangles(const vector<vec3i>& triangles);
inline vector<vec4i> flip_quads(const vector<vec4i>& quads);
// Align vertex positions. Alignment is 0: none, 1: min, 2: max, 3: center.
inline vector<vec3f> align_vertices(
const vector<vec3f>& positions, vec3i alignment);

} // namespace yocto

// -----------------------------------------------------------------------------
// SHAPE ELEMENT CONVERSION
// -----------------------------------------------------------------------------
namespace yocto {

// Convert quads to triangles
inline vector<vec3i> quads_to_triangles(const vector<vec4i>& quads);
// Convert triangles to quads by creating degenerate quads
inline vector<vec4i> triangles_to_quads(const vector<vec3i>& triangles);
// Convert beziers to lines using 3 lines for each bezier.
inline vector<vec4i> bezier_to_lines(vector<vec2i>& lines);

} // namespace yocto

// -----------------------------------------------------------------------------
// USER INTERFACE UTILITIES
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -3013,6 +3074,217 @@ inline pair<vec3f, vec3f> quad_tangents_fromuv(vec3f p0, vec3f p1, vec3f p2,

} // namespace yocto

// -----------------------------------------------------------------------------
// IMPLEMENTATION OF COMPUTATION OF PER-VERTEX PROPERTIES
// -----------------------------------------------------------------------------
namespace yocto {

// Compute per-vertex tangents for lines.
inline vector<vec3f> lines_tangents(
const vector<vec2i>& lines, const vector<vec3f>& positions) {
auto tangents = vector<vec3f>{positions.size()};
for (auto& tangent : tangents) tangent = {0, 0, 0};
for (auto& l : lines) {
auto tangent = line_tangent(positions[l.x], positions[l.y]);
auto length = line_length(positions[l.x], positions[l.y]);
tangents[l.x] += tangent * length;
tangents[l.y] += tangent * length;
}
for (auto& tangent : tangents) tangent = normalize(tangent);
return tangents;
}

// Compute per-vertex normals for triangles.
inline vector<vec3f> triangles_normals(
const vector<vec3i>& triangles, const vector<vec3f>& positions) {
auto normals = vector<vec3f>{positions.size()};
for (auto& normal : normals) normal = {0, 0, 0};
for (auto& t : triangles) {
auto normal = triangle_normal(
positions[t.x], positions[t.y], positions[t.z]);
auto area = triangle_area(positions[t.x], positions[t.y], positions[t.z]);
normals[t.x] += normal * area;
normals[t.y] += normal * area;
normals[t.z] += normal * area;
}
for (auto& normal : normals) normal = normalize(normal);
return normals;
}

// Compute per-vertex normals for quads.
inline vector<vec3f> quads_normals(
const vector<vec4i>& quads, const vector<vec3f>& positions) {
auto normals = vector<vec3f>{positions.size()};
for (auto& normal : normals) normal = {0, 0, 0};
for (auto& q : quads) {
auto normal = quad_normal(
positions[q.x], positions[q.y], positions[q.z], positions[q.w]);
auto area = quad_area(
positions[q.x], positions[q.y], positions[q.z], positions[q.w]);
normals[q.x] += normal * area;
normals[q.y] += normal * area;
normals[q.z] += normal * area;
if (q.z != q.w) normals[q.w] += normal * area;
}
for (auto& normal : normals) normal = normalize(normal);
return normals;
}

// Compute per-vertex tangents for lines.
inline void lines_tangents(vector<vec3f>& tangents, const vector<vec2i>& lines,
const vector<vec3f>& positions) {
if (tangents.size() != positions.size()) {
throw std::out_of_range("array should be the same length");
}
for (auto& tangent : tangents) tangent = {0, 0, 0};
for (auto& l : lines) {
auto tangent = line_tangent(positions[l.x], positions[l.y]);
auto length = line_length(positions[l.x], positions[l.y]);
tangents[l.x] += tangent * length;
tangents[l.y] += tangent * length;
}
for (auto& tangent : tangents) tangent = normalize(tangent);
}

// Compute per-vertex normals for triangles.
inline void triangles_normals(vector<vec3f>& normals,
const vector<vec3i>& triangles, const vector<vec3f>& positions) {
if (normals.size() != positions.size()) {
throw std::out_of_range("array should be the same length");
}
for (auto& normal : normals) normal = {0, 0, 0};
for (auto& t : triangles) {
auto normal = triangle_normal(
positions[t.x], positions[t.y], positions[t.z]);
auto area = triangle_area(positions[t.x], positions[t.y], positions[t.z]);
normals[t.x] += normal * area;
normals[t.y] += normal * area;
normals[t.z] += normal * area;
}
for (auto& normal : normals) normal = normalize(normal);
}

// Compute per-vertex normals for quads.
inline void quads_normals(vector<vec3f>& normals, const vector<vec4i>& quads,
const vector<vec3f>& positions) {
if (normals.size() != positions.size()) {
throw std::out_of_range("array should be the same length");
}
for (auto& normal : normals) normal = {0, 0, 0};
for (auto& q : quads) {
auto normal = quad_normal(
positions[q.x], positions[q.y], positions[q.z], positions[q.w]);
auto area = quad_area(
positions[q.x], positions[q.y], positions[q.z], positions[q.w]);
normals[q.x] += normal * area;
normals[q.y] += normal * area;
normals[q.z] += normal * area;
if (q.z != q.w) normals[q.w] += normal * area;
}
for (auto& normal : normals) normal = normalize(normal);
}

// Compute per-vertex tangent frame for triangle meshes.
// Tangent space is defined by a four component vector.
// The first three components are the tangent with respect to the U texcoord.
// The fourth component is the sign of the tangent wrt the V texcoord.
// Tangent frame is useful in normal mapping.
inline vector<vec4f> triangles_tangent_spaces(const vector<vec3i>& triangles,
const vector<vec3f>& positions, const vector<vec3f>& normals,
const vector<vec2f>& texcoords) {
auto tangu = vector<vec3f>(positions.size(), vec3f{0, 0, 0});
auto tangv = vector<vec3f>(positions.size(), vec3f{0, 0, 0});
for (auto t : triangles) {
auto tutv = triangle_tangents_fromuv(positions[t.x], positions[t.y],
positions[t.z], texcoords[t.x], texcoords[t.y], texcoords[t.z]);
for (auto vid : {t.x, t.y, t.z}) tangu[vid] += normalize(tutv.first);
for (auto vid : {t.x, t.y, t.z}) tangv[vid] += normalize(tutv.second);
}
for (auto& t : tangu) t = normalize(t);
for (auto& t : tangv) t = normalize(t);

auto tangent_spaces = vector<vec4f>(positions.size());
for (auto& tangent : tangent_spaces) tangent = vec4f{0, 0, 0, 0};
for (auto i = 0; i < positions.size(); i++) {
tangu[i] = orthonormalize(tangu[i], normals[i]);
auto s = (dot(cross(normals[i], tangu[i]), tangv[i]) < 0) ? -1.0f : 1.0f;
tangent_spaces[i] = {tangu[i].x, tangu[i].y, tangu[i].z, s};
}
return tangent_spaces;
}

} // namespace yocto

// -----------------------------------------------------------------------------
// COMPUTATION OF PER VERTEX PROPERTIES
// -----------------------------------------------------------------------------
namespace yocto {

// Flip vertex normals
inline vector<vec3f> flip_normals(const vector<vec3f>& normals) {
auto flipped = normals;
for (auto& n : flipped) n = -n;
return flipped;
}
// Flip face orientation
inline vector<vec3i> flip_triangles(const vector<vec3i>& triangles) {
auto flipped = triangles;
for (auto& t : flipped) swap(t.y, t.z);
return flipped;
}
inline vector<vec4i> flip_quads(const vector<vec4i>& quads) {
auto flipped = quads;
for (auto& q : flipped) {
if (q.z != q.w) {
swap(q.y, q.w);
} else {
swap(q.y, q.z);
q.w = q.z;
}
}
return flipped;
}

} // namespace yocto

// -----------------------------------------------------------------------------
// IMPLEMENTATION OF SHAPE ELEMENT CONVERSION
// -----------------------------------------------------------------------------
namespace yocto {

// Convert quads to triangles
inline vector<vec3i> quads_to_triangles(const vector<vec4i>& quads) {
auto triangles = vector<vec3i>{};
triangles.reserve(quads.size() * 2);
for (auto& q : quads) {
triangles.push_back({q.x, q.y, q.w});
if (q.z != q.w) triangles.push_back({q.z, q.w, q.y});
}
return triangles;
}

// Convert triangles to quads by creating degenerate quads
inline vector<vec4i> triangles_to_quads(const vector<vec3i>& triangles) {
auto quads = vector<vec4i>{};
quads.reserve(triangles.size());
for (auto& t : triangles) quads.push_back({t.x, t.y, t.z, t.z});
return quads;
}

// Convert beziers to lines using 3 lines for each bezier.
inline vector<vec2i> bezier_to_lines(const vector<vec4i>& beziers) {
auto lines = vector<vec2i>{};
lines.reserve(beziers.size() * 3);
for (auto b : beziers) {
lines.push_back({b.x, b.y});
lines.push_back({b.y, b.z});
lines.push_back({b.z, b.w});
}
return lines;
}

} // namespace yocto

// -----------------------------------------------------------------------------
// USER INTERFACE UTILITIES
// -----------------------------------------------------------------------------
Expand Down

0 comments on commit 24b2407

Please sign in to comment.