Python: Expose crazyspace correction functionality via RNA

Allows to perform correction of coordinate delta/displacement in a
similar way of how sculpt mode handles sculpting on a deformed mesh.
An example of usecase of this is allowing riggers and sciprters to
improve corrective shapekey workflow.

The usage consists of pre-processing and access. For example:

  object.crazyspace_eval(depsgraph, scene)

  # When we have a difference between two vertices and want to convert
  # it to a space to be stored, say, in shapekey:
  delta_in_orig_space = rigged_ob.crazyspace_displacement_to_original(
      vertex_index=i, displacement=delta)

  # The reverse of above.
  delta_in_deformed_space = rigged_ob.crazyspace_displacement_to_deformed(
      vertex_index=i, displacement=delta)

  object.crazyspace_eval_clear()

Fuller explanation with actual usecases and studio examples are written in
the comment:

  https://developer.blender.org/D13892#368898

Differential Revision: https://developer.blender.org/D13892
This commit is contained in:
Sergey Sharybin 2022-01-05 09:53:48 +01:00
parent 31296f6f9d
commit 196da819ba
6 changed files with 205 additions and 0 deletions

View File

@ -26,10 +26,12 @@
#ifdef __cplusplus
extern "C" {
#endif
struct BMEditMesh;
struct Depsgraph;
struct Mesh;
struct Object;
struct ReportList;
struct Scene;
/* crazyspace.c */
@ -69,6 +71,31 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph,
float (**deformmats)[3][3],
float (**deformcos)[3]);
/* -------------------------------------------------------------------- */
/** \name Crazyspace API
* \{ */
void BKE_crazyspace_api_eval(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *object,
struct ReportList *reports);
void BKE_crazyspace_api_displacement_to_deformed(struct Object *object,
struct ReportList *reports,
int vertex_index,
float displacement[3],
float r_displacement_deformed[3]);
void BKE_crazyspace_api_displacement_to_original(struct Object *object,
struct ReportList *reports,
int vertex_index,
float displacement_deformed[3],
float r_displacement[3]);
void BKE_crazyspace_api_eval_clear(struct Object *object);
/** \} */
#ifdef __cplusplus
}
#endif

View File

@ -41,6 +41,7 @@
#include "BKE_mesh_wrapper.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_report.h"
#include "DEG_depsgraph_query.h"
@ -516,3 +517,85 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph,
}
}
}
/* -------------------------------------------------------------------- */
/** \name Crazyspace API
* \{ */
void BKE_crazyspace_api_eval(Depsgraph *depsgraph,
Scene *scene,
Object *object,
struct ReportList *reports)
{
if (object->runtime.crazyspace_deform_imats != NULL ||
object->runtime.crazyspace_deform_cos != NULL) {
return;
}
if (object->type != OB_MESH) {
BKE_report(reports,
RPT_ERROR,
"Crazyspace transformation is only available for Mesh type of objects");
return;
}
const Mesh *mesh = (const Mesh *)object->data;
object->runtime.crazyspace_num_verts = mesh->totvert;
BKE_crazyspace_build_sculpt(depsgraph,
scene,
object,
&object->runtime.crazyspace_deform_imats,
&object->runtime.crazyspace_deform_cos);
}
void BKE_crazyspace_api_displacement_to_deformed(struct Object *object,
struct ReportList *reports,
int vertex_index,
float displacement[3],
float r_displacement_deformed[3])
{
if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_num_verts) {
BKE_reportf(reports,
RPT_ERROR,
"Invalid vertex index %d (expected to be within 0 to %d range)",
vertex_index,
object->runtime.crazyspace_num_verts);
return;
}
mul_v3_m3v3(r_displacement_deformed,
object->runtime.crazyspace_deform_imats[vertex_index],
displacement);
}
void BKE_crazyspace_api_displacement_to_original(struct Object *object,
struct ReportList *reports,
int vertex_index,
float displacement_deformed[3],
float r_displacement[3])
{
if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_num_verts) {
BKE_reportf(reports,
RPT_ERROR,
"Invalid vertex index %d (expected to be within 0 to %d range))",
vertex_index,
object->runtime.crazyspace_num_verts);
return;
}
float mat[3][3];
if (!invert_m3_m3(mat, object->runtime.crazyspace_deform_imats[vertex_index])) {
copy_v3_v3(r_displacement, displacement_deformed);
return;
}
mul_v3_m3v3(r_displacement, mat, displacement_deformed);
}
void BKE_crazyspace_api_eval_clear(Object *object)
{
MEM_SAFE_FREE(object->runtime.crazyspace_deform_imats);
MEM_SAFE_FREE(object->runtime.crazyspace_deform_cos);
}
/** \} */

View File

@ -87,6 +87,7 @@
#include "BKE_camera.h"
#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_crazyspace.h"
#include "BKE_curve.h"
#include "BKE_deform.h"
#include "BKE_displist.h"
@ -1881,6 +1882,8 @@ void BKE_object_free_derived_caches(Object *ob)
BKE_object_to_curve_clear(ob);
BKE_object_free_curve_cache(ob);
BKE_crazyspace_api_eval_clear(ob);
/* Clear grease pencil data. */
if (ob->runtime.gpd_eval != nullptr) {
BKE_gpencil_eval_delete(ob->runtime.gpd_eval);
@ -5219,6 +5222,9 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag))
runtime->object_as_temp_mesh = nullptr;
runtime->object_as_temp_curve = nullptr;
runtime->geometry_set_eval = nullptr;
runtime->crazyspace_deform_imats = nullptr;
runtime->crazyspace_deform_cos = nullptr;
}
void BKE_object_runtime_free_data(Object *object)

View File

@ -43,13 +43,16 @@
#include "DNA_object_types.h"
#include "BKE_context.h"
#include "BKE_crazyspace.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_query.h"
#include "BLI_sys_types.h" /* for intptr_t support */

View File

@ -216,6 +216,12 @@ typedef struct Object_Runtime {
unsigned short local_collections_bits;
short _pad2[3];
float (*crazyspace_deform_imats)[3][3];
float (*crazyspace_deform_cos)[3];
int crazyspace_num_verts;
int _pad3[3];
} Object_Runtime;
typedef struct ObjectLineArt {

View File

@ -68,6 +68,7 @@ static const EnumPropertyItem space_items[] = {
# include "BKE_bvhutils.h"
# include "BKE_constraint.h"
# include "BKE_context.h"
# include "BKE_crazyspace.h"
# include "BKE_customdata.h"
# include "BKE_global.h"
# include "BKE_layer.h"
@ -379,6 +380,39 @@ static void rna_Object_camera_fit_coords(
depsgraph, (const float(*)[3])cos, num_cos / 3, ob, co_ret, scale_ret);
}
static void rna_Object_crazyspace_eval(Object *object,
ReportList *reports,
Depsgraph *depsgraph,
Scene *scene)
{
BKE_crazyspace_api_eval(depsgraph, scene, object, reports);
}
static void rna_Object_crazyspace_displacement_to_deformed(Object *object,
ReportList *reports,
const int vertex_index,
float displacement[3],
float r_displacement_deformed[3])
{
BKE_crazyspace_api_displacement_to_deformed(
object, reports, vertex_index, displacement, r_displacement_deformed);
}
static void rna_Object_crazyspace_displacement_to_original(Object *object,
ReportList *reports,
const int vertex_index,
float displacement_deformed[3],
float r_displacement[3])
{
BKE_crazyspace_api_displacement_to_original(
object, reports, vertex_index, displacement_deformed, r_displacement);
}
static void rna_Object_crazyspace_eval_clear(Object *object)
{
BKE_crazyspace_api_eval_clear(object);
}
/* copied from Mesh_getFromObject and adapted to RNA interface */
static Mesh *rna_Object_to_mesh(Object *object,
ReportList *reports,
@ -978,6 +1012,52 @@ void RNA_api_object(StructRNA *srna)
parm, "", "The ortho scale to aim to be able to see all given points (if relevant)");
RNA_def_parameter_flags(parm, 0, PARM_OUTPUT);
/* Crazyspace access. */
func = RNA_def_function(srna, "crazyspace_eval", "rna_Object_crazyspace_eval");
RNA_def_function_ui_description(
func,
"Compute orientation mapping between vertices of an original object and object with shape "
"keys and deforming modifiers applied."
"The evaluation is to be freed with the crazyspace_eval_free function");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(
func, "depsgraph", "Depsgraph", "Dependency Graph", "Evaluated dependency graph");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(func, "scene", "Scene", "Scene", "Scene of the object");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
func = RNA_def_function(srna,
"crazyspace_displacement_to_deformed",
"rna_Object_crazyspace_displacement_to_deformed");
RNA_def_function_ui_description(
func, "Convert displacement vector from non-deformed object space to deformed object space");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_property(func, "vertex_index", PROP_INT, PROP_NONE);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_property(func, "displacement", PROP_FLOAT, PROP_XYZ);
RNA_def_property_array(parm, 3);
parm = RNA_def_property(func, "displacement_deformed", PROP_FLOAT, PROP_XYZ);
RNA_def_property_array(parm, 3);
RNA_def_function_output(func, parm);
func = RNA_def_function(srna,
"crazyspace_displacement_to_original",
"rna_Object_crazyspace_displacement_to_original");
RNA_def_function_ui_description(
func, "Convert displacement vector from deformed object space to non-deformed object space");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_property(func, "vertex_index", PROP_INT, PROP_NONE);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_property(func, "displacement", PROP_FLOAT, PROP_XYZ);
RNA_def_property_array(parm, 3);
parm = RNA_def_property(func, "displacement_original", PROP_FLOAT, PROP_XYZ);
RNA_def_property_array(parm, 3);
RNA_def_function_output(func, parm);
RNA_def_function(srna, "crazyspace_eval_clear", "rna_Object_crazyspace_eval_clear");
RNA_def_function_ui_description(func, "Free evaluated state of crazyspace");
/* mesh */
func = RNA_def_function(srna, "to_mesh", "rna_Object_to_mesh");
RNA_def_function_ui_description(