Merge branch 'blender-v4.5-release'

This commit is contained in:
Jesse Yurkovich
2025-07-08 19:45:03 -07:00
3 changed files with 181 additions and 1 deletions

View File

@@ -199,7 +199,13 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime)
readFaceSetsSample(bmain, mesh, motionSampleTime);
if (mesh_prim_.GetPointsAttr().ValueMightBeTimeVarying() ||
mesh_prim_.GetVelocitiesAttr().ValueMightBeTimeVarying())
mesh_prim_.GetNormalsAttr().ValueMightBeTimeVarying() ||
mesh_prim_.GetVelocitiesAttr().ValueMightBeTimeVarying() ||
mesh_prim_.GetCreaseSharpnessesAttr().ValueMightBeTimeVarying() ||
mesh_prim_.GetCreaseLengthsAttr().ValueMightBeTimeVarying() ||
mesh_prim_.GetCreaseIndicesAttr().ValueMightBeTimeVarying() ||
mesh_prim_.GetCornerSharpnessesAttr().ValueMightBeTimeVarying() ||
mesh_prim_.GetCornerIndicesAttr().ValueMightBeTimeVarying())
{
is_time_varying_ = true;
}

View File

@@ -0,0 +1,126 @@
#usda 1.0
(
defaultPrim = "root"
doc = "Blender v4.5.0 Beta"
endTimeCode = 24
metersPerUnit = 1
startTimeCode = 1
timeCodesPerSecond = 24
upAxis = "Z"
)
def Xform "root" (
customData = {
dictionary Blender = {
bool generated = 1
}
}
)
{
def Xform "mesh_edge_crease"
{
def Mesh "mesh_edge_crease" (
active = true
)
{
int[] creaseIndices.timeSamples = {
1: [2, 0, 0, 1, 1, 3, 3, 2, 6, 2, 3, 7, 7, 6, 4, 6, 7, 5, 5, 4, 0, 4, 5, 1],
}
int[] creaseLengths.timeSamples = {
1: [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
}
float[] creaseSharpnesses.timeSamples = {
1: [0.017361112, 0.017361112, 0.017361112, 0.017361112, 0.017361112, 0.017361112, 0.017361112, 0.017361112, 0.017361112, 0.017361112, 0.017361112, 0.017361112],
2: [0.06944445, 0.06944445, 0.06944445, 0.06944445, 0.06944445, 0.06944445, 0.06944445, 0.06944445, 0.06944445, 0.06944445, 0.06944445, 0.06944445],
3: [0.15625, 0.15625, 0.15625, 0.15625, 0.15625, 0.15625, 0.15625, 0.15625, 0.15625, 0.15625, 0.15625, 0.15625],
4: [0.2777778, 0.2777778, 0.2777778, 0.2777778, 0.2777778, 0.2777778, 0.2777778, 0.2777778, 0.2777778, 0.2777778, 0.2777778, 0.2777778],
5: [0.43402776, 0.43402776, 0.43402776, 0.43402776, 0.43402776, 0.43402776, 0.43402776, 0.43402776, 0.43402776, 0.43402776, 0.43402776, 0.43402776],
6: [0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625],
7: [0.8506944, 0.8506944, 0.8506944, 0.8506944, 0.8506944, 0.8506944, 0.8506944, 0.8506944, 0.8506944, 0.8506944, 0.8506944, 0.8506944],
8: [1.1111112, 1.1111112, 1.1111112, 1.1111112, 1.1111112, 1.1111112, 1.1111112, 1.1111112, 1.1111112, 1.1111112, 1.1111112, 1.1111112],
9: [1.40625, 1.40625, 1.40625, 1.40625, 1.40625, 1.40625, 1.40625, 1.40625, 1.40625, 1.40625, 1.40625, 1.40625],
10: [1.736111, 1.736111, 1.736111, 1.736111, 1.736111, 1.736111, 1.736111, 1.736111, 1.736111, 1.736111, 1.736111, 1.736111],
11: [2.1006944, 2.1006944, 2.1006944, 2.1006944, 2.1006944, 2.1006944, 2.1006944, 2.1006944, 2.1006944, 2.1006944, 2.1006944, 2.1006944],
12: [2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5],
13: [2.934028, 2.934028, 2.934028, 2.934028, 2.934028, 2.934028, 2.934028, 2.934028, 2.934028, 2.934028, 2.934028, 2.934028],
14: [3.4027777, 3.4027777, 3.4027777, 3.4027777, 3.4027777, 3.4027777, 3.4027777, 3.4027777, 3.4027777, 3.4027777, 3.4027777, 3.4027777],
15: [3.90625, 3.90625, 3.90625, 3.90625, 3.90625, 3.90625, 3.90625, 3.90625, 3.90625, 3.90625, 3.90625, 3.90625],
16: [4.4444447, 4.4444447, 4.4444447, 4.4444447, 4.4444447, 4.4444447, 4.4444447, 4.4444447, 4.4444447, 4.4444447, 4.4444447, 4.4444447],
17: [5.017361, 5.017361, 5.017361, 5.017361, 5.017361, 5.017361, 5.017361, 5.017361, 5.017361, 5.017361, 5.017361, 5.017361],
18: [5.625, 5.625, 5.625, 5.625, 5.625, 5.625, 5.625, 5.625, 5.625, 5.625, 5.625, 5.625],
19: [6.2673616, 6.2673616, 6.2673616, 6.2673616, 6.2673616, 6.2673616, 6.2673616, 6.2673616, 6.2673616, 6.2673616, 6.2673616, 6.2673616],
20: [6.944444, 6.944444, 6.944444, 6.944444, 6.944444, 6.944444, 6.944444, 6.944444, 6.944444, 6.944444, 6.944444, 6.944444],
21: [7.65625, 7.65625, 7.65625, 7.65625, 7.65625, 7.65625, 7.65625, 7.65625, 7.65625, 7.65625, 7.65625, 7.65625],
22: [8.402778, 8.402778, 8.402778, 8.402778, 8.402778, 8.402778, 8.402778, 8.402778, 8.402778, 8.402778, 8.402778, 8.402778],
23: [9.184028, 9.184028, 9.184028, 9.184028, 9.184028, 9.184028, 9.184028, 9.184028, 9.184028, 9.184028, 9.184028, 9.184028],
24: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
}
float3[] extent = [(-0.5, -0.5, -0.5), (0.5, 0.5, 0.5)]
int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]
int[] faceVertexIndices = [0, 1, 3, 2, 2, 3, 7, 6, 6, 7, 5, 4, 4, 5, 1, 0, 2, 6, 4, 0, 7, 3, 1, 5]
normal3f[] normals = [(-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0), (1, 0, 0), (1, 0, 0), (1, 0, 0), (1, 0, 0), (0, -1, 0), (0, -1, 0), (0, -1, 0), (0, -1, 0), (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)] (
interpolation = "faceVarying"
)
point3f[] points = [(-0.5, -0.5, -0.5), (-0.5, -0.5, 0.5), (-0.5, 0.5, -0.5), (-0.5, 0.5, 0.5), (0.5, -0.5, -0.5), (0.5, -0.5, 0.5), (0.5, 0.5, -0.5), (0.5, 0.5, 0.5)]
texCoord2f[] primvars:st = [(0.375, 0), (0.625, 0), (0.625, 0.25), (0.375, 0.25), (0.375, 0.25), (0.625, 0.25), (0.625, 0.5), (0.375, 0.5), (0.375, 0.5), (0.625, 0.5), (0.625, 0.75), (0.375, 0.75), (0.375, 0.75), (0.625, 0.75), (0.625, 1), (0.375, 1), (0.125, 0.5), (0.375, 0.5), (0.375, 0.75), (0.125, 0.75), (0.625, 0.5), (0.875, 0.5), (0.875, 0.75), (0.625, 0.75)] (
interpolation = "faceVarying"
)
uniform token subdivisionScheme = "none"
}
}
def Xform "mesh_vert_crease"
{
float3 xformOp:rotateXYZ = (0, -0, 0)
float3 xformOp:scale = (1, 1, 1)
double3 xformOp:translate = (2, 0, 0)
uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"]
def Mesh "mesh_vert_crease" (
active = true
)
{
int[] cornerIndices.timeSamples = {
1: [0, 1, 2, 3],
}
float[] cornerSharpnesses.timeSamples = {
1: [0.017361112, 0.017361112, 0.017361112, 0.017361112],
2: [0.06944445, 0.06944445, 0.06944445, 0.06944445],
3: [0.15625, 0.15625, 0.15625, 0.15625],
4: [0.2777778, 0.2777778, 0.2777778, 0.2777778],
5: [0.43402776, 0.43402776, 0.43402776, 0.43402776],
6: [0.625, 0.625, 0.625, 0.625],
7: [0.8506944, 0.8506944, 0.8506944, 0.8506944],
8: [1.1111112, 1.1111112, 1.1111112, 1.1111112],
9: [1.40625, 1.40625, 1.40625, 1.40625],
10: [1.736111, 1.736111, 1.736111, 1.736111],
11: [2.1006944, 2.1006944, 2.1006944, 2.1006944],
12: [2.5, 2.5, 2.5, 2.5],
13: [2.934028, 2.934028, 2.934028, 2.934028],
14: [3.4027777, 3.4027777, 3.4027777, 3.4027777],
15: [3.90625, 3.90625, 3.90625, 3.90625],
16: [4.4444447, 4.4444447, 4.4444447, 4.4444447],
17: [5.017361, 5.017361, 5.017361, 5.017361],
18: [5.625, 5.625, 5.625, 5.625],
19: [6.2673616, 6.2673616, 6.2673616, 6.2673616],
20: [6.944444, 6.944444, 6.944444, 6.944444],
21: [7.65625, 7.65625, 7.65625, 7.65625],
22: [8.402778, 8.402778, 8.402778, 8.402778],
23: [9.184028, 9.184028, 9.184028, 9.184028],
24: [10, 10, 10, 10],
}
float3[] extent = [(-0.5, -0.5, 0), (0.5, 0.5, 0)]
int[] faceVertexCounts = [4]
int[] faceVertexIndices = [0, 1, 3, 2]
normal3f[] normals = [(0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)] (
interpolation = "faceVarying"
)
point3f[] points = [(-0.5, -0.5, 0), (0.5, -0.5, 0), (-0.5, 0.5, 0), (0.5, 0.5, 0)]
texCoord2f[] primvars:st = [(0, 0), (1, 0), (1, 1), (0, 1)] (
interpolation = "faceVarying"
)
uniform token subdivisionScheme = "none"
}
}
}

View File

@@ -288,6 +288,54 @@ class USDImportTest(AbstractUSDTest):
check_mod("mesh6", 1, 2, 'SMOOTH_ALL', 'ALL')
check_mod("mesh7", 1, 2, 'PRESERVE_BOUNDARIES', 'PRESERVE_CORNERS')
def test_import_mesh_subd_varying(self):
"""Test importing meshes with subdivision crease values varying over time."""
testfile = str(self.testdir / "usd_mesh_subd_varying_test.usda")
res = bpy.ops.wm.usd_import(filepath=testfile)
self.assertEqual({'FINISHED'}, res, f"Unable to import USD file {testfile}")
stage = Usd.Stage.Open(testfile)
#
# Validate Mesh data
#
blender_mesh1 = bpy.data.objects["mesh_edge_crease"]
blender_mesh2 = bpy.data.objects["mesh_vert_crease"]
usd_mesh1 = UsdGeom.Mesh(stage.GetPrimAtPath("/root/mesh_edge_crease/mesh_edge_crease"))
usd_mesh2 = UsdGeom.Mesh(stage.GetPrimAtPath("/root/mesh_vert_crease/mesh_vert_crease"))
# A MeshSequenceCache modifier should be present on every imported object
for blender_mesh in [blender_mesh1, blender_mesh2]:
self.assertTrue(len(blender_mesh.modifiers) == 1 and blender_mesh.modifiers[0].type ==
'MESH_SEQUENCE_CACHE', f"{blender_mesh.name} has incorrect modifiers")
# Conversion from USD to Blender convention
def sharpness_to_crease(sharpness):
return math.sqrt(sharpness * 0.1)
# Compare Blender and USD data against each other for every frame
for frame in range(1, 25):
bpy.context.scene.frame_set(frame)
depsgraph = bpy.context.evaluated_depsgraph_get()
blender_mesh1_eval = bpy.data.objects["mesh_edge_crease"].evaluated_get(depsgraph)
blender_mesh2_eval = bpy.data.objects["mesh_vert_crease"].evaluated_get(depsgraph)
# Check crease values
blender_crease_data = [round(d.value) for d in blender_mesh1_eval.data.attributes["crease_edge"].data]
usd_crease_data = [round(sharpness_to_crease(d)) for d in usd_mesh1.GetCreaseSharpnessesAttr().Get(frame)]
self.assertEqual(
blender_crease_data,
usd_crease_data,
f"Frame {frame}: {blender_mesh1_eval.name} crease values do not match")
blender_crease_data = [round(d.value) for d in blender_mesh2_eval.data.attributes["crease_vert"].data]
usd_crease_data = [round(sharpness_to_crease(d)) for d in usd_mesh2.GetCornerSharpnessesAttr().Get(frame)]
self.assertEqual(
blender_crease_data,
usd_crease_data,
f"Frame {frame}: {blender_mesh2_eval.name} crease values do not match")
def test_import_camera_properties(self):
"""Test importing camera to ensure properties set correctly."""