This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/editors/object/object_warp.c
Sergey Sharybin f17fbf8065 Refactor: Rename Object->obmat to Object->object_to_world
Motivation is to disambiguate on the naming level what the matrix
actually means. It is very easy to understand the meaning backwards,
especially since in Python the name goes the opposite way (it is
called `world_matrix` in the Python API).

It is important to disambiguate the naming without making developers
to look into the comment in the header file (which is also not super
clear either). Additionally, more clear naming facilitates the unit
verification (or, in this case, space validation) when reading an
expression.

This patch calls the matrix `object_to_world` which makes it clear
from the local code what is it exactly going on. This is only done
on DNA level, and a lot of local variables still follow the old
naming.

A DNA rename is setup in a way that there is no change on the file
level, so there should be no regressions at all.

The possibility is to add `_matrix` or `_mat` suffix to the name
to make it explicit that it is a matrix. Although, not sure if it
really helps the readability, or is it something redundant.

Differential Revision: https://developer.blender.org/D16328
2022-11-01 10:48:18 +01:00

294 lines
8.1 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2013 Blender Foundation. All rights reserved. */
/** \file
* \ingroup edobj
*/
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
#include "BLI_math.h"
#include "BKE_context.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
#include "ED_transverts.h"
#include "object_intern.h"
static void object_warp_calc_view_matrix(float r_mat_view[4][4],
float r_center_view[3],
Object *obedit,
const float viewmat[4][4],
const float center[3],
const float offset_angle)
{
float mat_offset[4][4];
float viewmat_roll[4][4];
/* apply the rotation offset by rolling the view */
axis_angle_to_mat4_single(mat_offset, 'Z', offset_angle);
mul_m4_m4m4(viewmat_roll, mat_offset, viewmat);
/* apply the view and the object matrix */
mul_m4_m4m4(r_mat_view, viewmat_roll, obedit->object_to_world);
/* get the view-space cursor */
mul_v3_m4v3(r_center_view, viewmat_roll, center);
}
static void object_warp_transverts_minmax_x(TransVertStore *tvs,
const float mat_view[4][4],
const float center_view[3],
float *r_min,
float *r_max)
{
/* no need to apply translation and cursor offset for every vertex, delay this */
const float x_ofs = (mat_view[3][0] - center_view[0]);
float min = FLT_MAX, max = -FLT_MAX;
TransVert *tv = tvs->transverts;
for (int i = 0; i < tvs->transverts_tot; i++, tv++) {
float val;
/* Convert object-space to view-space. */
val = dot_m4_v3_row_x(mat_view, tv->loc);
min = min_ff(min, val);
max = max_ff(max, val);
}
*r_min = min + x_ofs;
*r_max = max + x_ofs;
}
static void object_warp_transverts(TransVertStore *tvs,
const float mat_view[4][4],
const float center_view[3],
const float angle_,
const float min,
const float max)
{
TransVert *tv;
const float angle = -angle_;
/* cache vars for tiny speedup */
#if 1
const float range = max - min;
const float range_inv = 1.0f / range;
const float min_ofs = min + (0.5f * range);
#endif
float dir_min[2], dir_max[2];
float imat_view[4][4];
invert_m4_m4(imat_view, mat_view);
/* calculate the direction vectors outside min/max range */
{
const float phi = angle * 0.5f;
dir_max[0] = cosf(phi);
dir_max[1] = sinf(phi);
dir_min[0] = -dir_max[0];
dir_min[1] = dir_max[1];
}
tv = tvs->transverts;
for (int i = 0; i < tvs->transverts_tot; i++, tv++) {
float co[3], co_add[2];
float val, phi;
/* Convert object-space to view-space. */
mul_v3_m4v3(co, mat_view, tv->loc);
sub_v2_v2(co, center_view);
val = co[0];
/* is overwritten later anyway */
// co[0] = 0.0f;
if (val < min) {
mul_v2_v2fl(co_add, dir_min, min - val);
val = min;
}
else if (val > max) {
mul_v2_v2fl(co_add, dir_max, val - max);
val = max;
}
else {
zero_v2(co_add);
}
/* map from x axis to (-0.5 - 0.5) */
#if 0
val = ((val - min) / (max - min)) - 0.5f;
#else
val = (val - min_ofs) * range_inv;
#endif
/* convert the x axis into a rotation */
phi = val * angle;
co[0] = -sinf(phi) * co[1];
co[1] = cosf(phi) * co[1];
add_v2_v2(co, co_add);
/* Convert view-space to object-space. */
add_v2_v2(co, center_view);
mul_v3_m4v3(tv->loc, imat_view, co);
}
}
static int object_warp_verts_exec(bContext *C, wmOperator *op)
{
const float warp_angle = RNA_float_get(op->ptr, "warp_angle");
const float offset_angle = RNA_float_get(op->ptr, "offset_angle");
TransVertStore tvs = {NULL};
Object *obedit = CTX_data_edit_object(C);
/* typically from 'rv3d' and 3d cursor */
float viewmat[4][4];
float center[3];
/* 'viewmat' relative vars */
float mat_view[4][4];
float center_view[3];
float min, max;
ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
if (tvs.transverts == NULL) {
return OPERATOR_CANCELLED;
}
/* Get view-matrix. */
{
PropertyRNA *prop_viewmat = RNA_struct_find_property(op->ptr, "viewmat");
if (RNA_property_is_set(op->ptr, prop_viewmat)) {
RNA_property_float_get_array(op->ptr, prop_viewmat, (float *)viewmat);
}
else {
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d) {
copy_m4_m4(viewmat, rv3d->viewmat);
}
else {
unit_m4(viewmat);
}
RNA_property_float_set_array(op->ptr, prop_viewmat, (float *)viewmat);
}
}
/* get center */
{
PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
if (RNA_property_is_set(op->ptr, prop_center)) {
RNA_property_float_get_array(op->ptr, prop_center, center);
}
else {
const Scene *scene = CTX_data_scene(C);
copy_v3_v3(center, scene->cursor.location);
RNA_property_float_set_array(op->ptr, prop_center, center);
}
}
object_warp_calc_view_matrix(mat_view, center_view, obedit, viewmat, center, offset_angle);
/* get minmax */
{
PropertyRNA *prop_min = RNA_struct_find_property(op->ptr, "min");
PropertyRNA *prop_max = RNA_struct_find_property(op->ptr, "max");
if (RNA_property_is_set(op->ptr, prop_min) || RNA_property_is_set(op->ptr, prop_max)) {
min = RNA_property_float_get(op->ptr, prop_min);
max = RNA_property_float_get(op->ptr, prop_max);
}
else {
/* handy to set the bounds of the mesh */
object_warp_transverts_minmax_x(&tvs, mat_view, center_view, &min, &max);
RNA_property_float_set(op->ptr, prop_min, min);
RNA_property_float_set(op->ptr, prop_max, max);
}
if (min > max) {
SWAP(float, min, max);
}
}
if (min != max) {
object_warp_transverts(&tvs, mat_view, center_view, warp_angle, min, max);
}
ED_transverts_update_obedit(&tvs, obedit);
ED_transverts_free(&tvs);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
return OPERATOR_FINISHED;
}
void TRANSFORM_OT_vertex_warp(struct wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Warp";
ot->description = "Warp vertices around the cursor";
ot->idname = "TRANSFORM_OT_vertex_warp";
/* api callbacks */
ot->exec = object_warp_verts_exec;
ot->poll = ED_transverts_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
prop = RNA_def_float(ot->srna,
"warp_angle",
DEG2RADF(360.0f),
-FLT_MAX,
FLT_MAX,
"Warp Angle",
"Amount to warp about the cursor",
DEG2RADF(-360.0f),
DEG2RADF(360.0f));
RNA_def_property_subtype(prop, PROP_ANGLE);
prop = RNA_def_float(ot->srna,
"offset_angle",
DEG2RADF(0.0f),
-FLT_MAX,
FLT_MAX,
"Offset Angle",
"Angle to use as the basis for warping",
DEG2RADF(-360.0f),
DEG2RADF(360.0f));
RNA_def_property_subtype(prop, PROP_ANGLE);
prop = RNA_def_float(ot->srna, "min", -1.0f, -FLT_MAX, FLT_MAX, "Min", "", -100.0, 100.0);
prop = RNA_def_float(ot->srna, "max", 1.0f, -FLT_MAX, FLT_MAX, "Max", "", -100.0, 100.0);
/* hidden props */
prop = RNA_def_float_matrix(
ot->srna, "viewmat", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_float_vector_xyz(
ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "", -FLT_MAX, FLT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}