diff --git a/edition/mesh_sdf.cpp b/edition/mesh_sdf.cpp index 26927fa9..caeca7c1 100644 --- a/edition/mesh_sdf.cpp +++ b/edition/mesh_sdf.cpp @@ -45,8 +45,8 @@ inline TriangleIntersectionResult ray_intersects_triangle(const Vector3f &p_from const Vector3f &p_v0, const Vector3f &p_v1, const Vector3f &p_v2) { const Vector3f e1 = p_v1 - p_v0; const Vector3f e2 = p_v2 - p_v0; - const Vector3f h = p_dir.cross(e2); - const float a = e1.dot(h); + const Vector3f h = math::cross(p_dir, e2); + const float a = math::dot(e1, h); if (Math::abs(a) < 0.00001f) { return { TriangleIntersectionResult::PARALLEL, -1 }; @@ -55,15 +55,15 @@ inline TriangleIntersectionResult ray_intersects_triangle(const Vector3f &p_from const float f = 1.0f / a; const Vector3f s = p_from - p_v0; - const float u = f * s.dot(h); + const float u = f * math::dot(s, h); if ((u < 0.0f) || (u > 1.0f)) { return { TriangleIntersectionResult::NO_INTERSECTION, -1 }; } - const Vector3f q = s.cross(e1); + const Vector3f q = math::cross(s, e1); - const float v = f * p_dir.dot(q); + const float v = f * math::dot(p_dir, q); if ((v < 0.0f) || (u + v > 1.0f)) { return { TriangleIntersectionResult::NO_INTERSECTION, -1 }; @@ -71,7 +71,7 @@ inline TriangleIntersectionResult ray_intersects_triangle(const Vector3f &p_from // At this stage we can compute t to find out where // the intersection point is on the line. - const float t = f * e2.dot(q); + const float t = f * math::dot(e2, q); if (t > 0.00001f) { // ray intersection //r_res = p_from + p_dir * t; @@ -134,7 +134,7 @@ TriangleIntersectionResult ray_intersects_triangle2(const Vector3f &p_from, cons } inline Vector3f get_normal(const Triangle &t) { - return t.v13.cross(t.v1 - t.v2).normalized(); + return math::cross(t.v13, math::normalized(t.v1 - t.v2)); } // const Triangle *raycast(Span triangles, Vector3f ray_position, Vector3f ray_dir) { @@ -264,7 +264,7 @@ bool find_sdf_sign_with_raycast( //ZN_PROFILE_SCOPE(); const Vector3f ref_center = (ref_triangle.v1 + ref_triangle.v2 + ref_triangle.v3) / 3.f; - const Vector3f ray_dir = (ref_center - ray_position).normalized(); + const Vector3f ray_dir = math::normalized(ref_center - ray_position); #ifdef ZN_MESH_SDF_DEBUG_BATCH DDD::draw_line(ray_position, ray_position + ray_dir * 10.f, Color(0, 1, 0)); @@ -283,14 +283,14 @@ bool find_sdf_sign_with_raycast( if (s_tri_not_found_error == false) { s_tri_not_found_error = true; ZN_PRINT_VERBOSE( - format("Could not find triangle by raycast, dp: {}", get_normal(ref_triangle).dot(ray_dir))); + format("Could not find triangle by raycast, dp: {}", math::dot(get_normal(ref_triangle), ray_dir))); } #endif return false; } const Vector3f triangle_normal = get_normal(*selected_triangle); - const float dp = triangle_normal.dot(ray_dir); + const float dp = math::dot(triangle_normal, ray_dir); // Same direction (+): we are inside, sign is negative // Opposite direction (-): we are outside, sign is positive out_sign = dp < 0.f ? 1 : -1; @@ -626,26 +626,26 @@ float get_distance_to_triangle_squared(const Vector3f v1, const Vector3f v2, con float get_distance_to_triangle_squared_precalc(const Triangle &t, const Vector3f p) { // https://iquilezles.org/articles/triangledistance/ + using namespace math; + const Vector3f p1 = p - t.v1; const Vector3f p2 = p - t.v2; const Vector3f p3 = p - t.v3; const float det = // - math::sign_nonzero(t.v21_cross_nor.dot(p1)) + // - math::sign_nonzero(t.v32_cross_nor.dot(p2)) + // - math::sign_nonzero(t.v13_cross_nor.dot(p3)); + sign_nonzero(dot(t.v21_cross_nor, p1)) + // + sign_nonzero(dot(t.v32_cross_nor, p2)) + // + sign_nonzero(dot(t.v13_cross_nor, p3)); if (det < 2.f) { // Outside of the prism: get distance to closest edge - return math::min( - math::min( // - (t.v21 * math::clamp(t.v21.dot(p1) * t.inv_v21_length_squared, 0.f, 1.f) - p1).length_squared(), - (t.v32 * math::clamp(t.v32.dot(p2) * t.inv_v32_length_squared, 0.f, 1.f) - p2) - .length_squared()), - (t.v13 * math::clamp(t.v13.dot(p3) * t.inv_v13_length_squared, 0.f, 1.f) - p3).length_squared()); + return min(min( // + length_squared(t.v21 * clamp(dot(t.v21, p1) * t.inv_v21_length_squared, 0.f, 1.f) - p1), + length_squared(t.v32 * clamp(dot(t.v32, p2) * t.inv_v32_length_squared, 0.f, 1.f) - p2)), + length_squared(t.v13 * clamp(dot(t.v13, p3) * t.inv_v13_length_squared, 0.f, 1.f) - p3)); } else { // Inside the prism: get distance to plane - return math::squared(t.nor.dot(p1)) * t.inv_nor_length_squared; + return squared(dot(t.nor, p1)) * t.inv_nor_length_squared; } } @@ -656,14 +656,14 @@ void precalc_triangles(Span triangles) { t.v21 = t.v2 - t.v1; t.v32 = t.v3 - t.v2; t.v13 = t.v1 - t.v3; - t.nor = t.v21.cross(t.v13); - t.v21_cross_nor = t.v21.cross(t.nor); - t.v32_cross_nor = t.v32.cross(t.nor); - t.v13_cross_nor = t.v13.cross(t.nor); - t.inv_v21_length_squared = 1.f / t.v21.length_squared(); - t.inv_v32_length_squared = 1.f / t.v32.length_squared(); - t.inv_v13_length_squared = 1.f / t.v13.length_squared(); - t.inv_nor_length_squared = 1.f / t.nor.length_squared(); + t.nor = math::cross(t.v21, t.v13); + t.v21_cross_nor = math::cross(t.v21, t.nor); + t.v32_cross_nor = math::cross(t.v32, t.nor); + t.v13_cross_nor = math::cross(t.v13, t.nor); + t.inv_v21_length_squared = 1.f / math::length_squared(t.v21); + t.inv_v32_length_squared = 1.f / math::length_squared(t.v32); + t.inv_v13_length_squared = 1.f / math::length_squared(t.v13); + t.inv_nor_length_squared = 1.f / math::length_squared(t.nor); } } @@ -732,9 +732,9 @@ float get_mesh_signed_distance_at(const Vector3f pos, Span trian //} else { // normal = (p_point1 - p_point2).cross(p_point1 - p_point3); //} - const float plane_d = plane_normal.dot(ct.v1); + const float plane_d = math::dot(plane_normal, ct.v1); - if (plane_normal.dot(pos) > plane_d) { + if (math::dot(plane_normal, pos) > plane_d) { return d; } return -d; @@ -780,9 +780,9 @@ float get_mesh_signed_distance_at(const Vector3f pos, const ChunkGrid &chunk_gri //} else { // normal = (p_point1 - p_point2).cross(p_point1 - p_point3); //} - const float plane_d = plane_normal.dot(closest_tri->v1); + const float plane_d = math::dot(plane_normal, closest_tri->v1); - if (plane_normal.dot(pos) > plane_d) { + if (math::dot(plane_normal, pos) > plane_d) { return d; } return -d; @@ -843,7 +843,7 @@ void generate_mesh_sdf_approx_interp(Span sdf_grid, const Vector3i res, S const unsigned int node_size_cells = 1 << node_size_po2; const Vector3i node_grid_size = math::ceildiv(res, node_size_cells) + Vector3i(1, 1, 1); - const float node_size = node_size_cells * cell_size.length(); + const float node_size = node_size_cells * math::length(cell_size); const float node_subdiv_threshold = 0.6f * node_size; std::vector node_grid; @@ -1445,7 +1445,7 @@ void generate_mesh_sdf_approx_floodfill(Span sdf_grid, const Vector3i res dds[0b001] = cell_size.z; dds[0b101] = Math::sqrt(math::squared(cell_size.x) + math::squared(cell_size.z)); dds[0b011] = Math::sqrt(math::squared(cell_size.y) + math::squared(cell_size.z)); - dds[0b111] = cell_size.length(); + dds[0b111] = math::length(cell_size); std::vector seeds1; diff --git a/meshers/blocky/voxel_blocky_model.cpp b/meshers/blocky/voxel_blocky_model.cpp index 5d63e097..ada60bac 100644 --- a/meshers/blocky/voxel_blocky_model.cpp +++ b/meshers/blocky/voxel_blocky_model.cpp @@ -468,7 +468,7 @@ static void bake_mesh_geometry(VoxelBlockyModel &config, VoxelBlockyModel::Baked tangent[0] = t[0]; tangent[1] = t[1]; tangent[2] = t[2]; - tangent[3] = (bt.dot(to_vec3f(normals[indices[i]]).cross(t))) < 0 ? -1.0f : 1.0f; + tangent[3] = (math::dot(bt, math::cross(to_vec3f(normals[indices[i]]), t))) < 0 ? -1.0f : 1.0f; } if (L::get_triangle_side(tri_positions[0], tri_positions[1], tri_positions[2], side)) { diff --git a/meshers/blocky/voxel_mesher_blocky.cpp b/meshers/blocky/voxel_mesher_blocky.cpp index 56fa9174..3fc2f18c 100644 --- a/meshers/blocky/voxel_mesher_blocky.cpp +++ b/meshers/blocky/voxel_mesher_blocky.cpp @@ -257,7 +257,7 @@ void generate_blocky_mesh(std::vector &out_arrays_per if (bake_occlusion) { for (unsigned int i = 0; i < vertex_count; ++i) { - Vector3f vertex_pos = side_positions[i]; + const Vector3f vertex_pos = side_positions[i]; // General purpose occlusion colouring. // TODO Optimize for cubes @@ -271,7 +271,7 @@ void generate_blocky_mesh(std::vector &out_arrays_per static_cast(shaded_corner[corner]); //float k = 1.f - Cube::g_corner_position[corner].distance_to(v); float k = 1.f - - Cube::g_corner_position[corner].distance_squared_to(vertex_pos); + math::distance_squared(Cube::g_corner_position[corner], vertex_pos); if (k < 0.0) { k = 0.0; } diff --git a/meshers/dmc/voxel_mesher_dmc.cpp b/meshers/dmc/voxel_mesher_dmc.cpp index 899fce81..b3add903 100644 --- a/meshers/dmc/voxel_mesher_dmc.cpp +++ b/meshers/dmc/voxel_mesher_dmc.cpp @@ -127,7 +127,7 @@ bool can_split(Vector3i node_origin, int node_size, const VoxelAccess &voxels, f float interpolated_value = math::interpolate_trilinear(v0, v1, v2, v3, v4, v5, v6, v7, positions_ratio[i]); - float gradient_magnitude = value.gradient.length(); + float gradient_magnitude = math::length(value.gradient); if (gradient_magnitude < FLT_EPSILON) { gradient_magnitude = 1.0; } @@ -1039,26 +1039,22 @@ void DualGridGenerator::node_proc(OctreeNode *node) { inline Vector3f interpolate(const Vector3f &v0, const Vector3f &v1, const HermiteValue &val0, const HermiteValue &val1, Vector3f &out_normal) { if (Math::abs(val0.sdf - SURFACE_ISO_LEVEL) <= FLT_EPSILON) { - out_normal = val0.gradient; - out_normal.normalize(); + out_normal = math::normalized(val0.gradient); return v0; } if (Math::abs(val1.sdf - SURFACE_ISO_LEVEL) <= FLT_EPSILON) { - out_normal = val1.gradient; - out_normal.normalize(); + out_normal = math::normalized(val1.gradient); return v1; } if (Math::abs(val1.sdf - val0.sdf) <= FLT_EPSILON) { - out_normal = val0.gradient; - out_normal.normalize(); + out_normal = math::normalized(val0.gradient); return v0; } float mu = (SURFACE_ISO_LEVEL - val0.sdf) / (val1.sdf - val0.sdf); - out_normal = val0.gradient + mu * (val1.gradient - val0.gradient); - out_normal.normalize(); + out_normal = math::normalized(val0.gradient + mu * (val1.gradient - val0.gradient)); return v0 + mu * (v1 - v0); } @@ -1101,16 +1097,16 @@ void polygonize_cell_marching_squares(const Vector3f *cube_corners, const Hermit HermiteValue inner_val; inner_val = values[0]; // mSrc->getValueAndGradient(intersection_points[0]); - intersection_normals[0] = inner_val.gradient.normalized(); // * (inner_val.value + 1.0); + intersection_normals[0] = math::normalized(inner_val.gradient); // * (inner_val.value + 1.0); inner_val = values[1]; // mSrc->getValueAndGradient(intersection_points[2]); - intersection_normals[2] = inner_val.gradient.normalized(); // * (inner_val.value + 1.0); + intersection_normals[2] = math::normalized(inner_val.gradient); // * (inner_val.value + 1.0); inner_val = values[2]; // mSrc->getValueAndGradient(intersection_points[4]); - intersection_normals[4] = inner_val.gradient.normalized(); // * (inner_val.value + 1.0); + intersection_normals[4] = math::normalized(inner_val.gradient); // * (inner_val.value + 1.0); inner_val = values[3]; // mSrc->getValueAndGradient(intersection_points[6]); - intersection_normals[6] = inner_val.gradient.normalized(); // * (inner_val.value + 1.0); + intersection_normals[6] = math::normalized(inner_val.gradient); // * (inner_val.value + 1.0); if (edge & 1) { intersection_points[1] = interpolate(cube_corners[corner_map[0]], cube_corners[corner_map[1]], values[0], diff --git a/meshers/transvoxel/transvoxel.cpp b/meshers/transvoxel/transvoxel.cpp index cc3f3784..f889ab74 100644 --- a/meshers/transvoxel/transvoxel.cpp +++ b/meshers/transvoxel/transvoxel.cpp @@ -92,7 +92,7 @@ inline uint8_t get_border_mask(const Vector3i &pos, const Vector3i &block_size) } inline Vector3f normalized_not_null(Vector3f n) { - const float lengthsq = n.length_squared(); + const float lengthsq = math::length_squared(n); if (lengthsq == 0) { return Vector3f(0, 1, 0); } else { diff --git a/util/math/vector3.h b/util/math/vector3.h index 365ff8c5..c117eba2 100644 --- a/util/math/vector3.h +++ b/util/math/vector3.h @@ -18,6 +18,10 @@ inline bool has_nan(const Vector3 &v) { return Math::is_nan(v.x) || Math::is_nan(v.y) || Math::is_nan(v.z); } +inline bool is_normalized(const Vector3 &v) { + return v.is_normalized(); +} + } // namespace zylann::math #endif // ZN_VECTOR3_H diff --git a/util/math/vector3f.h b/util/math/vector3f.h index afe0e20b..b554b6e3 100644 --- a/util/math/vector3f.h +++ b/util/math/vector3f.h @@ -34,53 +34,6 @@ struct Vector3f { Vector3f(float p_x, float p_y, float p_z) : x(p_x), y(p_y), z(p_z) {} - inline float length_squared() const { - return x * x + y * y + z * z; - } - - inline float length() const { - return Math::sqrt(length_squared()); - } - - inline float distance_squared_to(const Vector3f &p_to) const { - return (p_to - *this).length_squared(); - } - - inline Vector3f cross(const Vector3f &p_with) const { - const Vector3f ret( // - (y * p_with.z) - (z * p_with.y), // - (z * p_with.x) - (x * p_with.z), // - (x * p_with.y) - (y * p_with.x)); - return ret; - } - - inline float dot(const Vector3f &p_with) const { - return x * p_with.x + y * p_with.y + z * p_with.z; - } - - inline void normalize() { - const float lengthsq = length_squared(); - if (lengthsq == 0) { - x = y = z = 0; - } else { - const float length = Math::sqrt(lengthsq); - x /= length; - y /= length; - z /= length; - } - } - - inline Vector3f normalized() const { - Vector3f v = *this; - v.normalize(); - return v; - } - - bool is_normalized() const { - // use length_squared() instead of length() to avoid sqrt(), makes it more stringent. - return Math::is_equal_approx(length_squared(), 1, float(UNIT_EPSILON)); - } - inline const float &operator[](const unsigned int p_axis) const { #ifdef DEBUG_ENABLED ZN_ASSERT(p_axis < AXIS_COUNT); @@ -214,8 +167,47 @@ inline bool has_nan(const Vector3f &v) { return Math::is_nan(v.x) || Math::is_nan(v.y) || Math::is_nan(v.z); } +inline float length_squared(const Vector3f v) { + return v.x * v.x + v.y * v.y + v.z * v.z; +} + +inline float length(const Vector3f &v) { + return Math::sqrt(length_squared(v)); +} + +inline float distance_squared(const Vector3f &a, const Vector3f &b) { + return length_squared(b - a); +} + +inline Vector3f cross(const Vector3f &a, const Vector3f &b) { + const Vector3f ret( // + (a.y * b.z) - (a.z * b.y), // + (a.z * b.x) - (a.x * b.z), // + (a.x * b.y) - (a.y * b.x)); + return ret; +} + +inline float dot(const Vector3f &a, const Vector3f &b) { + return a.x * b.x + a.y * b.y + a.z * b.z; +} + +inline Vector3f normalized(const Vector3f &v) { + const float lengthsq = length_squared(v); + if (lengthsq == 0) { + return Vector3f(); + } else { + const float length = Math::sqrt(lengthsq); + return v / length; + } +} + +inline bool is_normalized(const Vector3f &v) { + // use length_squared() instead of length() to avoid sqrt(), makes it more stringent. + return Math::is_equal_approx(length_squared(v), 1, float(UNIT_EPSILON)); +} + inline float distance(const Vector3f &a, const Vector3f &b) { - return Math::sqrt(a.distance_squared_to(b)); + return Math::sqrt(distance_squared(a, b)); } } // namespace math diff --git a/util/voxel_raycast.h b/util/voxel_raycast.h index 403b88a5..d091949b 100644 --- a/util/voxel_raycast.h +++ b/util/voxel_raycast.h @@ -52,7 +52,7 @@ bool voxel_raycast(Vec3f_T ray_origin, Vec3f_T ray_direction, Predicate_F predic // Note : the grid is assumed to have 1-unit square cells. - ZN_ASSERT_RETURN_V(ray_direction.is_normalized(), false); // Must be normalized + ZN_ASSERT_RETURN_V(math::is_normalized(ray_direction), false); // Must be normalized /* Initialisation */