forked from blender/blender
WIP: uv-simple-select #1
@ -382,6 +382,7 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
|
||||
const bool import_materials = RNA_boolean_get(op->ptr, "import_materials");
|
||||
const bool import_meshes = RNA_boolean_get(op->ptr, "import_meshes");
|
||||
const bool import_volumes = RNA_boolean_get(op->ptr, "import_volumes");
|
||||
const bool import_shapes = RNA_boolean_get(op->ptr, "import_shapes");
|
||||
|
||||
const bool import_subdiv = RNA_boolean_get(op->ptr, "import_subdiv");
|
||||
|
||||
@ -443,6 +444,7 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
|
||||
.import_materials = import_materials,
|
||||
.import_meshes = import_meshes,
|
||||
.import_volumes = import_volumes,
|
||||
.import_shapes = import_shapes,
|
||||
.import_subdiv = import_subdiv,
|
||||
.import_instance_proxies = import_instance_proxies,
|
||||
.create_collection = create_collection,
|
||||
@ -488,6 +490,7 @@ static void wm_usd_import_draw(bContext *UNUSED(C), wmOperator *op)
|
||||
uiItemR(col, ptr, "import_materials", 0, NULL, ICON_NONE);
|
||||
uiItemR(col, ptr, "import_meshes", 0, NULL, ICON_NONE);
|
||||
uiItemR(col, ptr, "import_volumes", 0, NULL, ICON_NONE);
|
||||
uiItemR(col, ptr, "import_shapes", 0, NULL, ICON_NONE);
|
||||
uiItemR(box, ptr, "prim_path_mask", 0, NULL, ICON_NONE);
|
||||
uiItemR(box, ptr, "scale", 0, NULL, ICON_NONE);
|
||||
|
||||
@ -577,6 +580,7 @@ void WM_OT_usd_import(struct wmOperatorType *ot)
|
||||
RNA_def_boolean(ot->srna, "import_materials", true, "Materials", "");
|
||||
RNA_def_boolean(ot->srna, "import_meshes", true, "Meshes", "");
|
||||
RNA_def_boolean(ot->srna, "import_volumes", true, "Volumes", "");
|
||||
RNA_def_boolean(ot->srna, "import_shapes", true, "Shapes", "");
|
||||
|
||||
RNA_def_boolean(ot->srna,
|
||||
"import_subdiv",
|
||||
|
@ -83,6 +83,7 @@ set(SRC
|
||||
intern/usd_reader_mesh.cc
|
||||
intern/usd_reader_nurbs.cc
|
||||
intern/usd_reader_prim.cc
|
||||
intern/usd_reader_shape.cc
|
||||
intern/usd_reader_stage.cc
|
||||
intern/usd_reader_volume.cc
|
||||
intern/usd_reader_xform.cc
|
||||
@ -111,6 +112,7 @@ set(SRC
|
||||
intern/usd_reader_mesh.h
|
||||
intern/usd_reader_nurbs.h
|
||||
intern/usd_reader_prim.h
|
||||
intern/usd_reader_shape.h
|
||||
intern/usd_reader_stage.h
|
||||
intern/usd_reader_volume.h
|
||||
intern/usd_reader_xform.h
|
||||
|
245
source/blender/io/usd/intern/usd_reader_shape.cc
Normal file
245
source/blender/io/usd/intern/usd_reader_shape.cc
Normal file
@ -0,0 +1,245 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2023 Nvidia. All rights reserved. */
|
||||
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
#include "DNA_cachefile_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
#include "usd_reader_shape.h"
|
||||
|
||||
#include <pxr/usd/usdGeom/capsule.h>
|
||||
#include <pxr/usd/usdGeom/cone.h>
|
||||
#include <pxr/usd/usdGeom/cube.h>
|
||||
#include <pxr/usd/usdGeom/cylinder.h>
|
||||
#include <pxr/usd/usdGeom/sphere.h>
|
||||
#include <pxr/usdImaging/usdImaging/capsuleAdapter.h>
|
||||
#include <pxr/usdImaging/usdImaging/coneAdapter.h>
|
||||
#include <pxr/usdImaging/usdImaging/cubeAdapter.h>
|
||||
#include <pxr/usdImaging/usdImaging/cylinderAdapter.h>
|
||||
#include <pxr/usdImaging/usdImaging/sphereAdapter.h>
|
||||
|
||||
namespace blender::io::usd {
|
||||
|
||||
USDShapeReader::USDShapeReader(const pxr::UsdPrim &prim,
|
||||
const USDImportParams &import_params,
|
||||
const ImportSettings &settings)
|
||||
: USDGeomReader(prim, import_params, settings)
|
||||
{
|
||||
}
|
||||
|
||||
void USDShapeReader::create_object(Main *bmain, double /*motionSampleTime*/)
|
||||
{
|
||||
Mesh *mesh = BKE_mesh_add(bmain, name_.c_str());
|
||||
object_ = BKE_object_add_only_object(bmain, OB_MESH, name_.c_str());
|
||||
object_->data = mesh;
|
||||
}
|
||||
|
||||
void USDShapeReader::read_object_data(Main *bmain, double motionSampleTime)
|
||||
{
|
||||
Mesh *mesh = (Mesh *)object_->data;
|
||||
Mesh *read_mesh = this->read_mesh(
|
||||
mesh, motionSampleTime, import_params_.mesh_read_flag, nullptr);
|
||||
|
||||
if (read_mesh != mesh) {
|
||||
BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_);
|
||||
if (is_time_varying()) {
|
||||
USDGeomReader::add_cache_modifier();
|
||||
}
|
||||
}
|
||||
|
||||
USDXformReader::read_object_data(bmain, motionSampleTime);
|
||||
}
|
||||
|
||||
template<typename Adapter>
|
||||
void USDShapeReader::read_values(const double motionSampleTime,
|
||||
pxr::VtVec3fArray &positions,
|
||||
pxr::VtIntArray &face_indices,
|
||||
pxr::VtIntArray &face_counts) const
|
||||
{
|
||||
Adapter adapter;
|
||||
pxr::VtValue points_val = adapter.GetPoints(prim_, motionSampleTime);
|
||||
|
||||
if (points_val.IsHolding<pxr::VtVec3fArray>()) {
|
||||
positions = points_val.Get<pxr::VtVec3fArray>();
|
||||
}
|
||||
|
||||
pxr::VtValue topology_val = adapter.GetTopology(prim_, pxr::SdfPath(), motionSampleTime);
|
||||
|
||||
if (topology_val.IsHolding<pxr::HdMeshTopology>()) {
|
||||
const pxr::HdMeshTopology &topology = topology_val.Get<pxr::HdMeshTopology>();
|
||||
face_counts = topology.GetFaceVertexCounts();
|
||||
face_indices = topology.GetFaceVertexIndices();
|
||||
}
|
||||
}
|
||||
|
||||
bool USDShapeReader::read_mesh_values(double motionSampleTime,
|
||||
pxr::VtVec3fArray &positions,
|
||||
pxr::VtIntArray &face_indices,
|
||||
pxr::VtIntArray &face_counts) const
|
||||
{
|
||||
if (prim_.IsA<pxr::UsdGeomCapsule>()) {
|
||||
read_values<pxr::UsdImagingCapsuleAdapter>(
|
||||
motionSampleTime, positions, face_indices, face_counts);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (prim_.IsA<pxr::UsdGeomCylinder>()) {
|
||||
read_values<pxr::UsdImagingCylinderAdapter>(
|
||||
motionSampleTime, positions, face_indices, face_counts);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (prim_.IsA<pxr::UsdGeomCone>()) {
|
||||
read_values<pxr::UsdImagingConeAdapter>(
|
||||
motionSampleTime, positions, face_indices, face_counts);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (prim_.IsA<pxr::UsdGeomCube>()) {
|
||||
read_values<pxr::UsdImagingCubeAdapter>(
|
||||
motionSampleTime, positions, face_indices, face_counts);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (prim_.IsA<pxr::UsdGeomSphere>()) {
|
||||
read_values<pxr::UsdImagingSphereAdapter>(
|
||||
motionSampleTime, positions, face_indices, face_counts);
|
||||
return true;
|
||||
}
|
||||
|
||||
WM_reportf(RPT_ERROR,
|
||||
"Unhandled Gprim type: %s (%s)",
|
||||
prim_.GetTypeName().GetText(),
|
||||
prim_.GetPath().GetText());
|
||||
return false;
|
||||
}
|
||||
|
||||
Mesh *USDShapeReader::read_mesh(struct Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
int /*read_flag*/,
|
||||
const char ** /*err_str*/)
|
||||
{
|
||||
pxr::VtIntArray face_indices;
|
||||
pxr::VtIntArray face_counts;
|
||||
|
||||
if (!prim_) {
|
||||
return existing_mesh;
|
||||
}
|
||||
|
||||
/* Should have a good set of data by this point-- copy over. */
|
||||
Mesh *active_mesh = mesh_from_prim(existing_mesh, motionSampleTime, face_indices, face_counts);
|
||||
if (active_mesh == existing_mesh) {
|
||||
return existing_mesh;
|
||||
}
|
||||
|
||||
MutableSpan<MPoly> polys = active_mesh->polys_for_write();
|
||||
MutableSpan<MLoop> loops = active_mesh->loops_for_write();
|
||||
|
||||
const char should_smooth = prim_.IsA<pxr::UsdGeomCube>() ? 0 : ME_SMOOTH;
|
||||
|
||||
int loop_index = 0;
|
||||
for (int i = 0; i < face_counts.size(); i++) {
|
||||
const int face_size = face_counts[i];
|
||||
|
||||
MPoly &poly = polys[i];
|
||||
poly.loopstart = loop_index;
|
||||
poly.totloop = face_size;
|
||||
|
||||
/* Don't smooth-shade cubes; we're not worrying about sharpness for Gprims. */
|
||||
poly.flag |= should_smooth;
|
||||
|
||||
for (int f = 0; f < face_size; ++f, ++loop_index) {
|
||||
loops[loop_index].v = face_indices[loop_index];
|
||||
}
|
||||
}
|
||||
|
||||
BKE_mesh_calc_edges(active_mesh, false, false);
|
||||
return active_mesh;
|
||||
}
|
||||
|
||||
Mesh *USDShapeReader::mesh_from_prim(Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
pxr::VtIntArray &face_indices,
|
||||
pxr::VtIntArray &face_counts) const
|
||||
{
|
||||
pxr::VtVec3fArray positions;
|
||||
|
||||
if (!read_mesh_values(motionSampleTime, positions, face_indices, face_counts)) {
|
||||
return existing_mesh;
|
||||
}
|
||||
|
||||
const bool poly_counts_match = existing_mesh ? face_counts.size() == existing_mesh->totpoly :
|
||||
false;
|
||||
const bool position_counts_match = existing_mesh ? positions.size() == existing_mesh->totvert :
|
||||
false;
|
||||
|
||||
Mesh *active_mesh = nullptr;
|
||||
if (!position_counts_match || !poly_counts_match) {
|
||||
active_mesh = BKE_mesh_new_nomain_from_template(
|
||||
existing_mesh, positions.size(), 0, 0, face_indices.size(), face_counts.size());
|
||||
}
|
||||
else {
|
||||
active_mesh = existing_mesh;
|
||||
}
|
||||
|
||||
MutableSpan<float3> vert_positions = active_mesh->vert_positions_for_write();
|
||||
|
||||
for (int i = 0; i < positions.size(); i++) {
|
||||
vert_positions[i][0] = positions[i][0];
|
||||
vert_positions[i][1] = positions[i][1];
|
||||
vert_positions[i][2] = positions[i][2];
|
||||
}
|
||||
|
||||
return active_mesh;
|
||||
}
|
||||
|
||||
bool USDShapeReader::is_time_varying()
|
||||
{
|
||||
if (prim_.IsA<pxr::UsdGeomCapsule>()) {
|
||||
pxr::UsdGeomCapsule geom(prim_);
|
||||
return (geom.GetAxisAttr().ValueMightBeTimeVarying() ||
|
||||
geom.GetHeightAttr().ValueMightBeTimeVarying() ||
|
||||
geom.GetRadiusAttr().ValueMightBeTimeVarying());
|
||||
}
|
||||
|
||||
if (prim_.IsA<pxr::UsdGeomCylinder>()) {
|
||||
pxr::UsdGeomCylinder geom(prim_);
|
||||
return (geom.GetAxisAttr().ValueMightBeTimeVarying() ||
|
||||
geom.GetHeightAttr().ValueMightBeTimeVarying() ||
|
||||
geom.GetRadiusAttr().ValueMightBeTimeVarying());
|
||||
}
|
||||
|
||||
if (prim_.IsA<pxr::UsdGeomCone>()) {
|
||||
pxr::UsdGeomCone geom(prim_);
|
||||
return (geom.GetAxisAttr().ValueMightBeTimeVarying() ||
|
||||
geom.GetHeightAttr().ValueMightBeTimeVarying() ||
|
||||
geom.GetRadiusAttr().ValueMightBeTimeVarying());
|
||||
}
|
||||
|
||||
if (prim_.IsA<pxr::UsdGeomCube>()) {
|
||||
pxr::UsdGeomCube geom(prim_);
|
||||
return geom.GetSizeAttr().ValueMightBeTimeVarying();
|
||||
}
|
||||
|
||||
if (prim_.IsA<pxr::UsdGeomSphere>()) {
|
||||
pxr::UsdGeomSphere geom(prim_);
|
||||
return geom.GetRadiusAttr().ValueMightBeTimeVarying();
|
||||
}
|
||||
|
||||
WM_reportf(RPT_ERROR,
|
||||
"Unhandled Gprim type: %s (%s)",
|
||||
prim_.GetTypeName().GetText(),
|
||||
prim_.GetPath().GetText());
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace blender::io::usd
|
62
source/blender/io/usd/intern/usd_reader_shape.h
Normal file
62
source/blender/io/usd/intern/usd_reader_shape.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2023 Nvidia. All rights reserved. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "usd.h"
|
||||
#include "usd_reader_geom.h"
|
||||
#include "usd_reader_xform.h"
|
||||
#include <pxr/usd/usdGeom/gprim.h>
|
||||
|
||||
struct Mesh;
|
||||
|
||||
namespace blender::io::usd {
|
||||
|
||||
/*
|
||||
* Read USDGeom primitive shapes as Blender Meshes. This class uses the same adapter functions
|
||||
* as the GL viewport to generate geometry for each of the supported types.
|
||||
*/
|
||||
class USDShapeReader : public USDGeomReader {
|
||||
private:
|
||||
/* Template required to read mesh information out of Shape prims,
|
||||
* as each prim type has a separate subclass. */
|
||||
template<typename Adapter>
|
||||
void read_values(double motionSampleTime,
|
||||
pxr::VtVec3fArray &positions,
|
||||
pxr::VtIntArray &face_indices,
|
||||
pxr::VtIntArray &face_counts) const;
|
||||
|
||||
/* Wrapper for the templated method read_values, calling the correct template
|
||||
* instantiation based on the introspected prim type. */
|
||||
bool read_mesh_values(double motionSampleTime,
|
||||
pxr::VtVec3fArray &positions,
|
||||
pxr::VtIntArray &face_indices,
|
||||
pxr::VtIntArray &face_counts) const;
|
||||
|
||||
/* Read the pxr:UsdGeomMesh values and convert them to a Blender Mesh,
|
||||
* also returning face_indices and counts for further loop processing. */
|
||||
Mesh *mesh_from_prim(Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
pxr::VtIntArray &face_indices,
|
||||
pxr::VtIntArray &face_counts) const;
|
||||
|
||||
public:
|
||||
USDShapeReader(const pxr::UsdPrim &prim,
|
||||
const USDImportParams &import_params,
|
||||
const ImportSettings &settings);
|
||||
|
||||
void create_object(Main *bmain, double /*motionSampleTime*/) override;
|
||||
void read_object_data(Main *bmain, double motionSampleTime) override;
|
||||
Mesh *read_mesh(Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
int /*read_flag*/,
|
||||
const char ** /*err_str*/) override;
|
||||
bool is_time_varying();
|
||||
|
||||
virtual bool topology_changed(const Mesh * /*existing_mesh*/, double /*motionSampleTime*/)
|
||||
{
|
||||
return false;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace blender::io::usd
|
@ -9,6 +9,7 @@
|
||||
#include "usd_reader_mesh.h"
|
||||
#include "usd_reader_nurbs.h"
|
||||
#include "usd_reader_prim.h"
|
||||
#include "usd_reader_shape.h"
|
||||
#include "usd_reader_volume.h"
|
||||
#include "usd_reader_xform.h"
|
||||
|
||||
@ -16,9 +17,14 @@
|
||||
#include <pxr/usd/usd/primRange.h>
|
||||
#include <pxr/usd/usdGeom/camera.h>
|
||||
#include <pxr/usd/usdGeom/curves.h>
|
||||
#include <pxr/usd/usdGeom/capsule.h>
|
||||
#include <pxr/usd/usdGeom/cone.h>
|
||||
#include <pxr/usd/usdGeom/cube.h>
|
||||
#include <pxr/usd/usdGeom/cylinder.h>
|
||||
#include <pxr/usd/usdGeom/mesh.h>
|
||||
#include <pxr/usd/usdGeom/nurbsCurves.h>
|
||||
#include <pxr/usd/usdGeom/scope.h>
|
||||
#include <pxr/usd/usdGeom/sphere.h>
|
||||
#include <pxr/usd/usdGeom/xform.h>
|
||||
#include <pxr/usd/usdShade/material.h>
|
||||
|
||||
@ -57,8 +63,18 @@ bool USDStageReader::valid() const
|
||||
return stage_;
|
||||
}
|
||||
|
||||
bool USDStageReader::is_primitive_prim(const pxr::UsdPrim &prim) const
|
||||
{
|
||||
return (prim.IsA<pxr::UsdGeomCapsule>() || prim.IsA<pxr::UsdGeomCylinder>() ||
|
||||
prim.IsA<pxr::UsdGeomCone>() || prim.IsA<pxr::UsdGeomCube>() ||
|
||||
prim.IsA<pxr::UsdGeomSphere>());
|
||||
}
|
||||
|
||||
USDPrimReader *USDStageReader::create_reader_if_allowed(const pxr::UsdPrim &prim)
|
||||
{
|
||||
if (params_.import_shapes && is_primitive_prim(prim)) {
|
||||
return new USDShapeReader(prim, params_, settings_);
|
||||
}
|
||||
if (params_.import_cameras && prim.IsA<pxr::UsdGeomCamera>()) {
|
||||
return new USDCameraReader(prim, params_, settings_);
|
||||
}
|
||||
@ -91,6 +107,9 @@ USDPrimReader *USDStageReader::create_reader_if_allowed(const pxr::UsdPrim &prim
|
||||
|
||||
USDPrimReader *USDStageReader::create_reader(const pxr::UsdPrim &prim)
|
||||
{
|
||||
if (is_primitive_prim(prim)) {
|
||||
return new USDShapeReader(prim, params_, settings_);
|
||||
}
|
||||
if (prim.IsA<pxr::UsdGeomCamera>()) {
|
||||
return new USDCameraReader(prim, params_, settings_);
|
||||
}
|
||||
|
@ -100,6 +100,12 @@ class USDStageReader {
|
||||
* toggled off.
|
||||
*/
|
||||
bool include_by_purpose(const pxr::UsdGeomImageable &imageable) const;
|
||||
|
||||
/*
|
||||
* Returns true if the specified UsdPrim is a UsdGeom primitive,
|
||||
* procedural shape, such as UsdGeomCube.
|
||||
*/
|
||||
bool is_primitive_prim(const pxr::UsdPrim &prim) const;
|
||||
};
|
||||
|
||||
}; // namespace blender::io::usd
|
||||
|
@ -66,6 +66,7 @@ struct USDImportParams {
|
||||
bool import_materials;
|
||||
bool import_meshes;
|
||||
bool import_volumes;
|
||||
bool import_shapes;
|
||||
char prim_path_mask[1024];
|
||||
bool import_subdiv;
|
||||
bool import_instance_proxies;
|
||||
|
Loading…
Reference in New Issue
Block a user