Cleanup: Alembic, moved axis conversion functions into their own files

The long-term goal is to move code out of `abc_util.{h,cc}` into either
files with better, more concrete names, or simply into the one file
where they are used.

No functional changes.
This commit is contained in:
Sybren A. Stüvel 2020-05-08 09:52:22 +02:00
parent 298356a9c0
commit 163a48f203
15 changed files with 278 additions and 212 deletions

View File

@ -41,6 +41,7 @@ set(INC_SYS
)
set(SRC
intern/abc_axis_conversion.cc
intern/abc_customdata.cc
intern/abc_exporter.cc
intern/abc_reader_archive.cc
@ -65,6 +66,7 @@ set(SRC
intern/alembic_capi.cc
ABC_alembic.h
intern/abc_axis_conversion.h
intern/abc_customdata.h
intern/abc_exporter.h
intern/abc_reader_archive.h

View File

@ -0,0 +1,166 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/** \file
* \ingroup Alembic
*/
#include "abc_axis_conversion.h"
extern "C" {
#include "BLI_assert.h"
#include "DNA_object_types.h"
#include "BLI_math_geom.h"
}
void create_swapped_rotation_matrix(float rot_x_mat[3][3],
float rot_y_mat[3][3],
float rot_z_mat[3][3],
const float euler[3],
AbcAxisSwapMode mode)
{
const float rx = euler[0];
float ry;
float rz;
/* Apply transformation */
switch (mode) {
case ABC_ZUP_FROM_YUP:
ry = -euler[2];
rz = euler[1];
break;
case ABC_YUP_FROM_ZUP:
ry = euler[2];
rz = -euler[1];
break;
default:
ry = 0.0f;
rz = 0.0f;
BLI_assert(false);
break;
}
unit_m3(rot_x_mat);
unit_m3(rot_y_mat);
unit_m3(rot_z_mat);
rot_x_mat[1][1] = cos(rx);
rot_x_mat[2][1] = -sin(rx);
rot_x_mat[1][2] = sin(rx);
rot_x_mat[2][2] = cos(rx);
rot_y_mat[2][2] = cos(ry);
rot_y_mat[0][2] = -sin(ry);
rot_y_mat[2][0] = sin(ry);
rot_y_mat[0][0] = cos(ry);
rot_z_mat[0][0] = cos(rz);
rot_z_mat[1][0] = -sin(rz);
rot_z_mat[0][1] = sin(rz);
rot_z_mat[1][1] = cos(rz);
}
/* Convert matrix from Z=up to Y=up or vice versa.
* Use yup_mat = zup_mat for in-place conversion. */
void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode)
{
float dst_rot[3][3], src_rot[3][3], dst_scale_mat[4][4];
float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3];
float src_trans[3], dst_scale[3], src_scale[3], euler[3];
zero_v3(src_trans);
zero_v3(dst_scale);
zero_v3(src_scale);
zero_v3(euler);
unit_m3(src_rot);
unit_m3(dst_rot);
unit_m4(dst_scale_mat);
/* TODO(Sybren): This code assumes there is no sheer component and no
* homogeneous scaling component, which is not always true when writing
* non-hierarchical (e.g. flat) objects (e.g. when parent has non-uniform
* scale and the child rotates). This is currently not taken into account
* when axis-swapping. */
/* Extract translation, rotation, and scale form matrix. */
mat4_to_loc_rot_size(src_trans, src_rot, src_scale, src_mat);
/* Get euler angles from rotation matrix. */
mat3_to_eulO(euler, ROT_MODE_XZY, src_rot);
/* Create X, Y, Z rotation matrices from euler angles. */
create_swapped_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, mode);
/* Concatenate rotation matrices. */
mul_m3_m3m3(dst_rot, dst_rot, rot_z_mat);
mul_m3_m3m3(dst_rot, dst_rot, rot_y_mat);
mul_m3_m3m3(dst_rot, dst_rot, rot_x_mat);
mat3_to_eulO(euler, ROT_MODE_XZY, dst_rot);
/* Start construction of dst_mat from rotation matrix */
unit_m4(dst_mat);
copy_m4_m3(dst_mat, dst_rot);
/* Apply translation */
switch (mode) {
case ABC_ZUP_FROM_YUP:
copy_zup_from_yup(dst_mat[3], src_trans);
break;
case ABC_YUP_FROM_ZUP:
copy_yup_from_zup(dst_mat[3], src_trans);
break;
default:
BLI_assert(false);
}
/* Apply scale matrix. Swaps y and z, but does not
* negate like translation does. */
dst_scale[0] = src_scale[0];
dst_scale[1] = src_scale[2];
dst_scale[2] = src_scale[1];
size_to_mat4(dst_scale_mat, dst_scale);
mul_m4_m4m4(dst_mat, dst_mat, dst_scale_mat);
}
/* Recompute transform matrix of object in new coordinate system
* (from Z-Up to Y-Up). */
void create_transform_matrix(Object *obj,
float r_yup_mat[4][4],
AbcMatrixMode mode,
Object *proxy_from)
{
float zup_mat[4][4];
/* get local or world matrix. */
if (mode == ABC_MATRIX_LOCAL && obj->parent) {
/* Note that this produces another matrix than the local matrix, due to
* constraints and modifiers as well as the obj->parentinv matrix. */
invert_m4_m4(obj->parent->imat, obj->parent->obmat);
mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat);
}
else {
copy_m4_m4(zup_mat, obj->obmat);
}
if (proxy_from) {
mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat);
}
copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP);
}

View File

@ -0,0 +1,99 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2016 Kévin Dietrich & Blender Foundation.
* All rights reserved.
*/
#pragma once
/** \file
* \ingroup Alembic
*/
struct Object;
#ifdef _MSC_VER
# define ABC_INLINE static __forceinline
#else
# define ABC_INLINE static inline
#endif
/* TODO(kevin): for now keeping these transformations hardcoded to make sure
* everything works properly, and also because Alembic is almost exclusively
* used in Y-up software, but eventually they'll be set by the user in the UI
* like other importers/exporters do, to support other axis. */
/* Copy from Y-up to Z-up. */
ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3])
{
const float old_yup1 = yup[1]; /* in case zup == yup */
zup[0] = yup[0];
zup[1] = -yup[2];
zup[2] = old_yup1;
}
ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3])
{
const short old_yup1 = yup[1]; /* in case zup == yup */
zup[0] = yup[0];
zup[1] = -yup[2];
zup[2] = old_yup1;
}
/* Copy from Z-up to Y-up. */
ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3])
{
const float old_zup1 = zup[1]; /* in case yup == zup */
yup[0] = zup[0];
yup[1] = zup[2];
yup[2] = -old_zup1;
}
ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3])
{
const short old_zup1 = zup[1]; /* in case yup == zup */
yup[0] = zup[0];
yup[1] = zup[2];
yup[2] = -old_zup1;
}
/* Names are given in (dst, src) order, just like
* the parameters of copy_m44_axis_swap() */
typedef enum {
ABC_ZUP_FROM_YUP = 1,
ABC_YUP_FROM_ZUP = 2,
} AbcAxisSwapMode;
/* Create a rotation matrix for each axis from euler angles.
* Euler angles are swapped to change coordinate system. */
void create_swapped_rotation_matrix(float rot_x_mat[3][3],
float rot_y_mat[3][3],
float rot_z_mat[3][3],
const float euler[3],
AbcAxisSwapMode mode);
void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode);
typedef enum {
ABC_MATRIX_WORLD = 1,
ABC_MATRIX_LOCAL = 2,
} AbcMatrixMode;
void create_transform_matrix(Object *obj,
float r_transform_mat[4][4],
AbcMatrixMode mode,
Object *proxy_from);

View File

@ -22,6 +22,7 @@
*/
#include "abc_reader_curves.h"
#include "abc_axis_conversion.h"
#include "abc_reader_transform.h"
#include "abc_util.h"

View File

@ -19,6 +19,7 @@
*/
#include "abc_reader_mesh.h"
#include "abc_axis_conversion.h"
#include "abc_reader_transform.h"
#include "abc_util.h"

View File

@ -19,6 +19,7 @@
*/
#include "abc_reader_nurbs.h"
#include "abc_axis_conversion.h"
#include "abc_reader_transform.h"
#include "abc_util.h"

View File

@ -19,6 +19,7 @@
*/
#include "abc_reader_object.h"
#include "abc_axis_conversion.h"
#include "abc_util.h"
extern "C" {

View File

@ -20,6 +20,7 @@
#include "abc_util.h"
#include "abc_axis_conversion.h"
#include "abc_reader_camera.h"
#include "abc_reader_curves.h"
#include "abc_reader_mesh.h"
@ -121,144 +122,6 @@ void split(const std::string &s, const char delim, std::vector<std::string> &tok
}
}
void create_swapped_rotation_matrix(float rot_x_mat[3][3],
float rot_y_mat[3][3],
float rot_z_mat[3][3],
const float euler[3],
AbcAxisSwapMode mode)
{
const float rx = euler[0];
float ry;
float rz;
/* Apply transformation */
switch (mode) {
case ABC_ZUP_FROM_YUP:
ry = -euler[2];
rz = euler[1];
break;
case ABC_YUP_FROM_ZUP:
ry = euler[2];
rz = -euler[1];
break;
default:
ry = 0.0f;
rz = 0.0f;
BLI_assert(false);
break;
}
unit_m3(rot_x_mat);
unit_m3(rot_y_mat);
unit_m3(rot_z_mat);
rot_x_mat[1][1] = cos(rx);
rot_x_mat[2][1] = -sin(rx);
rot_x_mat[1][2] = sin(rx);
rot_x_mat[2][2] = cos(rx);
rot_y_mat[2][2] = cos(ry);
rot_y_mat[0][2] = -sin(ry);
rot_y_mat[2][0] = sin(ry);
rot_y_mat[0][0] = cos(ry);
rot_z_mat[0][0] = cos(rz);
rot_z_mat[1][0] = -sin(rz);
rot_z_mat[0][1] = sin(rz);
rot_z_mat[1][1] = cos(rz);
}
/* Convert matrix from Z=up to Y=up or vice versa.
* Use yup_mat = zup_mat for in-place conversion. */
void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode)
{
float dst_rot[3][3], src_rot[3][3], dst_scale_mat[4][4];
float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3];
float src_trans[3], dst_scale[3], src_scale[3], euler[3];
zero_v3(src_trans);
zero_v3(dst_scale);
zero_v3(src_scale);
zero_v3(euler);
unit_m3(src_rot);
unit_m3(dst_rot);
unit_m4(dst_scale_mat);
/* TODO(Sybren): This code assumes there is no sheer component and no
* homogeneous scaling component, which is not always true when writing
* non-hierarchical (e.g. flat) objects (e.g. when parent has non-uniform
* scale and the child rotates). This is currently not taken into account
* when axis-swapping. */
/* Extract translation, rotation, and scale form matrix. */
mat4_to_loc_rot_size(src_trans, src_rot, src_scale, src_mat);
/* Get euler angles from rotation matrix. */
mat3_to_eulO(euler, ROT_MODE_XZY, src_rot);
/* Create X, Y, Z rotation matrices from euler angles. */
create_swapped_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, mode);
/* Concatenate rotation matrices. */
mul_m3_m3m3(dst_rot, dst_rot, rot_z_mat);
mul_m3_m3m3(dst_rot, dst_rot, rot_y_mat);
mul_m3_m3m3(dst_rot, dst_rot, rot_x_mat);
mat3_to_eulO(euler, ROT_MODE_XZY, dst_rot);
/* Start construction of dst_mat from rotation matrix */
unit_m4(dst_mat);
copy_m4_m3(dst_mat, dst_rot);
/* Apply translation */
switch (mode) {
case ABC_ZUP_FROM_YUP:
copy_zup_from_yup(dst_mat[3], src_trans);
break;
case ABC_YUP_FROM_ZUP:
copy_yup_from_zup(dst_mat[3], src_trans);
break;
default:
BLI_assert(false);
}
/* Apply scale matrix. Swaps y and z, but does not
* negate like translation does. */
dst_scale[0] = src_scale[0];
dst_scale[1] = src_scale[2];
dst_scale[2] = src_scale[1];
size_to_mat4(dst_scale_mat, dst_scale);
mul_m4_m4m4(dst_mat, dst_mat, dst_scale_mat);
}
/* Recompute transform matrix of object in new coordinate system
* (from Z-Up to Y-Up). */
void create_transform_matrix(Object *obj,
float r_yup_mat[4][4],
AbcMatrixMode mode,
Object *proxy_from)
{
float zup_mat[4][4];
/* get local or world matrix. */
if (mode == ABC_MATRIX_LOCAL && obj->parent) {
/* Note that this produces another matrix than the local matrix, due to
* constraints and modifiers as well as the obj->parentinv matrix. */
invert_m4_m4(obj->parent->imat, obj->parent->obmat);
mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat);
}
else {
copy_m4_m4(zup_mat, obj->obmat);
}
if (proxy_from) {
mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat);
}
copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP);
}
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
{
if (!prop.valid()) {

View File

@ -56,15 +56,6 @@ Imath::M44d convert_matrix_datatype(float mat[4][4]);
/* Convert from Alembic to float matrix representations. Does NOT convert from Y-up to Z-up. */
void convert_matrix_datatype(const Imath::M44d &xform, float r_mat[4][4]);
typedef enum {
ABC_MATRIX_WORLD = 1,
ABC_MATRIX_LOCAL = 2,
} AbcMatrixMode;
void create_transform_matrix(Object *obj,
float r_transform_mat[4][4],
AbcMatrixMode mode,
Object *proxy_from);
void split(const std::string &s, const char delim, std::vector<std::string> &tokens);
template<class TContainer> bool begins_with(const TContainer &input, const TContainer &match)
@ -115,66 +106,6 @@ float get_weight_and_index(float time,
AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSettings &settings);
/* ************************** */
/* TODO(kevin): for now keeping these transformations hardcoded to make sure
* everything works properly, and also because Alembic is almost exclusively
* used in Y-up software, but eventually they'll be set by the user in the UI
* like other importers/exporters do, to support other axis. */
/* Copy from Y-up to Z-up. */
ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3])
{
const float old_yup1 = yup[1]; /* in case zup == yup */
zup[0] = yup[0];
zup[1] = -yup[2];
zup[2] = old_yup1;
}
ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3])
{
const short old_yup1 = yup[1]; /* in case zup == yup */
zup[0] = yup[0];
zup[1] = -yup[2];
zup[2] = old_yup1;
}
/* Copy from Z-up to Y-up. */
ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3])
{
const float old_zup1 = zup[1]; /* in case yup == zup */
yup[0] = zup[0];
yup[1] = zup[2];
yup[2] = -old_zup1;
}
ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3])
{
const short old_zup1 = zup[1]; /* in case yup == zup */
yup[0] = zup[0];
yup[1] = zup[2];
yup[2] = -old_zup1;
}
/* Names are given in (dst, src) order, just like
* the parameters of copy_m44_axis_swap() */
typedef enum {
ABC_ZUP_FROM_YUP = 1,
ABC_YUP_FROM_ZUP = 2,
} AbcAxisSwapMode;
/* Create a rotation matrix for each axis from euler angles.
* Euler angles are swapped to change coordinate system. */
void create_swapped_rotation_matrix(float rot_x_mat[3][3],
float rot_y_mat[3][3],
float rot_z_mat[3][3],
const float euler[3],
AbcAxisSwapMode mode);
void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode);
/* *************************** */
#undef ABC_DEBUG_TIME

View File

@ -22,6 +22,7 @@
*/
#include "abc_writer_curves.h"
#include "abc_axis_conversion.h"
#include "abc_reader_curves.h"
#include "abc_writer_transform.h"

View File

@ -19,7 +19,7 @@
*/
#include "abc_writer_hair.h"
#include "abc_util.h"
#include "abc_axis_conversion.h"
#include "abc_writer_transform.h"
#include <cstdio>

View File

@ -19,7 +19,7 @@
*/
#include "abc_writer_mesh.h"
#include "abc_util.h"
#include "abc_axis_conversion.h"
#include "abc_writer_transform.h"
extern "C" {

View File

@ -19,7 +19,7 @@
*/
#include "abc_writer_nurbs.h"
#include "abc_util.h"
#include "abc_axis_conversion.h"
#include "abc_writer_transform.h"
extern "C" {

View File

@ -19,7 +19,7 @@
*/
#include "abc_writer_transform.h"
#include "abc_util.h"
#include "abc_axis_conversion.h"
#include <OpenEXR/ImathBoxAlgo.h>

View File

@ -1,7 +1,7 @@
#include "testing/testing.h"
// Keep first since utildefines defines AT which conflicts with STL
#include "intern/abc_util.h"
#include "intern/abc_axis_conversion.h"
extern "C" {
#include "BLI_math.h"