USD: Add support for Text objects during export
Similar to the existing meta-ball export, and the other exporters, convert Text objects to meshes for export. Ref #138883 Pull Request: https://projects.blender.org/blender/blender/pulls/138903
This commit is contained in:
committed by
Jesse Yurkovich
parent
de5d0cfdc5
commit
3b2bbad609
@@ -811,8 +811,8 @@ bool AbstractHierarchyIterator::mark_as_weak_export(const Object * /*object*/) c
|
||||
bool AbstractHierarchyIterator::should_visit_dupli_object(const DupliObject *dupli_object) const
|
||||
{
|
||||
/* Do not visit dupli objects if their `no_draw` flag is set (things like custom bone shapes) or
|
||||
* if they are meta-balls. */
|
||||
if (dupli_object->no_draw || dupli_object->ob->type == OB_MBALL) {
|
||||
* if they are meta-balls / text objects. */
|
||||
if (dupli_object->no_draw || ELEM(dupli_object->ob->type, OB_MBALL, OB_FONT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ set(SRC
|
||||
intern/usd_writer_mesh.cc
|
||||
intern/usd_writer_metaball.cc
|
||||
intern/usd_writer_points.cc
|
||||
intern/usd_writer_text.cc
|
||||
intern/usd_writer_transform.cc
|
||||
intern/usd_writer_volume.cc
|
||||
|
||||
@@ -133,6 +134,7 @@ set(SRC
|
||||
intern/usd_writer_mesh.hh
|
||||
intern/usd_writer_metaball.hh
|
||||
intern/usd_writer_points.hh
|
||||
intern/usd_writer_text.hh
|
||||
intern/usd_writer_transform.hh
|
||||
intern/usd_writer_volume.hh
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "usd_writer_mesh.hh"
|
||||
#include "usd_writer_metaball.hh"
|
||||
#include "usd_writer_points.hh"
|
||||
#include "usd_writer_text.hh"
|
||||
#include "usd_writer_transform.hh"
|
||||
#include "usd_writer_volume.hh"
|
||||
|
||||
@@ -52,6 +53,7 @@ bool USDHierarchyIterator::mark_as_weak_export(const Object *object) const
|
||||
return false;
|
||||
case OB_MESH:
|
||||
case OB_MBALL:
|
||||
case OB_FONT:
|
||||
return !params_.export_meshes;
|
||||
case OB_CAMERA:
|
||||
return !params_.export_cameras;
|
||||
@@ -174,6 +176,9 @@ AbstractHierarchyWriter *USDHierarchyIterator::create_data_writer(const Hierarch
|
||||
case OB_MBALL:
|
||||
data_writer = new USDMetaballWriter(usd_export_context);
|
||||
break;
|
||||
case OB_FONT:
|
||||
data_writer = new USDTextWriter(usd_export_context);
|
||||
break;
|
||||
case OB_CURVES_LEGACY:
|
||||
case OB_CURVES:
|
||||
if (usd_export_context.export_params.export_curves) {
|
||||
@@ -210,7 +215,6 @@ AbstractHierarchyWriter *USDHierarchyIterator::create_data_writer(const Hierarch
|
||||
|
||||
case OB_EMPTY:
|
||||
case OB_SURF:
|
||||
case OB_FONT:
|
||||
case OB_SPEAKER:
|
||||
case OB_LIGHTPROBE:
|
||||
case OB_LATTICE:
|
||||
|
||||
34
source/blender/io/usd/intern/usd_writer_text.cc
Normal file
34
source/blender/io/usd/intern/usd_writer_text.cc
Normal file
@@ -0,0 +1,34 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#include "usd_writer_text.hh"
|
||||
#include "usd_exporter_context.hh"
|
||||
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_object.hh"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
|
||||
namespace blender::io::usd {
|
||||
|
||||
USDTextWriter::USDTextWriter(const USDExporterContext &ctx) : USDGenericMeshWriter(ctx) {}
|
||||
|
||||
Mesh *USDTextWriter::get_export_mesh(Object *object_eval, bool &r_needsfree)
|
||||
{
|
||||
Mesh *mesh_eval = BKE_object_get_evaluated_mesh(object_eval);
|
||||
if (mesh_eval != nullptr) {
|
||||
/* Mesh_eval only exists when generative modifiers are in use. */
|
||||
r_needsfree = false;
|
||||
return mesh_eval;
|
||||
}
|
||||
r_needsfree = true;
|
||||
return BKE_mesh_new_from_object(usd_export_context_.depsgraph, object_eval, false, false, true);
|
||||
}
|
||||
|
||||
void USDTextWriter::free_export_mesh(Mesh *mesh)
|
||||
{
|
||||
BKE_id_free(nullptr, mesh);
|
||||
}
|
||||
|
||||
} // namespace blender::io::usd
|
||||
22
source/blender/io/usd/intern/usd_writer_text.hh
Normal file
22
source/blender/io/usd/intern/usd_writer_text.hh
Normal file
@@ -0,0 +1,22 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "usd_writer_mesh.hh"
|
||||
|
||||
struct Mesh;
|
||||
struct Object;
|
||||
|
||||
namespace blender::io::usd {
|
||||
|
||||
class USDTextWriter : public USDGenericMeshWriter {
|
||||
public:
|
||||
USDTextWriter(const USDExporterContext &ctx);
|
||||
|
||||
protected:
|
||||
Mesh *get_export_mesh(Object *object_eval, bool &r_needsfree) override;
|
||||
void free_export_mesh(Mesh *mesh) override;
|
||||
};
|
||||
|
||||
} // namespace blender::io::usd
|
||||
BIN
tests/files/render/mesh/storm_usd_renders/curve_modifier.png
(Stored with Git LFS)
BIN
tests/files/render/mesh/storm_usd_renders/curve_modifier.png
(Stored with Git LFS)
Binary file not shown.
BIN
tests/files/render/mesh/storm_usd_renders/texture_space_font.png
(Stored with Git LFS)
BIN
tests/files/render/mesh/storm_usd_renders/texture_space_font.png
(Stored with Git LFS)
Binary file not shown.
BIN
tests/files/render/mesh/storm_usd_renders/texture_space_font_auto.png
(Stored with Git LFS)
BIN
tests/files/render/mesh/storm_usd_renders/texture_space_font_auto.png
(Stored with Git LFS)
Binary file not shown.
BIN
tests/files/usd/usd_text_test.blend
(Stored with Git LFS)
Normal file
BIN
tests/files/usd/usd_text_test.blend
(Stored with Git LFS)
Normal file
Binary file not shown.
@@ -975,6 +975,66 @@ class USDExportTest(AbstractUSDTest):
|
||||
weight_samples = anim.GetBlendShapeWeightsAttr().GetTimeSamples()
|
||||
self.assertEqual(weight_samples, [1.0, 2.0, 3.0, 4.0, 5.0])
|
||||
|
||||
def test_export_text(self):
|
||||
"""Test various forms of Text/Font export."""
|
||||
|
||||
bpy.ops.wm.open_mainfile(filepath=str(self.testdir / "usd_text_test.blend"))
|
||||
|
||||
export_path = str(self.tempdir / "usd_text_test.usda")
|
||||
self.export_and_validate(filepath=export_path, export_animation=True, evaluation_mode="RENDER")
|
||||
|
||||
stats = UsdUtils.ComputeUsdStageStats(export_path)
|
||||
stage = Usd.Stage.Open(export_path)
|
||||
|
||||
# There should be 4 meshes in the output
|
||||
self.assertEqual(stats['primary']['primCountsByType']['Mesh'], 4)
|
||||
|
||||
bboxcache_frame1 = UsdGeom.BBoxCache(1.0, [UsdGeom.Tokens.default_])
|
||||
bboxcache_frame5 = UsdGeom.BBoxCache(5.0, [UsdGeom.Tokens.default_])
|
||||
|
||||
# Static, flat, text
|
||||
mesh = UsdGeom.Mesh(stage.GetPrimAtPath("/root/static/static"))
|
||||
bounds1 = bboxcache_frame1.ComputeWorldBound(mesh.GetPrim())
|
||||
bbox1 = bounds1.GetRange().GetMax() - bounds1.GetRange().GetMin()
|
||||
self.assertEqual(mesh.GetPointsAttr().GetTimeSamples(), [])
|
||||
self.assertEqual(mesh.GetExtentAttr().GetTimeSamples(), [])
|
||||
self.assertTrue(bbox1[0] > 0.0)
|
||||
self.assertTrue(bbox1[1] > 0.0)
|
||||
self.assertAlmostEqual(bbox1[2], 0.0, 5)
|
||||
|
||||
# Dynamic, flat, text
|
||||
mesh = UsdGeom.Mesh(stage.GetPrimAtPath("/root/dynamic/dynamic"))
|
||||
bounds1 = bboxcache_frame1.ComputeWorldBound(mesh.GetPrim())
|
||||
bounds5 = bboxcache_frame5.ComputeWorldBound(mesh.GetPrim())
|
||||
bbox1 = bounds1.GetRange().GetMax() - bounds1.GetRange().GetMin()
|
||||
bbox5 = bounds5.GetRange().GetMax() - bounds5.GetRange().GetMin()
|
||||
self.assertEqual(mesh.GetPointsAttr().GetTimeSamples(), [1.0, 2.0, 3.0, 4.0, 5.0])
|
||||
self.assertEqual(mesh.GetExtentAttr().GetTimeSamples(), [1.0, 2.0, 3.0, 4.0, 5.0])
|
||||
self.assertEqual(bbox1[2], 0.0)
|
||||
self.assertTrue(bbox1[0] < bbox5[0]) # Text grows on x-axis
|
||||
self.assertAlmostEqual(bbox1[1], bbox5[1], 5)
|
||||
self.assertAlmostEqual(bbox1[2], bbox5[2], 5)
|
||||
|
||||
# Static, extruded on Z, text
|
||||
mesh = UsdGeom.Mesh(stage.GetPrimAtPath("/root/extruded/extruded"))
|
||||
bounds1 = bboxcache_frame1.ComputeWorldBound(mesh.GetPrim())
|
||||
bbox1 = bounds1.GetRange().GetMax() - bounds1.GetRange().GetMin()
|
||||
self.assertEqual(mesh.GetPointsAttr().GetTimeSamples(), [])
|
||||
self.assertEqual(mesh.GetExtentAttr().GetTimeSamples(), [])
|
||||
self.assertTrue(bbox1[0] > 0.0)
|
||||
self.assertTrue(bbox1[1] > 0.0)
|
||||
self.assertAlmostEqual(bbox1[2], 0.1, 5)
|
||||
|
||||
# Static, uses depth, text
|
||||
mesh = UsdGeom.Mesh(stage.GetPrimAtPath("/root/has_depth/has_depth"))
|
||||
bounds1 = bboxcache_frame1.ComputeWorldBound(mesh.GetPrim())
|
||||
bbox1 = bounds1.GetRange().GetMax() - bounds1.GetRange().GetMin()
|
||||
self.assertEqual(mesh.GetPointsAttr().GetTimeSamples(), [])
|
||||
self.assertEqual(mesh.GetExtentAttr().GetTimeSamples(), [])
|
||||
self.assertTrue(bbox1[0] > 0.0)
|
||||
self.assertTrue(bbox1[1] > 0.0)
|
||||
self.assertAlmostEqual(bbox1[2], 0.1, 5)
|
||||
|
||||
def test_export_volumes(self):
|
||||
"""Test various combinations of volume export including with all supported volume modifiers."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user