Fix: Prevent NURBS .obj importer from setting invalid degree/order

Default behavior in most edit mode operators is to adjust the order
if there is not enough points/knots to support it. If the degree is
incorrectly encoded in the file, import should update it to avoid
generating an invalid  NURBS curve.

Pull Request: https://projects.blender.org/blender/blender/pulls/138374
This commit is contained in:
Mattias Fredriksson
2025-05-07 17:41:39 +02:00
committed by Hans Goudey
parent fbb659c4c5
commit 87d04eadd4
2 changed files with 13 additions and 6 deletions

View File

@@ -73,10 +73,18 @@ Object *CurveFromGeometry::create_curve_object(Main *bmain, const OBJImportParam
return obj;
}
static int8_t get_valid_nurbs_degree(const NurbsElement &element)
{
/* Use max(1, min()) to avoid undefined clamp behavior when curve_indices.size() == 0 */
const int degree = std::max(1, std::min<int>(element.degree, element.curv_indices.size() - 1));
return degree + 1 > std::numeric_limits<int8_t>::max() ? std::numeric_limits<int8_t>::max() - 1 :
int8_t(degree);
}
void CurveFromGeometry::create_nurbs(Curve *curve, const OBJImportParams &import_params)
{
const NurbsElement &nurbs_geometry = curve_geometry_.nurbs_element_;
const int degree = nurbs_geometry.degree;
const int8_t degree = get_valid_nurbs_degree(nurbs_geometry);
Nurb *nurb = static_cast<Nurb *>(curve->nurb.first);
nurb->type = CU_NURBS;
@@ -87,8 +95,7 @@ void CurveFromGeometry::create_nurbs(Curve *curve, const OBJImportParams &import
nurb->pntsu = 0;
/* Total points = pntsu * pntsv. */
nurb->pntsv = 1;
nurb->orderu = nurb->orderv = (nurbs_geometry.degree + 1 > SHRT_MAX) ? 4 :
nurbs_geometry.degree + 1;
nurb->orderu = nurb->orderv = degree + 1;
nurb->resolu = nurb->resolv = curve->resolu;
nurb->flagu = this->detect_knot_mode(import_params,
@@ -136,7 +143,7 @@ void CurveFromGeometry::create_nurbs(Curve *curve, const OBJImportParams &import
}
short CurveFromGeometry::detect_knot_mode(const OBJImportParams &import_params,
const int degree,
const int8_t degree,
const Span<int> indices,
const Span<float> knots,
const float2 range)
@@ -170,7 +177,7 @@ short CurveFromGeometry::detect_knot_mode(const OBJImportParams &import_params,
* the parameters should have at least (degree+1) values on each end,
* and their values should match curve range. */
bool do_endpoints = false;
int order = degree + 1;
const int8_t order = degree + 1;
if (knots.size() >= order * 2) {
do_endpoints = true;
for (int i = 0; i < order; ++i) {

View File

@@ -45,7 +45,7 @@ class CurveFromGeometry : NonMovable, NonCopyable {
void create_nurbs(Curve *curve, const OBJImportParams &import_params);
short detect_knot_mode(const OBJImportParams &import_params,
int degree,
int8_t degree,
Span<int> indices,
Span<float> knots,
float2 range);