blob: 1507fc0dde6a8cb8e7b9594ca25295e235bba355 [file] [log] [blame] [edit]
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/*
* File "hand_d_tapenade_generated.c" is generated by Tapenade 3.14 (r7259) from this file.
* To reproduce such a generation you can use Tapenade CLI
* (can be downloaded from http://www-sop.inria.fr/tropics/tapenade/downloading.html)
*
* Firstly, add a type declaration of Matrix and Triangle to the content of this file (Tapenade can't process a file
* with unknown types). You can both take this declaration from the files "hand.h" and "<repo root>/src/cpp/shared/defs.h" or
* copypaste the following lines removing asterisks:
*
* typedef struct
* {
* int nrows;
* int ncols;
* double* data;
* } Matrix;
* typedef struct
* {
* int verts[3];
* } Triangle;
*
* Tapenade can't process a code with #define constants defined both by a user or by a standard library, so, you have
* to replace all "NULL" insertions in the file by some numeric value (e.g. 42). Note, that this value has to be unique
* in this file because you'll have to replace it back with "NULL" in the generated file.
* After Tapenade CLI installing use the next command to generate a file:
*
* tapenade -o hand_tapenade -head "hand_objective(err)/(theta) hand_objective_complicated(err)/(theta us)" hand.c
*
* This will produce a file "hand_tapenade_d.c" which content will be the same as the content of the file "hand_d_tapenade_generated.c",
* except one-line header, Matrix and Triangle type declarations (which should be removed) and NULL replaced by some value that
* you have chosen (you have to replace it back with "NULL"). Moreover a log-file "hand_tapenade_b.msg" will be produced.
*
* NOTE: the code in "hand_d_tapenade_generated.c" is wrong and won't work.
* REPAIRED SOURCE IS STORED IN THE FILE "hand_d.c".
* You can either use diff tool or read "hand_d.c" header to figure out what changes was performed to fix the code.
*
* NOTE: you can also use Tapenade web server (http://tapenade.inria.fr:8080/tapenade/index.jsp)
* for generating but result can be slightly different.
*/
#include "../adbench/hand.h"
extern "C" {
#include "hand.h"
/*========================================================================*/
/* MATRIX METHODS */
/*========================================================================*/
// returns a new matrix of size nrows * ncols
Matrix* get_new_matrix(int nrows, int ncols)
{
Matrix* mat = (Matrix*)malloc(sizeof(Matrix));
mat->nrows = nrows;
mat->ncols = ncols;
mat->data = (double*)malloc(nrows * ncols * sizeof(double));
return mat;
}
// return new empty matrix
Matrix* get_new_empty_matrix()
{
Matrix* mat = (Matrix*)malloc(sizeof(Matrix));
mat->nrows = 0;
mat->ncols = 0;
mat->data = NULL;
return mat;
}
// disposes data matrix holds
void delete_matrix(Matrix* mat)
{
if (mat->data != NULL)
{
free(mat->data);
}
free(mat);
}
// creates array of matricies
Matrix* get_matrix_array(int count)
{
Matrix* result = (Matrix*)malloc(count * sizeof(Matrix));
int i;
for (i = 0; i < count; i++)
{
result[i].data = NULL;
result[i].nrows = result[i].ncols = 0;
}
return result;
}
// disposes array of matricies
void delete_light_matrix_array(Matrix* matricies, int count)
{
int i;
for (i = 0; i < count; i++)
{
if (matricies[i].data != NULL)
{
free(matricies[i].data);
}
}
free(matricies);
}
// sets a new size of a matrix
void resize(Matrix* mat, int nrows, int ncols)
{
if (mat->nrows * mat->ncols != nrows * ncols)
{
if (mat->data != NULL)
{
free(mat->data);
}
if (nrows * ncols > 0)
{
mat->data = (double*)malloc(ncols * nrows * sizeof(double));
}
else
{
mat->data = NULL;
}
}
mat->ncols = ncols;
mat->nrows = nrows;
}
// multiplies matricies
void mat_mult(const Matrix* __restrict lhs, const Matrix* __restrict rhs, Matrix* __restrict out)
{
int i, j, k;
resize(out, lhs->nrows, rhs->ncols);
for (i = 0; i < lhs->nrows; i++)
{
for (k = 0; k < rhs->ncols; k++)
{
out->data[i + k * out->nrows] = lhs->data[i + 0 * lhs->nrows] * rhs->data[0 + k * rhs->nrows];
for (j = 1; j < lhs->ncols; j++)
{
out->data[i + k * out->nrows] += lhs->data[i + j * lhs->nrows] * rhs->data[j + k * rhs->nrows];
}
}
}
}
// set matrix identity
void set_identity(Matrix* mat)
{
int i_col, i_row;
for (i_col = 0; i_col < mat->ncols; i_col++)
{
for (i_row = 0; i_row < mat->nrows; i_row++)
{
if (i_col == i_row)
{
mat->data[i_row + i_col * mat->nrows] = 1.0;
}
else
{
mat->data[i_row + i_col * mat->nrows] = 0.0;
}
}
}
}
// fills matrix with the given value
void fill(Matrix* mat, double val)
{
int i;
for (i = 0; i < mat->ncols * mat->nrows; i++)
{
mat->data[i] = val;
}
}
// set a block of the matrix with another matrix
void set_block(Matrix* mat, int row_off, int col_off, const Matrix* block)
{
int i_col, i_row;
for (i_col = 0; i_col < block->ncols; i_col++)
{
for (i_row = 0; i_row < block->nrows; i_row++)
{
mat->data[i_row + row_off + (i_col + col_off) * mat->nrows] = block->data[i_row + i_col * block->nrows];
}
}
}
// copies one matrix to another
void copy(Matrix* dst, const Matrix* src)
{
if (dst->data != NULL)
{
free(dst->data);
}
dst->ncols = src->ncols;
dst->nrows = src->nrows;
dst->data = (double*)malloc(dst->ncols * dst->nrows * sizeof(double));
int i;
for (i = 0; i < dst->ncols * dst->nrows; i++)
{
dst->data[i] = src->data[i];
}
}
/*========================================================================*/
/* UTILS */
/*========================================================================*/
// sum of component squares
double square_sum(int n, double const* x)
{
int i;
double res = x[0] * x[0];
for (i = 1; i < n; i++)
{
res = res + x[i] * x[i];
}
return res;
}
/*========================================================================*/
/* MAIN LOGIC */
/*========================================================================*/
void angle_axis_to_rotation_matrix(
double const* angle_axis,
Matrix* R
)
{
double norm = sqrt(square_sum(3, angle_axis));
if (norm < 0.0001)
{
set_identity(R);
return;
}
double x = angle_axis[0] / norm;
double y = angle_axis[1] / norm;
double z = angle_axis[2] / norm;
double s = sin(norm);
double c = cos(norm);
R->data[0 + 0 * R->nrows] = x * x + (1 - x * x) * c; // first row
R->data[0 + 1 * R->nrows] = x * y * (1 - c) - z * s;
R->data[0 + 2 * R->nrows] = x * z * (1 - c) + y * s;
R->data[1 + 0 * R->nrows] = x * y * (1 - c) + z * s; // second row
R->data[1 + 1 * R->nrows] = y * y + (1 - y * y) * c;
R->data[1 + 2 * R->nrows] = y * z * (1 - c) - x * s;
R->data[2 + 0 * R->nrows] = x * z * (1 - c) - y * s; // third row
R->data[2 + 1 * R->nrows] = z * y * (1 - c) + x * s;
R->data[2 + 2 * R->nrows] = z * z + (1 - z * z) * c;
}
void apply_global_transform(
const Matrix* pose_params,
Matrix* positions
)
{
int i, j;
Matrix* R = get_new_matrix(3, 3);
angle_axis_to_rotation_matrix(pose_params->data, R);
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
R->data[j + i * R->nrows] *= pose_params->data[i + 1 * pose_params->nrows];
}
}
Matrix* tmp = get_new_empty_matrix();
mat_mult(R, positions, tmp);
for (j = 0; j < positions->ncols; j++)
{
for (i = 0; i < positions->nrows; i++)
{
positions->data[i + j * positions->nrows] = tmp->data[i + j * tmp->nrows] + pose_params->data[i + 2 * pose_params->nrows];
}
}
delete_matrix(R);
delete_matrix(tmp);
}
void relatives_to_absolutes(
int count,
const Matrix* relatives,
const int* parents,
Matrix* absolutes
)
{
int i;
for (i = 0; i < count; i++)
{
if (parents[i] == -1)
{
copy(&absolutes[i], &relatives[i]);
}
else
{
mat_mult(&absolutes[parents[i]], &relatives[i], &absolutes[i]);
}
}
}
void euler_angles_to_rotation_matrix(
double const* __restrict xzy,
Matrix* __restrict R
)
{
double tx = xzy[0];
double ty = xzy[2];
double tz = xzy[1];
Matrix* Rx = get_new_matrix(3, 3);
Matrix* Ry = get_new_matrix(3, 3);
Matrix* Rz = get_new_matrix(3, 3);
set_identity(Rx);
Rx->data[1 + 1 * Rx->nrows] = cos(tx);
Rx->data[2 + 1 * Rx->nrows] = sin(tx);
Rx->data[1 + 2 * Rx->nrows] = -Rx->data[2 + 1 * Rx->nrows];
Rx->data[2 + 2 * Rx->nrows] = Rx->data[1 + 1 * Rx->nrows];
set_identity(Ry);
Ry->data[0 + 0 * Ry->nrows] = cos(ty);
Ry->data[0 + 2 * Ry->nrows] = sin(ty);
Ry->data[2 + 0 * Ry->nrows] = -Ry->data[0 + 2 * Ry->nrows];
Ry->data[2 + 2 * Ry->nrows] = Ry->data[0 + 0 * Ry->nrows];
set_identity(Rz);
Rz->data[0 + 0 * Rz->nrows] = cos(tz);
Rz->data[1 + 0 * Rz->nrows] = sin(tz);
Rz->data[0 + 1 * Rz->nrows] = -Rz->data[1 + 0 * Rz->nrows];
Rz->data[1 + 1 * Rz->nrows] = Rz->data[0 + 0 * Rz->nrows];
Matrix* tmp = get_new_empty_matrix();
mat_mult(Rz, Ry, tmp);
mat_mult(tmp, Rx, R);
delete_matrix(Rx);
delete_matrix(Ry);
delete_matrix(Rz);
delete_matrix(tmp);
}
void get_posed_relatives(
int bone_count,
const Matrix* __restrict base_relatives,
const Matrix* __restrict pose_params,
Matrix* __restrict relatives
)
{
int i;
int offset = 3;
Matrix* tr = get_new_matrix(4, 4);
Matrix* R = get_new_matrix(3, 3);
for (i = 0; i < bone_count; i++)
{
set_identity(tr);
euler_angles_to_rotation_matrix(pose_params->data + (i + offset) * pose_params->nrows, R);
set_block(tr, 0, 0, R);
mat_mult(&base_relatives[i], tr, &relatives[i]);
}
delete_matrix(tr);
delete_matrix(R);
}
static inline void get_skinned_vertex_positions(
int bone_count,
const Matrix* __restrict base_relatives,
const int* parents,
const Matrix* __restrict inverse_base_absolutes,
const Matrix* __restrict base_positions,
const Matrix* __restrict weights,
int is_mirrored,
const Matrix* __restrict pose_params,
Matrix* __restrict positions,
int apply_global
)
{
int i;
Matrix* relatives = get_matrix_array(bone_count);
Matrix* absolutes = get_matrix_array(bone_count);
Matrix* transforms = get_matrix_array(bone_count);
get_posed_relatives(bone_count, base_relatives, pose_params, relatives);
relatives_to_absolutes(bone_count, relatives, parents, absolutes);
// Get bone transforms->
for (i = 0; i < bone_count; i++)
{
mat_mult(&absolutes[i], &inverse_base_absolutes[i], &transforms[i]);
}
// Transform vertices by necessary transforms-> + apply skinning
resize(positions, 3, base_positions->ncols);
fill(positions, 0.0);
Matrix* curr_positions = get_new_matrix(4, base_positions->ncols);
int i_bone, i_vert;
for (i_bone = 0; i_bone < bone_count; i_bone++)
{
mat_mult(&transforms[i_bone], base_positions, curr_positions);
for (i_vert = 0; i_vert < positions->ncols; i_vert++)
{
for (i = 0; i < 3; i++)
{
positions->data[i + i_vert * positions->nrows] +=
curr_positions->data[i + i_vert * curr_positions->nrows] *
weights->data[i_bone + i_vert * weights->nrows];
}
}
}
if (is_mirrored)
{
for (i = 0; i < positions->ncols; i++)
{
positions->data[0 + i * positions->nrows] *= -1;
}
}
if (apply_global)
{
apply_global_transform(pose_params, positions);
}
delete_matrix(curr_positions);
delete_light_matrix_array(relatives, bone_count);
delete_light_matrix_array(absolutes, bone_count);
delete_light_matrix_array(transforms, bone_count);
}
//% !!!!!!! fixed order pose_params !!!!!
//% 1) global_rotation 2) scale 3) global_translation
//% 4) wrist
//% 5) thumb1, 6)thumb2, 7) thumb3, 8) thumb4
//% similarly: index, middle, ring, pinky
//% end) forearm
void to_pose_params(
int count,
double const* __restrict theta,
const char** __restrict bone_names,
Matrix* __restrict pose_params
)
{
int i;
resize(pose_params, 3, count + 3);
fill(pose_params, 0.0);
for (i = 0; i < pose_params->nrows; i++)
{
pose_params->data[i] = theta[i];
pose_params->data[i + 1 * pose_params->nrows] = 1.0;
pose_params->data[i + 2 * pose_params->nrows] = theta[i + 3];
}
int i_theta = 6;
int i_pose_params = 5;
int n_fingers = 5;
int i_finger;
for (i_finger = 0; i_finger < n_fingers; i_finger++)
{
for (i = 2; i <= 4; i++)
{
pose_params->data[0 + i_pose_params * pose_params->nrows] = theta[i_theta];
i_theta++;
if (i == 2)
{
pose_params->data[1 + i_pose_params * pose_params->nrows] = theta[i_theta];
i_theta++;
}
i_pose_params++;
}
i_pose_params++;
}
}
void hand_objective(
double const* __restrict theta,
int bone_count,
const char** __restrict bone_names,
const int* __restrict parents,
Matrix* __restrict base_relatives,
Matrix* __restrict inverse_base_absolutes,
Matrix* __restrict base_positions,
Matrix* __restrict weights,
const Triangle* __restrict triangles,
int is_mirrored,
int corresp_count,
const int* __restrict correspondences,
Matrix* points,
double* __restrict err
)
{
Matrix* pose_params = get_new_empty_matrix();
to_pose_params(bone_count, theta, bone_names, pose_params);
Matrix* vertex_positions = get_new_empty_matrix();
get_skinned_vertex_positions(
bone_count,
base_relatives,
parents,
inverse_base_absolutes,
base_positions,
weights,
is_mirrored,
pose_params,
vertex_positions,
1
);
int i, j;
for (i = 0; i < corresp_count; i++)
{
for (j = 0; j < 3; j++)
{
err[i * 3 + j] =
points->data[j + i * points->nrows] -
vertex_positions->data[j + correspondences[i] * vertex_positions->nrows];
}
}
delete_matrix(pose_params);
delete_matrix(vertex_positions);
}
void hand_objective_complicated(
double const* theta,
double const* us,
int bone_count,
const char** bone_names,
const int* parents,
Matrix* base_relatives,
Matrix* inverse_base_absolutes,
Matrix* base_positions,
Matrix* weights,
const Triangle* triangles,
int is_mirrored,
int corresp_count,
const int* __restrict correspondences,
Matrix* points,
double* err
)
{
Matrix* pose_params = get_new_empty_matrix();
to_pose_params(bone_count, theta, bone_names, pose_params);
Matrix* vertex_positions = get_new_empty_matrix();
get_skinned_vertex_positions(
bone_count,
base_relatives,
parents,
inverse_base_absolutes,
base_positions,
weights,
is_mirrored,
pose_params,
vertex_positions,
1
);
int i, j;
for (i = 0; i < corresp_count; i++)
{
const int* verts = triangles[correspondences[i]].verts;
double const* u = &us[2 * i];
for (j = 0; j < 3; j++)
{
double hand_point_coord =
u[0] * vertex_positions->data[j + verts[0] * vertex_positions->nrows] +
u[1] * vertex_positions->data[j + verts[1] * vertex_positions->nrows] +
(1.0 - u[0] - u[1]) * vertex_positions->data[j + verts[2] * vertex_positions->nrows];
err[i * 3 + j] = points->data[j + i * points->nrows] - hand_point_coord;
}
}
}
//* tapenade -o hand_tapenade -head "hand_objective(err)/(theta) hand_objective_complicated(err)/(theta us)" hand.c
extern int enzyme_const;
extern int enzyme_dup;
extern int enzyme_dupnoneed;
void __enzyme_autodiff(...) noexcept;
// tapenade -o hand_tapenade -head "hand_objective(err)/(theta) hand_objective_complicated(err)/(theta us)" hand.c
void dhand_objective(
double const* theta,
double* dtheta,
int bone_count,
const char** bone_names,
const int* parents,
Matrix* base_relatives,
Matrix* inverse_base_absolutes,
Matrix* base_positions,
Matrix* weights,
const Triangle* triangles,
int is_mirrored,
int corresp_count,
const int* correspondences,
Matrix* points,
double* err,
double* derr
)
{
__enzyme_autodiff(hand_objective,
enzyme_dup, theta, dtheta,
enzyme_const, bone_count,
enzyme_const, bone_names,
enzyme_const, parents,
enzyme_const, base_relatives,
enzyme_const, inverse_base_absolutes,
enzyme_const, base_positions,
enzyme_const, weights,
enzyme_const, triangles,
enzyme_const, is_mirrored,
enzyme_const, corresp_count,
enzyme_const, correspondences,
enzyme_const, points,
enzyme_dupnoneed, err, derr
);
}
void dhand_objective_complicated(
double const* theta,
double* dtheta,
double const* us,
double* dus,
int bone_count,
const char** bone_names,
const int* parents,
Matrix* base_relatives,
Matrix* inverse_base_absolutes,
Matrix* base_positions,
Matrix* weights,
const Triangle* triangles,
int is_mirrored,
int corresp_count,
const int* correspondences,
Matrix* points,
double* err,
double* derr
) {
__enzyme_autodiff(hand_objective_complicated,
enzyme_dup, theta, dtheta,
enzyme_dup, us, dus,
enzyme_const, bone_count,
enzyme_const, bone_names,
enzyme_const, parents,
enzyme_const, base_relatives,
enzyme_const, inverse_base_absolutes,
enzyme_const, base_positions,
enzyme_const, weights,
enzyme_const, triangles,
enzyme_const, is_mirrored,
enzyme_const, corresp_count,
enzyme_const, correspondences,
enzyme_const, points,
enzyme_dupnoneed, err, derr
);
}
}
#if 0
//! Tapenade Forward
extern "C" {
#include <adBuffer.h>
// Struct created by Tapenade for holding Matrix diff info.
typedef struct {
double* data;
} Matrix_diff;
Matrix_diff* get_new_zero_matrix_diff(const Matrix* mat) /* TFIX */
{
Matrix_diff* result = (Matrix_diff*)malloc(sizeof(Matrix_diff));
result->data = (double*)malloc(mat->nrows * mat->ncols * sizeof(double));
for (int i = 0; i < mat->nrows * mat->ncols; i++)
{
result->data[i] = 0.0;
}
return result;
}
// removes matrix diff
void delete_matrix_diff(Matrix_diff* md) /* TFIX */
{
if (md->data != NULL)
{
free(md->data);
}
free(md);
}
// creates new matrix diff array initialized by zeros
Matrix_diff* get_new_zero_matrix_diff_array(int count, const Matrix* m_arr) /* TFIX */
{
Matrix_diff* result = (Matrix_diff*)malloc(count * sizeof(Matrix_diff));
int i;
for (i = 0; i < count; i++)
{
if (m_arr[i].data != NULL)
{
result[i].data = (double*)malloc(m_arr[i].nrows * m_arr[i].ncols * sizeof(double));
}
else
{
result[i].data = NULL;
}
}
return result;
}
// delete matrix diff array
void delete_matrix_diff_array(int count, Matrix_diff* md_arr) /* TFIX */
{
int i;
for (i = 0; i < count; i++)
{
if (md_arr[i].data != NULL)
{
free(md_arr[i].data);
}
}
free(md_arr);
}
/*
Differentiation of get_new_matrix in forward (tangent) mode:
Plus diff mem management of: alloc(*mat).data:in-out get_new_matrix:in-out
========================================================================
MATRIX METHODS
========================================================================*/
// returns a new matrix of size nrows * ncols
Matrix_diff * get_new_matrix_d(int nrows, int ncols, Matrix **get_new_matrix)
{
Matrix *mat;
Matrix_diff *matd;
matd = (Matrix_diff *)malloc(sizeof(Matrix_diff));
mat = (Matrix *)malloc(sizeof(Matrix));
mat->nrows = nrows;
mat->ncols = ncols;
matd->data = (double *)malloc(nrows*ncols*sizeof(double));
mat->data = (double *)malloc(nrows*ncols*sizeof(double));
*get_new_matrix = mat;
return matd;
}
/*
Differentiation of get_new_empty_matrix in forward (tangent) mode:
Plus diff mem management of: alloc(*mat).data:in-out get_new_empty_matrix:in-out
*/
// return new empty matrix
Matrix_diff * get_new_empty_matrix_d(Matrix **get_new_empty_matrix) {
Matrix *mat;
Matrix_diff *matd;
matd = (Matrix_diff *)malloc(sizeof(Matrix_diff));
mat = (Matrix *)malloc(sizeof(Matrix));
mat->nrows = 0;
mat->ncols = 0;
mat->data = NULL;
*get_new_empty_matrix = mat;
return matd;
}
/*
Differentiation of delete_matrix in forward (tangent) mode:
Plus diff mem management of: mat:out *mat.data:out
*/
// disposes data matrix holds
void delete_matrix_d0(Matrix *mat, Matrix_diff *matd) {
if (mat->data != NULL) {
free(matd->data);
free(mat->data);
}
free(matd);
free(mat);
}
/*
Differentiation of delete_matrix in forward (tangent) mode:
variations of useful results: *(*mat.data)
with respect to varying inputs: *(*mat.data)
Plus diff mem management of: mat:in-out *mat.data:in-out
*/
// disposes data matrix holds
void delete_matrix_d(Matrix *mat, Matrix_diff *matd) {
if (mat->data != NULL) {
free(matd->data);
free(mat->data);
}
free(matd);
free(mat);
}
/*
Differentiation of get_matrix_array in forward (tangent) mode:
Plus diff mem management of: get_matrix_array:in-out
*/
// creates array of matricies
Matrix_diff * get_matrix_array_d(int count, Matrix **get_matrix_array) {
Matrix *result;
Matrix_diff *resultd;
resultd = (Matrix_diff *)malloc(count*sizeof(Matrix_diff));
result = (Matrix *)malloc(count*sizeof(Matrix));
int i;
for (i = 0; i < count; ++i) {
result[i].data = NULL;
result[i].ncols = 0;
result[i].nrows = result[i].ncols;
}
*get_matrix_array = result;
return resultd;
}
/*
Differentiation of delete_light_matrix_array in forward (tangent) mode:
variations of useful results: *(*matricies.data)
with respect to varying inputs: *(*matricies.data)
Plus diff mem management of: matricies:in-out *matricies.data:out
*/
// disposes array of matricies
void delete_light_matrix_array_d(Matrix *matricies, Matrix_diff *matriciesd,
int count) {
int i;
for (i = 0; i < count; ++i)
if (matricies[i].data != NULL) {
free(matriciesd[i].data);
free(matricies[i].data);
}
free(matriciesd);
free(matricies);
}
/*
Differentiation of resize in forward (tangent) mode:
Plus diff mem management of: *mat.data:in-out
*/
// sets a new size of a matrix
void resize_d0(Matrix *mat, Matrix_diff *matd, int nrows, int ncols) {
if (mat->nrows*mat->ncols != nrows*ncols) {
if (mat->data != NULL) {
free(matd->data);
free(mat->data);
}
if (nrows*ncols > 0) {
matd->data = (double *)malloc(ncols*nrows*sizeof(double));
mat->data = (double *)malloc(ncols*nrows*sizeof(double));
} else
mat->data = NULL;
}
mat->ncols = ncols;
mat->nrows = nrows;
}
/*
Differentiation of resize in forward (tangent) mode:
variations of useful results: *(*mat.data)
with respect to varying inputs: *(*mat.data)
Plus diff mem management of: mat:in *mat.data:in-out
*/
// sets a new size of a matrix
void resize_d(Matrix *mat, Matrix_diff *matd, int nrows, int ncols) {
if (mat->nrows*mat->ncols != nrows*ncols) {
if (mat->data != NULL) {
free(matd->data);
free(mat->data);
}
if (nrows*ncols > 0) {
matd->data = (double *)malloc(ncols*nrows*sizeof(double));
mat->data = (double *)malloc(ncols*nrows*sizeof(double));
} else
mat->data = NULL;
}
mat->ncols = ncols;
mat->nrows = nrows;
}
/*
Differentiation of mat_mult in forward (tangent) mode:
variations of useful results: alloc(*(*mat.data)) *(*out.data)
with respect to varying inputs: alloc(*(*mat.data)) *(*out.data)
*(*lhs.data) *(*rhs.data)
Plus diff mem management of: out:in *out.data:in-out lhs:in
*lhs.data:in rhs:in *rhs.data:in
*/
// multiplies matricies
void mat_mult_d(const Matrix *lhs, const Matrix_diff *lhsd, const Matrix *rhs,
const Matrix_diff *rhsd, Matrix *out, Matrix_diff *outd) {
int i, j, k;
resize_d(out, outd, lhs->nrows, rhs->ncols);
for (i = 0; i < lhs->nrows; ++i)
for (k = 0; k < rhs->ncols; ++k) {
outd->data[i + k*out->nrows] = lhsd->data[i+0*lhs->nrows]*rhs->
data[0+k*rhs->nrows] + lhs->data[i+0*lhs->nrows]*rhsd->data[0+
k*rhs->nrows];
out->data[i + k*out->nrows] = lhs->data[i+0*lhs->nrows]*rhs->data[
0+k*rhs->nrows];
for (j = 1; j < lhs->ncols; ++j) {
outd->data[i + k*out->nrows] = outd->data[i + k*out->nrows] +
lhsd->data[i+j*lhs->nrows]*rhs->data[j+k*rhs->nrows] + lhs
->data[i+j*lhs->nrows]*rhsd->data[j+k*rhs->nrows];
out->data[i + k*out->nrows] += lhs->data[i+j*lhs->nrows]*rhs->
data[j+k*rhs->nrows];
}
}
}
/*
Differentiation of set_identity in forward (tangent) mode:
variations of useful results: *(*mat.data)
with respect to varying inputs: *(*mat.data)
Plus diff mem management of: mat:in *mat.data:in
*/
// set matrix identity
void set_identity_d(Matrix *mat, Matrix_diff *matd) {
int i_col, i_row;
for (i_col = 0; i_col < mat->ncols; ++i_col)
for (i_row = 0; i_row < mat->nrows; ++i_row)
if (i_col == i_row) {
matd->data[i_row + i_col*mat->nrows] = 0.0;
mat->data[i_row + i_col*mat->nrows] = 1.0;
} else {
matd->data[i_row + i_col*mat->nrows] = 0.0;
mat->data[i_row + i_col*mat->nrows] = 0.0;
}
}
/*
Differentiation of fill in forward (tangent) mode:
variations of useful results: *(*mat.data)
with respect to varying inputs: *(*mat.data)
Plus diff mem management of: mat:in *mat.data:in
*/
// fills matrix with the given value
void fill_d(Matrix *mat, Matrix_diff *matd, double val) {
int i;
for (i = 0; i < mat->ncols*mat->nrows; ++i) {
matd->data[i] = 0.0;
mat->data[i] = val;
}
}
// fills matrix with the given value
void fill_nodiff(Matrix *mat, double val) {
int i;
for (i = 0; i < mat->ncols*mat->nrows; ++i)
mat->data[i] = val;
}
/*
Differentiation of set_block in forward (tangent) mode:
variations of useful results: *(*mat.data)
with respect to varying inputs: *(*block.data) *(*mat.data)
Plus diff mem management of: block:in *block.data:in mat:in
*mat.data:in
*/
// set a block of the matrix with another matrix
void set_block_d(Matrix *mat, Matrix_diff *matd, int row_off, int col_off,
const Matrix *block, const Matrix_diff *blockd) {
int i_col, i_row;
for (i_col = 0; i_col < block->ncols; ++i_col)
for (i_row = 0; i_row < block->nrows; ++i_row) {
matd->data[i_row + row_off + (i_col+col_off)*mat->nrows] = blockd
->data[i_row + i_col*block->nrows];
mat->data[i_row + row_off + (i_col+col_off)*mat->nrows] = block->
data[i_row + i_col*block->nrows];
}
}
/*
Differentiation of copy in forward (tangent) mode:
variations of useful results: alloc(*(*dst.data)) *(*dst.data)
with respect to varying inputs: alloc(*(*dst.data)) *(*src.data)
*(*dst.data)
Plus diff mem management of: src:in *src.data:in dst:in *dst.data:in-out
*/
// copies one matrix to another
void copy_d(Matrix *dst, Matrix_diff *dstd, const Matrix *src, const
Matrix_diff *srcd) {
int ii1;
if (dst->data != NULL) {
free(dstd->data);
free(dst->data);
}
dst->ncols = src->ncols;
dst->nrows = src->nrows;
dstd->data = (double *)malloc(dst->ncols*dst->nrows*sizeof(double));
for (ii1 = 0; ii1 < dst->ncols*dst->nrows; ++ii1)
dstd->data[ii1] = 0.0;
dst->data = (double *)malloc(dst->ncols*dst->nrows*sizeof(double));
int i;
for (i = 0; i < dst->ncols*dst->nrows; ++i) {
dstd->data[i] = srcd->data[i];
dst->data[i] = src->data[i];
}
}
/*
Differentiation of square_sum in forward (tangent) mode:
variations of useful results: square_sum
with respect to varying inputs: *x
Plus diff mem management of: x:in
========================================================================
UTILS
========================================================================*/
// sum of component squares
double square_sum_d(int n, const double *x, const double *xd, double *
square_sum) {
int i;
double res = x[0]*x[0];
double resd = xd[0]*x[0] + x[0]*xd[0];
for (i = 1; i < n; ++i) {
resd = resd + xd[i]*x[i] + x[i]*xd[i];
res = res + x[i]*x[i];
}
*square_sum = res;
return resd;
}
/*
Differentiation of angle_axis_to_rotation_matrix in forward (tangent) mode:
variations of useful results: *(*R.data)
with respect to varying inputs: *angle_axis *(*R.data)
Plus diff mem management of: angle_axis:in R:in *R.data:in
========================================================================
MAIN LOGIC
========================================================================*/
void angle_axis_to_rotation_matrix_d(const double *angle_axis, const double *
angle_axisd, Matrix *R, Matrix_diff *Rd) {
double norm;
double normd;
double result1;
double result1d;
result1d = square_sum_d(3, angle_axis, angle_axisd, &result1);
normd = (result1 == 0.0 ? 0.0 : result1d/(2.0*sqrt(result1)));
norm = sqrt(result1);
if (norm < 0.0001)
set_identity_d(R, Rd);
else {
double x = angle_axis[0]/norm;
double xd = (angle_axisd[0]*norm-angle_axis[0]*normd)/(norm*norm);
double y = angle_axis[1]/norm;
double yd = (angle_axisd[1]*norm-angle_axis[1]*normd)/(norm*norm);
double z = angle_axis[2]/norm;
double zd = (angle_axisd[2]*norm-angle_axis[2]*normd)/(norm*norm);
double s;
double sd;
sd = normd*cos(norm);
s = sin(norm);
double c;
double cd;
cd = -(normd*sin(norm));
c = cos(norm);
Rd->data[0 + 0*R->nrows] = xd*x + x*xd + (-(xd*x)-x*xd)*c + (1-x*x)*cd
;
R->data[0 + 0*R->nrows] = x*x + (1-x*x)*c;
// first row
Rd->data[0 + 1*R->nrows] = (xd*y+x*yd)*(1-c) - x*y*cd - zd*s - z*sd;
R->data[0 + 1*R->nrows] = x*y*(1-c) - z*s;
Rd->data[0 + 2*R->nrows] = (xd*z+x*zd)*(1-c) - x*z*cd + yd*s + y*sd;
R->data[0 + 2*R->nrows] = x*z*(1-c) + y*s;
Rd->data[1 + 0*R->nrows] = (xd*y+x*yd)*(1-c) - x*y*cd + zd*s + z*sd;
R->data[1 + 0*R->nrows] = x*y*(1-c) + z*s;
// second row
Rd->data[1 + 1*R->nrows] = yd*y + y*yd + (-(yd*y)-y*yd)*c + (1-y*y)*cd
;
R->data[1 + 1*R->nrows] = y*y + (1-y*y)*c;
Rd->data[1 + 2*R->nrows] = (yd*z+y*zd)*(1-c) - y*z*cd - xd*s - x*sd;
R->data[1 + 2*R->nrows] = y*z*(1-c) - x*s;
Rd->data[2 + 0*R->nrows] = (xd*z+x*zd)*(1-c) - x*z*cd - yd*s - y*sd;
R->data[2 + 0*R->nrows] = x*z*(1-c) - y*s;
// third row
Rd->data[2 + 1*R->nrows] = (zd*y+z*yd)*(1-c) - z*y*cd + xd*s + x*sd;
R->data[2 + 1*R->nrows] = z*y*(1-c) + x*s;
Rd->data[2 + 2*R->nrows] = zd*z + z*zd + (-(zd*z)-z*zd)*c + (1-z*z)*cd
;
R->data[2 + 2*R->nrows] = z*z + (1-z*z)*c;
}
}
/*
Differentiation of apply_global_transform in forward (tangent) mode:
variations of useful results: alloc(*(*mat.data)) *(alloc(*mat).data)
alloc(*(*mat.data)) *(alloc(*mat).data) *(*positions.data)
with respect to varying inputs: alloc(*(*mat.data)) *(alloc(*mat).data)
alloc(*(*mat.data)) *(alloc(*mat).data) *(*pose_params.data)
*(*positions.data)
Plus diff mem management of: alloc(*mat).data:in-out alloc(*mat).data:in-out
pose_params:in *pose_params.data:in positions:in
*positions.data:in
*/
void apply_global_transform_d(const Matrix *pose_params, const Matrix_diff *
pose_paramsd, Matrix *positions, Matrix_diff *positionsd) {
int i, j;
Matrix *R;
Matrix_diff *Rd;
Rd = get_new_matrix_d(3, 3, &R);
angle_axis_to_rotation_matrix_d(pose_params->data, pose_paramsd->data, R,
Rd);
for (i = 0; i < 3; ++i)
for (j = 0; j < 3; ++j) {
Rd->data[j + i*R->nrows] = Rd->data[j+i*R->nrows]*pose_params->
data[i+1*pose_params->nrows] + R->data[j+i*R->nrows]*
pose_paramsd->data[i+1*pose_params->nrows];
R->data[j + i*R->nrows] *= pose_params->data[i + 1*pose_params->
nrows];
}
Matrix *tmp;
Matrix_diff *tmpd;
tmpd = get_new_empty_matrix_d(&tmp);
mat_mult_d(R, Rd, positions, positionsd, tmp, tmpd);
for (j = 0; j < positions->ncols; ++j)
for (i = 0; i < positions->nrows; ++i) {
positionsd->data[i + j*positions->nrows] = tmpd->data[i + j*tmp->
nrows] + pose_paramsd->data[i + 2*pose_params->nrows];
positions->data[i + j*positions->nrows] = tmp->data[i + j*tmp->
nrows] + pose_params->data[i + 2*pose_params->nrows];
}
delete_matrix_d(R, Rd);
delete_matrix_d(tmp, tmpd);
}
/*
Differentiation of relatives_to_absolutes in forward (tangent) mode:
variations of useful results: alloc(*(*dst.data)) alloc(*(*mat.data))
*(*absolutes.data)
with respect to varying inputs: alloc(*(*mat.data)) *(*absolutes.data)
*(*relatives.data)
Plus diff mem management of: absolutes:in *absolutes.data:out
relatives:in
*/
void relatives_to_absolutes_d(int count, const Matrix *relatives, const
Matrix_diff *relativesd, const int *parents, Matrix *absolutes,
Matrix_diff *absolutesd) {
int i;
for (i = 0; i < count; ++i)
if (parents[i] == -1)
copy_d(&(absolutes[i]), &(absolutesd[i]), &(relatives[i]), &(
relativesd[i]));
else
mat_mult_d(&(absolutes[parents[i]]), &(absolutesd[parents[i]]), &(
relatives[i]), &(relativesd[i]), &(absolutes[i]), &(
absolutesd[i]));
}
/*
Differentiation of euler_angles_to_rotation_matrix in forward (tangent) mode:
variations of useful results: alloc(*(*mat.data)) *(alloc(*mat).data)
alloc(*(*mat.data)) *(alloc(*mat).data) *(*R.data)
with respect to varying inputs: alloc(*(*mat.data)) *(alloc(*mat).data)
alloc(*(*mat.data)) *(alloc(*mat).data) *xzy *(*R.data)
Plus diff mem management of: alloc(*mat).data:in-out alloc(*mat).data:in-out
xzy:in R:in *R.data:in-out
*/
void euler_angles_to_rotation_matrix_d(const double *xzy, const double *xzyd,
Matrix *R, Matrix_diff *Rd) {
double tx = xzy[0];
double txd = xzyd[0];
double ty = xzy[2];
double tyd = xzyd[2];
double tz = xzy[1];
double tzd = xzyd[1];
Matrix *Rx;
Matrix_diff *Rxd;
Rxd = get_new_matrix_d(3, 3, &Rx);
Matrix *Ry;
Matrix_diff *Ryd;
Ryd = get_new_matrix_d(3, 3, &Ry);
Matrix *Rz;
Matrix_diff *Rzd;
Rzd = get_new_matrix_d(3, 3, &Rz);
set_identity_d(Rx, Rxd);
Rxd->data[1 + 1*Rx->nrows] = -(txd*sin(tx));
Rx->data[1 + 1*Rx->nrows] = cos(tx);
Rxd->data[2 + 1*Rx->nrows] = txd*cos(tx);
Rx->data[2 + 1*Rx->nrows] = sin(tx);
Rxd->data[1 + 2*Rx->nrows] = -Rxd->data[2+1*Rx->nrows];
Rx->data[1 + 2*Rx->nrows] = -Rx->data[2+1*Rx->nrows];
Rxd->data[2 + 2*Rx->nrows] = Rxd->data[1 + 1*Rx->nrows];
Rx->data[2 + 2*Rx->nrows] = Rx->data[1 + 1*Rx->nrows];
set_identity_d(Ry, Ryd);
Ryd->data[0 + 0*Ry->nrows] = -(tyd*sin(ty));
Ry->data[0 + 0*Ry->nrows] = cos(ty);
Ryd->data[0 + 2*Ry->nrows] = tyd*cos(ty);
Ry->data[0 + 2*Ry->nrows] = sin(ty);
Ryd->data[2 + 0*Ry->nrows] = -Ryd->data[0+2*Ry->nrows];
Ry->data[2 + 0*Ry->nrows] = -Ry->data[0+2*Ry->nrows];
Ryd->data[2 + 2*Ry->nrows] = Ryd->data[0 + 0*Ry->nrows];
Ry->data[2 + 2*Ry->nrows] = Ry->data[0 + 0*Ry->nrows];
set_identity_d(Rz, Rzd);
Rzd->data[0 + 0*Rz->nrows] = -(tzd*sin(tz));
Rz->data[0 + 0*Rz->nrows] = cos(tz);
Rzd->data[1 + 0*Rz->nrows] = tzd*cos(tz);
Rz->data[1 + 0*Rz->nrows] = sin(tz);
Rzd->data[0 + 1*Rz->nrows] = -Rzd->data[1+0*Rz->nrows];
Rz->data[0 + 1*Rz->nrows] = -Rz->data[1+0*Rz->nrows];
Rzd->data[1 + 1*Rz->nrows] = Rzd->data[0 + 0*Rz->nrows];
Rz->data[1 + 1*Rz->nrows] = Rz->data[0 + 0*Rz->nrows];
Matrix *tmp;
Matrix_diff *tmpd;
tmpd = get_new_empty_matrix_d(&tmp);
mat_mult_d(Rz, Rzd, Ry, Ryd, tmp, tmpd);
mat_mult_d(tmp, tmpd, Rx, Rxd, R, Rd);
delete_matrix_d(Rx, Rxd);
delete_matrix_d(Ry, Ryd);
delete_matrix_d(Rz, Rzd);
delete_matrix_d(tmp, tmpd);
}
/*
Differentiation of get_posed_relatives in forward (tangent) mode:
variations of useful results: alloc(*(*mat.data)) *(alloc(*mat).data)
alloc(*(*mat.data)) *(alloc(*mat).data) *(*relatives.data)
with respect to varying inputs: alloc(*(*mat.data)) *(alloc(*mat).data)
*(*pose_params.data)
Plus diff mem management of: alloc(*mat).data:in-out alloc(*mat).data:in-out
pose_params:in *pose_params.data:in base_relatives:in
relatives:in
*/
void get_posed_relatives_d(int bone_count, const Matrix *base_relatives, const
Matrix_diff *base_relativesd, const Matrix *pose_params, const
Matrix_diff *pose_paramsd, Matrix *relatives, Matrix_diff *relativesd)
{
int i, j; /* TFIX */
int offset = 3;
Matrix *tr;
Matrix_diff *trd;
trd = get_new_matrix_d(4, 4, &tr);
Matrix *R;
Matrix_diff *Rd;
Rd = get_new_matrix_d(3, 3, &R);
/* TFIX */
for (i = 0; i < bone_count; ++i) {
set_identity_d(tr, trd);
euler_angles_to_rotation_matrix_d(pose_params->data + (i+offset)*
pose_params->nrows, pose_paramsd->
data + (i+offset)*pose_params->nrows
, R, Rd);
set_block_d(tr, trd, 0, 0, R, Rd);
for (j = 0; j < base_relatives->nrows * base_relatives->ncols; j++) /* TFIX */
base_relativesd[i].data[j] = 0.0;
mat_mult_d(&(base_relatives[i]), &(base_relativesd[i]), tr, trd, &(
relatives[i]), &(relativesd[i]));
}
delete_matrix_d(tr, trd);
delete_matrix_d(R, Rd);
}
/*
Differentiation of get_skinned_vertex_positions in forward (tangent) mode:
variations of useful results: alloc(*(*mat.data)) *(alloc(*mat).data)
*(*positions.data)
with respect to varying inputs: alloc(*(*mat.data)) *(alloc(*mat).data)
*(*pose_params.data) *(*positions.data)
Plus diff mem management of: alloc(*mat).data:in-out alloc(*mat).data:in-out
pose_params:in *pose_params.data:in base_positions:in
*base_positions.data:in positions:in *positions.data:in-out
inverse_base_absolutes:in
*/
void get_skinned_vertex_positions_d(int bone_count, const Matrix *
base_relatives, const int *parents, const Matrix *
inverse_base_absolutes, const Matrix_diff *inverse_base_absolutesd,
const Matrix *base_positions, const Matrix_diff *base_positionsd,
const Matrix *weights, int is_mirrored, const Matrix *pose_params,
const Matrix_diff *pose_paramsd, Matrix *positions, Matrix_diff *
positionsd, int apply_global) {
int i, j; /* TFIX */
Matrix *relatives;
Matrix_diff *relativesd;
Matrix_diff* base_relativesd = get_new_zero_matrix_diff_array(bone_count, base_relatives); /* TFIX */
relativesd = get_matrix_array_d(bone_count, &relatives);
Matrix *absolutes;
Matrix_diff *absolutesd;
absolutesd = get_matrix_array_d(bone_count, &absolutes);
Matrix *transforms;
Matrix_diff *transformsd;
transformsd = get_matrix_array_d(bone_count, &transforms);
get_posed_relatives_d(bone_count, base_relatives, base_relativesd,
pose_params, pose_paramsd, relatives, relativesd);
relatives_to_absolutes_d(bone_count, relatives, relativesd, parents,
absolutes, absolutesd);
// Get bone transforms->
for (i = 0; i < bone_count; ++i) {
for (j = 0; j < inverse_base_absolutes[i].nrows * inverse_base_absolutes[i].ncols; j++) /* TFIX */
inverse_base_absolutesd[i].data[j] = 0.0;
mat_mult_d(&(absolutes[i]), &(absolutesd[i]), &(inverse_base_absolutes
[i]), &(inverse_base_absolutesd[i]), &(transforms[i]), &(
transformsd[i]));
}
// Transform vertices by necessary transforms-> + apply skinning
resize_d(positions, positionsd, 3, base_positions->ncols);
fill_d(positions, positionsd, 0.0);
Matrix *curr_positions;
Matrix_diff *curr_positionsd;
curr_positionsd = get_new_matrix_d(4, base_positions->ncols, &
curr_positions);
int i_bone, i_vert;
for (i_bone = 0; i_bone < bone_count; ++i_bone) {
for (i = 0; i < base_positions->nrows * base_positions->ncols; i++) /* TFIX */
base_positionsd->data[i] = 0.0;
mat_mult_d(&(transforms[i_bone]), &(transformsd[i_bone]),
base_positions, base_positionsd, curr_positions,
curr_positionsd);
for (i_vert = 0; i_vert < positions->ncols; ++i_vert)
for (i = 0; i < 3; ++i) {
positionsd->data[i + i_vert*positions->nrows] = positionsd->
data[i + i_vert*positions->nrows] + weights->data[i_bone+
i_vert*weights->nrows]*curr_positionsd->data[i+i_vert*
curr_positions->nrows];
positions->data[i + i_vert*positions->nrows] += curr_positions
->data[i+i_vert*curr_positions->nrows]*weights->data[i_bone+
i_vert*weights->nrows];
}
}
if (is_mirrored)
for (i = 0; i < positions->ncols; ++i) {
positionsd->data[0 + i*positions->nrows] = -positionsd->data[0+i*
positions->nrows];
positions->data[0 + i*positions->nrows] *= -1;
}
if (apply_global)
apply_global_transform_d(pose_params, pose_paramsd, positions,
positionsd);
delete_matrix_d(curr_positions, curr_positionsd);
delete_light_matrix_array_d(relatives, relativesd, bone_count);
delete_light_matrix_array_d(absolutes, absolutesd, bone_count);
delete_light_matrix_array_d(transforms, transformsd, bone_count);
delete_matrix_diff_array(bone_count, base_relativesd); /* TFIX */ // Added to dispose memory allocated in repaired code
}
/*
Differentiation of to_pose_params in forward (tangent) mode:
variations of useful results: alloc(*(*mat.data)) *(*pose_params.data)
with respect to varying inputs: *theta
Plus diff mem management of: pose_params:in *pose_params.data:in-out
theta:in
*/
//% !!!!!!! fixed order pose_params !!!!!
//% 1) global_rotation 2) scale 3) global_translation
//% 4) wrist
//% 5) thumb1, 6)thumb2, 7) thumb3, 8) thumb4
//% similarly: index, middle, ring, pinky
//% end) forearm
void to_pose_params_d(int count, const double *theta, const double *thetad,
const char **bone_names, Matrix *pose_params, Matrix_diff *
pose_paramsd) {
int i;
resize_d0(pose_params, pose_paramsd, 3, count + 3);
fill_d(pose_params, pose_paramsd, 0.0); /* TFIX */
for (i = 0; i < pose_params->nrows; ++i) {
pose_paramsd->data[i] = thetad[i];
pose_params->data[i] = theta[i];
pose_paramsd->data[i + 1*pose_params->nrows] = 0.0;
pose_params->data[i + 1*pose_params->nrows] = 1.0;
pose_paramsd->data[i + 2*pose_params->nrows] = thetad[i + 3];
pose_params->data[i + 2*pose_params->nrows] = theta[i + 3];
}
int i_theta = 6;
int i_pose_params = 5;
int n_fingers = 5;
int i_finger;
for (i_finger = 0; i_finger < n_fingers; ++i_finger) {
for (i = 2; i < 5; ++i) {
pose_paramsd->data[0 + i_pose_params*pose_params->nrows] = thetad[
i_theta];
pose_params->data[0 + i_pose_params*pose_params->nrows] = theta[
i_theta];
i_theta++;
if (i == 2) {
pose_paramsd->data[1 + i_pose_params*pose_params->nrows] =
thetad[i_theta];
pose_params->data[1 + i_pose_params*pose_params->nrows] =
theta[i_theta];
i_theta++;
}
i_pose_params++;
}
i_pose_params++;
}
}
/*
Differentiation of hand_objective in forward (tangent) mode:
variations of useful results: *err
with respect to varying inputs: *theta
RW status of diff variables: *err:out *theta:in
Plus diff mem management of: alloc(*mat).data:in-out alloc(*mat).data:in-out
err:in base_positions:in *base_positions.data:in
theta:in
*/
void hand_objective_d(const double *theta, double *thetad, int
bone_count, const char **bone_names, const int *parents, Matrix *
base_relatives, Matrix *inverse_base_absolutes, Matrix *base_positions
, Matrix *weights, const Triangle * /* TFIX */
triangles, int is_mirrored, int corresp_count, const int *
correspondences, Matrix *points, double *err, double *errd) {
Matrix_diff* base_positionsd = get_new_zero_matrix_diff(base_positions); /* TFIX */ // Added instead of function parameter
Matrix *pose_params;
Matrix_diff *pose_paramsd;
Matrix_diff* inverse_base_absolutesd = get_new_zero_matrix_diff_array(bone_count, inverse_base_absolutes); /* TFIX */
pose_paramsd = get_new_empty_matrix_d(&pose_params);
to_pose_params_d(bone_count, theta, thetad, bone_names, pose_params,
pose_paramsd);
Matrix *vertex_positions;
Matrix_diff *vertex_positionsd;
vertex_positionsd = get_new_empty_matrix_d(&vertex_positions);
get_skinned_vertex_positions_d(bone_count, base_relatives, parents,
inverse_base_absolutes,
inverse_base_absolutesd, base_positions,
base_positionsd, weights, is_mirrored,
pose_params, pose_paramsd, vertex_positions
, vertex_positionsd, 1);
int i, j;
*errd = 0.0;
for (i = 0; i < corresp_count; ++i)
for (j = 0; j < 3; ++j) {
errd[i*3 + j] = -vertex_positionsd->data[j+correspondences[i]*
vertex_positions->nrows];
err[i*3 + j] = points->data[j + i*points->nrows] -
vertex_positions->data[j + correspondences[i]*vertex_positions
->nrows];
}
delete_matrix_d0(pose_params, pose_paramsd);
delete_matrix_d0(vertex_positions, vertex_positionsd);
delete_matrix_diff(base_positionsd); /* TFIX */ // Added to dispose memory allocated in repaired code
delete_matrix_diff_array(bone_count, inverse_base_absolutesd);
}
/*
Differentiation of hand_objective_complicated in forward (tangent) mode:
variations of useful results: *err
with respect to varying inputs: *us *theta
RW status of diff variables: *err:out *us:in *theta:in
Plus diff mem management of: alloc(*mat).data:in-out alloc(*mat).data:in-out
err:in us:in base_positions:in *base_positions.data:in
theta:in
*/
void hand_objective_complicated_d(const double *theta, double *thetad,
const double *us, double *usd, int bone_count, const char **
bone_names, const int *parents, Matrix *base_relatives, Matrix *
inverse_base_absolutes, Matrix *base_positions, /* TFIX */
Matrix *weights, const Triangle *triangles, int
is_mirrored, int corresp_count, const int *correspondences, Matrix *
points, double *err, double *errd) {
Matrix_diff* base_positionsd = get_new_zero_matrix_diff(base_positions); /* TFIX */ // Added instead of function parameter
Matrix *pose_params;
Matrix_diff *pose_paramsd;
Matrix_diff* inverse_base_absolutesd = get_new_zero_matrix_diff_array(bone_count, inverse_base_absolutes); /* TFIX */
pose_paramsd = get_new_empty_matrix_d(&pose_params);
to_pose_params_d(bone_count, theta, thetad, bone_names, pose_params,
pose_paramsd);
Matrix *vertex_positions;
Matrix_diff *vertex_positionsd;
vertex_positionsd = get_new_empty_matrix_d(&vertex_positions);
get_skinned_vertex_positions_d(bone_count, base_relatives, parents,
inverse_base_absolutes,
inverse_base_absolutesd, base_positions,
base_positionsd, weights, is_mirrored,
pose_params, pose_paramsd, vertex_positions
, vertex_positionsd, 1);
int i, j;
*errd = 0.0;
for (i = 0; i < corresp_count; ++i) {
const int *verts = triangles[correspondences[i]].verts;
double *u = const_cast<double*>(&(us[2*i]));
double *ud = &(usd[2*i]);
for (j = 0; j < 3; ++j) {
double hand_point_coord = u[0]*vertex_positions->data[j+verts[0]*
vertex_positions->nrows] + u[1]*vertex_positions->data[j+verts[1]*
vertex_positions->nrows] + (1.0-u[0]-u[1])*vertex_positions->data[
j+verts[2]*vertex_positions->nrows];
double hand_point_coordd = ud[0]*vertex_positions->data[j+verts[0]
*vertex_positions->nrows] + u[0]*vertex_positionsd->data[j+verts[0
]*vertex_positions->nrows] + ud[1]*vertex_positions->data[j+verts[
1]*vertex_positions->nrows] + u[1]*vertex_positionsd->data[j+verts
[1]*vertex_positions->nrows] + (-ud[0]-ud[1])*vertex_positions->
data[j+verts[2]*vertex_positions->nrows] + (1.0-u[0]-u[1])*
vertex_positionsd->data[j+verts[2]*vertex_positions->nrows];
errd[i*3 + j] = -hand_point_coordd;
err[i*3 + j] = points->data[j + i*points->nrows] -
hand_point_coord;
}
}
delete_matrix_diff(base_positionsd); /* TFIX */ // Added to dispose memory allocated in repaired code
delete_matrix_diff_array(bone_count, inverse_base_absolutesd);
}
}
#else
extern "C" {
#include <adBuffer.h>
// Struct created by Tapenade for holding Matrix diff info.
typedef struct {
double* data;
} Matrix_diff;
/*
Differentiation of get_new_matrix in reverse (adjoint) mode:
Plus diff mem management of: alloc(*mat).data:in-out get_new_matrix:in-out
========================================================================
MATRIX METHODS
========================================================================*/
// returns a new matrix of size nrows * ncols
void get_new_matrix_b(int nrows, int ncols, Matrix_diff *get_new_matrixb) {
Matrix *mat;
Matrix_diff *matb;
int ii1;
Matrix *get_new_matrix;
matb = (Matrix_diff *)malloc(sizeof(Matrix_diff));
matb->data = NULL;
mat = (Matrix *)malloc(sizeof(Matrix));
pushPointer8(matb->data);
matb->data = (double *)malloc(nrows*ncols*sizeof(double));
for (ii1 = 0; ii1 < nrows*ncols; ++ii1)
matb->data[ii1] = 0.0;
pushPointer8(mat->data);
mat->data = (double *)malloc(nrows*ncols*sizeof(double));
get_new_matrixb = matb;
free(mat->data);
popPointer8((void **)&(mat->data));
free(matb->data);
popPointer8((void **)&(matb->data));
free(mat);
free(matb);
}
/*========================================================================
MATRIX METHODS
========================================================================*/
// returns a new matrix of size nrows * ncols
Matrix * get_new_matrix_c(int nrows, int ncols) {
Matrix *mat;
mat = (Matrix *)malloc(sizeof(Matrix));
mat->nrows = nrows;
mat->ncols = ncols;
mat->data = (double *)malloc(nrows*ncols*sizeof(double));
return mat;
}
/*
Differentiation of get_new_empty_matrix in reverse (adjoint) mode:
Plus diff mem management of: alloc(*mat).data:in-out get_new_empty_matrix:in-out
*/
// return new empty matrix
void get_new_empty_matrix_b(Matrix_diff *get_new_empty_matrixb) {
Matrix *mat;
Matrix_diff *matb;
Matrix *get_new_empty_matrix;
matb = (Matrix_diff *)malloc(sizeof(Matrix_diff));
matb->data = NULL;
mat = (Matrix *)malloc(sizeof(Matrix));
matb->data = (double *)0;
get_new_empty_matrixb = matb;
free(mat);
free(matb);
}
// return new empty matrix
Matrix * get_new_empty_matrix_c() {
Matrix *mat;
mat = (Matrix *)malloc(sizeof(Matrix));
mat->nrows = 0;
mat->ncols = 0;
mat->data = (double *)0;
return mat;
}
/*
Differentiation of delete_matrix in reverse (adjoint) mode:
Plus diff mem management of: mat:out *mat.data:in-out
*/
// disposes data matrix holds
void delete_matrix_b(Matrix *mat, Matrix_diff *matb) {}
// disposes data matrix holds
void delete_matrix_c(Matrix *mat) {
if (mat->data != (double *)0)
free(mat->data);
free(mat);
}
/*
Differentiation of get_matrix_array in reverse (adjoint) mode:
Plus diff mem management of: get_matrix_array:in-out
*/
// creates array of matricies
void get_matrix_array_b(int count, Matrix_diff *get_matrix_arrayb) {
Matrix *result;
Matrix_diff *resultb;
int ii1;
Matrix *get_matrix_array;
resultb = (Matrix_diff *)malloc(count*sizeof(Matrix_diff));
for (ii1 = 0; ii1 < count; ++ii1)
resultb[ii1].data = NULL;
result = (Matrix *)malloc(count*sizeof(Matrix));
int i;
label100:
;
get_matrix_arrayb = resultb;
free(result);
free(resultb);
}
// creates array of matricies
Matrix * get_matrix_array_c(int count) {
Matrix *result;
result = (Matrix *)malloc(count*sizeof(Matrix));
int i;
for (i = 0; i < count; ++i) {
result[i].data = (double *)0;
result[i].ncols = 0;
result[i].nrows = result[i].ncols;
}
return result;
}
/*
Differentiation of delete_light_matrix_array in reverse (adjoint) mode:
Plus diff mem management of: matricies:out *matricies.data:out
*/
// disposes array of matricies
void delete_light_matrix_array_b(Matrix *matricies, Matrix_diff *matriciesb,
int count) {
int i;
pushPointer8(matriciesb);
pushPointer8(matricies);
popPointer8((void **)&matricies);
popPointer8((void **)&matriciesb);
}
// disposes array of matricies
void delete_light_matrix_array_c(Matrix *matricies, int count) {
int i;
for (i = 0; i < count; ++i)
if (matricies[i].data != (void *)0)
free(matricies[i].data);
free(matricies);
}
/*
Differentiation of resize in reverse (adjoint) mode:
Plus diff mem management of: *mat.data:in-out
*/
// sets a new size of a matrix
void resize_b(Matrix *mat, Matrix_diff *matb, int nrows, int ncols) {
int chunklength;
void *diffchunkold;
void *chunkold;
int ii1;
int branch;
if (mat->nrows*mat->ncols != nrows*ncols) {
if (mat->data != (void *)0) {
pushPointer8(matb->data);
free(matb->data);
pushPointer8(mat->data);
free(mat->data);
pushInteger4(chunklength);
pushControl1b(0);
} else
pushControl1b(1);
if (nrows*ncols > 0) {
pushPointer8(matb->data);
matb->data = (double *)malloc(ncols*nrows*sizeof(double));
for (ii1 = 0; ii1 < ncols*nrows; ++ii1)
matb->data[ii1] = 0.0;
pushPointer8(mat->data);
mat->data = (double *)malloc(ncols*nrows*sizeof(double));
free(mat->data);
popPointer8((void **)&(mat->data));
free(matb->data);
popPointer8((void **)&(matb->data));
} else {
pushPointer8(matb->data);
matb->data = (double *)0;
popPointer8((void **)&(matb->data));
}
popControl1b(&branch);
if (branch == 0) {
popInteger4(&chunklength);
mat->data = (double *)malloc(8*chunklength);
popPointer8((void **)&chunkold);
matb->data = (double *)malloc(8*chunklength);
popPointer8((void **)&diffchunkold);
}
}
}
// sets a new size of a matrix
void resize_c(Matrix *mat, int nrows, int ncols) {
if (mat->nrows*mat->ncols != nrows*ncols) {
if (mat->data != (void *)0)
free(mat->data);
if (nrows*ncols > 0)
mat->data = (double *)malloc(ncols*nrows*sizeof(double));
else
mat->data = (double *)0;
}
mat->ncols = ncols;
mat->nrows = nrows;
}
/*
Differentiation of mat_mult in reverse (adjoint) mode:
gradient of useful results: alloc(*(*mat.data)) *(*out.data)
*(*lhs.data) *(*rhs.data)
with respect to varying inputs: alloc(*(*mat.data)) *(*out.data)
*(*lhs.data) *(*rhs.data)
Plus diff mem management of: out:in *out.data:in-out lhs:in
*lhs.data:in rhs:in *rhs.data:in
*/
// multiplies matricies
void mat_mult_b(const Matrix *lhs, Matrix_diff *lhsb, const Matrix *rhs,
Matrix_diff *rhsb, Matrix *out, Matrix_diff *outb) {
int i, j, k;
pushInteger4(out->nrows);
pushInteger4(out->ncols);
pushPointer8(out->data);
resize_c(out, lhs->nrows, rhs->ncols);
for (i = 0; i < lhs->nrows; ++i)
for (k = 0; k < rhs->ncols; ++k) {
out->data[i + k*out->nrows] = lhs->data[i+0*lhs->nrows]*rhs->data[
0+k*rhs->nrows];
for (j = 1; j < lhs->ncols; ++j)
out->data[i + k*out->nrows] = out->data[i + k*out->nrows] +
lhs->data[i+j*lhs->nrows]*rhs->data[j+k*rhs->nrows];
}
for (i = lhs->nrows-1; i > -1; --i)
for (k = rhs->ncols-1; k > -1; --k) {
for (j = lhs->ncols-1; j > 0; --j) {
lhsb->data[i + j*lhs->nrows] = lhsb->data[i + j*lhs->nrows] +
rhs->data[j+k*rhs->nrows]*outb->data[i+k*out->nrows];
rhsb->data[j + k*rhs->nrows] = rhsb->data[j + k*rhs->nrows] +
lhs->data[i+j*lhs->nrows]*outb->data[i+k*out->nrows];
}
lhsb->data[i + 0*lhs->nrows] = lhsb->data[i + 0*lhs->nrows] + rhs
->data[0+k*rhs->nrows]*outb->data[i+k*out->nrows];
rhsb->data[0 + k*rhs->nrows] = rhsb->data[0 + k*rhs->nrows] + lhs
->data[i+0*lhs->nrows]*outb->data[i+k*out->nrows];
outb->data[i + k*out->nrows] = 0.0;
}
popPointer8((void **)&(out->data));
popInteger4(&(out->ncols));
popInteger4(&(out->nrows));
resize_b(out, outb, lhs->nrows, rhs->ncols);
}
// multiplies matricies
void mat_mult_c(const Matrix *lhs, const Matrix *rhs, Matrix *out) {
int i, j, k;
resize_c(out, lhs->nrows, rhs->ncols);
for (i = 0; i < lhs->nrows; ++i)
for (k = 0; k < rhs->ncols; ++k) {
out->data[i + k*out->nrows] = lhs->data[i+0*lhs->nrows]*rhs->data[
0+k*rhs->nrows];
for (j = 1; j < lhs->ncols; ++j)
out->data[i + k*out->nrows] += lhs->data[i+j*lhs->nrows]*rhs->
data[j+k*rhs->nrows];
}
}
/*
Differentiation of set_identity in reverse (adjoint) mode:
gradient of useful results: *(*mat.data)
with respect to varying inputs: *(*mat.data)
Plus diff mem management of: mat:in *mat.data:in
*/
// set matrix identity
void set_identity_b(Matrix *mat, Matrix_diff *matb) {
int i_col, i_row;
int branch;
for (i_col = 0; i_col < mat->ncols; ++i_col)
for (i_row = 0; i_row < mat->nrows; ++i_row)
if (i_col == i_row)
pushControl1b(1);
else
pushControl1b(0);
for (i_col = mat->ncols-1; i_col > -1; --i_col)
for (i_row = mat->nrows-1; i_row > -1; --i_row) {
popControl1b(&branch);
if (branch == 0)
matb->data[i_row + i_col*mat->nrows] = 0.0;
else
matb->data[i_row + i_col*mat->nrows] = 0.0;
}
}
// set matrix identity
void set_identity_c(Matrix *mat) {
int i_col, i_row;
for (i_col = 0; i_col < mat->ncols; ++i_col)
for (i_row = 0; i_row < mat->nrows; ++i_row)
if (i_col == i_row)
mat->data[i_row + i_col*mat->nrows] = 1.0;
else
mat->data[i_row + i_col*mat->nrows] = 0.0;
}
/*
Differentiation of fill in reverse (adjoint) mode:
gradient of useful results: *(*mat.data)
with respect to varying inputs: *(*mat.data)
Plus diff mem management of: mat:in *mat.data:in
*/
// fills matrix with the given value
void fill_b(Matrix *mat, Matrix_diff *matb, double val) {
int i;
for (i = mat->ncols*mat->nrows-1; i > -1; --i)
matb->data[i] = 0.0;
}
// fills matrix with the given value
void fill_c(Matrix *mat, double val) {
int i;
for (i = 0; i < mat->ncols*mat->nrows; ++i)
mat->data[i] = val;
}
/*
Differentiation of set_block in reverse (adjoint) mode:
gradient of useful results: *(*block.data) *(*mat.data)
with respect to varying inputs: *(*block.data) *(*mat.data)
Plus diff mem management of: block:in *block.data:in mat:in
*mat.data:in
*/
// set a block of the matrix with another matrix
void set_block_b(Matrix *mat, Matrix_diff *matb, int row_off, int col_off,
const Matrix *block, Matrix_diff *blockb) {
int i_col, i_row;
for (i_col = block->ncols-1; i_col > -1; --i_col)
for (i_row = block->nrows-1; i_row > -1; --i_row) {
blockb->data[i_row + i_col*block->nrows] = blockb->data[i_row +
i_col*block->nrows] + matb->data[i_row + row_off + (i_col+
col_off)*mat->nrows];
matb->data[i_row + row_off + (i_col+col_off)*mat->nrows] = 0.0;
}
}
// set a block of the matrix with another matrix
void set_block_c(Matrix *mat, int row_off, int col_off, const Matrix *block) {
int i_col, i_row;
for (i_col = 0; i_col < block->ncols; ++i_col)
for (i_row = 0; i_row < block->nrows; ++i_row)
mat->data[i_row + row_off + (i_col+col_off)*mat->nrows] = block->
data[i_row + i_col*block->nrows];
}
/*
Differentiation of copy in reverse (adjoint) mode:
gradient of useful results: alloc(*(*dst.data)) *(*src.data)
*(*dst.data)
with respect to varying inputs: alloc(*(*dst.data)) *(*src.data)
*(*dst.data)
Plus diff mem management of: src:in *src.data:in dst:in *dst.data:in-out
*/
// copies one matrix to another
void copy_b(Matrix *dst, Matrix_diff *dstb, const Matrix *src, Matrix_diff *
srcb) {
int chunklength;
int ii1;
void *diffchunkold;
void *chunkold;
int branch;
if (dst->data != (void *)0) {
pushPointer8(dstb->data);
free(dstb->data);
pushPointer8(dst->data);
free(dst->data);
pushInteger4(chunklength);
pushControl1b(0);
} else
pushControl1b(1);
pushInteger4(dst->ncols);
dst->ncols = src->ncols;
pushInteger4(dst->nrows);
dst->nrows = src->nrows;
dstb->data = (double *)malloc(dst->ncols*dst->nrows*sizeof(double));
for (ii1 = 0; ii1 < dst->ncols*dst->nrows; ++ii1)
dstb->data[ii1] = 0.0;
pushPointer8(dst->data);
dst->data = (double *)malloc(dst->ncols*dst->nrows*sizeof(double));
int i;
for (i = dst->ncols*dst->nrows-1; i > -1; --i) {
srcb->data[i] = srcb->data[i] + dstb->data[i];
dstb->data[i] = 0.0;
}
free(dst->data);
popPointer8((void **)&(dst->data));
free(dstb->data);
popInteger4(&(dst->nrows));
popInteger4(&(dst->ncols));
popControl1b(&branch);
if (branch == 0) {
popInteger4(&chunklength);
dst->data = (double *)malloc(8*chunklength);
popPointer8((void **)&chunkold);
dstb->data = (double *)malloc(8*chunklength);
popPointer8((void **)&diffchunkold);
for (ii1 = 0; ii1 < chunklength; ++ii1)
dstb->data[ii1] = 0.0;
}
}
// copies one matrix to another
void copy_c(Matrix *dst, const Matrix *src) {
if (dst->data != (void *)0)
free(dst->data);
dst->ncols = src->ncols;
dst->nrows = src->nrows;
dst->data = (double *)malloc(dst->ncols*dst->nrows*sizeof(double));
int i;
for (i = 0; i < dst->ncols*dst->nrows; ++i)
dst->data[i] = src->data[i];
}
/*
Differentiation of square_sum in reverse (adjoint) mode:
gradient of useful results: *x square_sum
with respect to varying inputs: *x
Plus diff mem management of: x:in
========================================================================
UTILS
========================================================================*/
// sum of component squares
void square_sum_b(int n, const double *x, double *xb, double square_sumb) {
int i;
double res = x[0]*x[0];
double resb = 0.0;
double square_sum;
resb = square_sumb;
for (i = n-1; i > 0; --i)
xb[i] = xb[i] + 2*x[i]*resb;
xb[0] = xb[0] + 2*x[0]*resb;
}
/*========================================================================
UTILS
========================================================================*/
// sum of component squares
double square_sum_c(int n, const double *x) {
int i;
double res = x[0]*x[0];
for (i = 1; i < n; ++i)
res = res + x[i]*x[i];
return res;
}
/*
Differentiation of angle_axis_to_rotation_matrix in reverse (adjoint) mode:
gradient of useful results: *angle_axis *(*R.data)
with respect to varying inputs: *angle_axis *(*R.data)
Plus diff mem management of: angle_axis:in R:in *R.data:in
========================================================================
MAIN LOGIC
========================================================================*/
void angle_axis_to_rotation_matrix_b(const double *angle_axis, double *
angle_axisb, Matrix *R, Matrix_diff *Rb) {
double norm;
double normb;
double result1;
double result1b;
result1 = square_sum_c(3, angle_axis);
norm = sqrt(result1);
if (norm < 0.0001) {
set_identity_b(R, Rb);
normb = 0.0;
} else {
double x = angle_axis[0]/norm;
double xb = 0.0;
double y = angle_axis[1]/norm;
double yb = 0.0;
double z = angle_axis[2]/norm;
double zb = 0.0;
double s;
double sb;
s = sin(norm);
double c;
double cb;
c = cos(norm);
// first row
// second row
// third row
zb = (2*z-2*z*c)*Rb->data[2+2*R->nrows];
cb = (1-z*z)*Rb->data[2+2*R->nrows];
Rb->data[2 + 2*R->nrows] = 0.0;
zb = zb + y*(1-c)*Rb->data[2+1*R->nrows];
yb = z*(1-c)*Rb->data[2+1*R->nrows];
cb = cb - z*y*Rb->data[2+1*R->nrows];
xb = s*Rb->data[2+1*R->nrows];
sb = x*Rb->data[2+1*R->nrows];
Rb->data[2 + 1*R->nrows] = 0.0;
xb = xb + z*(1-c)*Rb->data[2+0*R->nrows];
zb = zb + x*(1-c)*Rb->data[2+0*R->nrows];
cb = cb - x*z*Rb->data[2+0*R->nrows];
yb = yb - s*Rb->data[2+0*R->nrows];
sb = sb - y*Rb->data[2+0*R->nrows];
Rb->data[2 + 0*R->nrows] = 0.0;
yb = yb + z*(1-c)*Rb->data[1+2*R->nrows];
zb = zb + y*(1-c)*Rb->data[1+2*R->nrows];
cb = cb - y*z*Rb->data[1+2*R->nrows];
xb = xb - s*Rb->data[1+2*R->nrows];
sb = sb - x*Rb->data[1+2*R->nrows];
Rb->data[1 + 2*R->nrows] = 0.0;
yb = yb + (2*y-2*y*c)*Rb->data[1+1*R->nrows];
cb = cb + (1-y*y)*Rb->data[1+1*R->nrows];
Rb->data[1 + 1*R->nrows] = 0.0;
xb = xb + y*(1-c)*Rb->data[1+0*R->nrows];
yb = yb + x*(1-c)*Rb->data[1+0*R->nrows];
cb = cb - x*y*Rb->data[1+0*R->nrows];
zb = zb + s*Rb->data[1+0*R->nrows];
sb = sb + z*Rb->data[1+0*R->nrows];
Rb->data[1 + 0*R->nrows] = 0.0;
xb = xb + z*(1-c)*Rb->data[0+2*R->nrows];
zb = zb + x*(1-c)*Rb->data[0+2*R->nrows];
cb = cb - x*z*Rb->data[0+2*R->nrows];
yb = yb + s*Rb->data[0+2*R->nrows];
sb = sb + y*Rb->data[0+2*R->nrows];
Rb->data[0 + 2*R->nrows] = 0.0;
xb = xb + y*(1-c)*Rb->data[0+1*R->nrows];
yb = yb + x*(1-c)*Rb->data[0+1*R->nrows];
cb = cb - x*y*Rb->data[0+1*R->nrows];
zb = zb - s*Rb->data[0+1*R->nrows];
sb = sb - z*Rb->data[0+1*R->nrows];
Rb->data[0 + 1*R->nrows] = 0.0;
xb = xb + (2*x-2*x*c)*Rb->data[0+0*R->nrows];
cb = cb + (1-x*x)*Rb->data[0+0*R->nrows];
Rb->data[0 + 0*R->nrows] = 0.0;
normb = cos(norm)*sb - sin(norm)*cb - angle_axis[2]*zb/(norm*norm) -
angle_axis[1]*yb/(norm*norm) - angle_axis[0]*xb/(norm*norm);
angle_axisb[2] = angle_axisb[2] + zb/norm;
angle_axisb[1] = angle_axisb[1] + yb/norm;
angle_axisb[0] = angle_axisb[0] + xb/norm;
}
result1b = (result1 == 0.0 ? 0.0 : normb/(2.0*sqrt(result1)));
square_sum_b(3, angle_axis, angle_axisb, result1b);
}
/*========================================================================
MAIN LOGIC
========================================================================*/
void angle_axis_to_rotation_matrix_c(const double *angle_axis, Matrix *R) {
double norm;
double result1;
result1 = square_sum_c(3, angle_axis);
norm = sqrt(result1);
if (norm < 0.0001) {
set_identity_c(R);
return;
} else {
double x = angle_axis[0]/norm;
double y = angle_axis[1]/norm;
double z = angle_axis[2]/norm;
double s;
s = sin(norm);
double c;
c = cos(norm);
R->data[0 + 0*R->nrows] = x*x + (1-x*x)*c;
// first row
R->data[0 + 1*R->nrows] = x*y*(1-c) - z*s;
R->data[0 + 2*R->nrows] = x*z*(1-c) + y*s;
R->data[1 + 0*R->nrows] = x*y*(1-c) + z*s;
// second row
R->data[1 + 1*R->nrows] = y*y + (1-y*y)*c;
R->data[1 + 2*R->nrows] = y*z*(1-c) - x*s;
R->data[2 + 0*R->nrows] = x*z*(1-c) - y*s;
// third row
R->data[2 + 1*R->nrows] = z*y*(1-c) + x*s;
R->data[2 + 2*R->nrows] = z*z + (1-z*z)*c;
}
}
/*
Differentiation of apply_global_transform in reverse (adjoint) mode:
gradient of useful results: alloc(*(*mat.data)) *(alloc(*mat).data)
alloc(*(*mat.data)) *(alloc(*mat).data) *(*pose_params.data)
*(*positions.data)
with respect to varying inputs: alloc(*(*mat.data)) *(alloc(*mat).data)
alloc(*(*mat.data)) *(alloc(*mat).data) *(*pose_params.data)
*(*positions.data)
Plus diff mem management of: alloc(*mat).data:in-out alloc(*mat).data:in-out
pose_params:in *pose_params.data:in positions:in
*positions.data:in
*/
void apply_global_transform_b(const Matrix *pose_params, Matrix_diff *
pose_paramsb, Matrix *positions, Matrix_diff *positionsb) {
int i, j;
Matrix *R;
Matrix_diff *Rb;
int branch;
R = get_new_matrix_c(3, 3);
angle_axis_to_rotation_matrix_c(pose_params->data, R);
for (i = 0; i < 3; ++i)
for (j = 0; j < 3; ++j) {
pushReal8(R->data[j + i*R->nrows]);
R->data[j + i*R->nrows] = R->data[j+i*R->nrows]*pose_params->data[
i+1*pose_params->nrows];
}
Matrix *tmp;
Matrix_diff *tmpb;
tmp = get_new_empty_matrix_c();
pushInteger4(tmp->nrows);
pushInteger4(tmp->ncols);
if (tmp->data) {
pushReal8(*tmp->data);
pushControl1b(1);
} else
pushControl1b(0);
pushPointer8(tmp->data);
mat_mult_c(R, positions, tmp);
delete_matrix_b(tmp, tmpb);
delete_matrix_b(R, Rb);
for (j = positions->ncols-1; j > -1; --j)
for (i = positions->nrows-1; i > -1; --i) {
tmpb->data[i + j*tmp->nrows] = tmpb->data[i + j*tmp->nrows] +
positionsb->data[i + j*positions->nrows];
pose_paramsb->data[i + 2*pose_params->nrows] = pose_paramsb->data[
i + 2*pose_params->nrows] + positionsb->data[i + j*positions->
nrows];
positionsb->data[i + j*positions->nrows] = 0.0;
}
popPointer8((void **)&(tmp->data));
popControl1b(&branch);
if (branch == 1)
popReal8(tmp->data);
popInteger4(&(tmp->ncols));
popInteger4(&(tmp->nrows));
mat_mult_b(R, Rb, positions, positionsb, tmp, tmpb);
get_new_empty_matrix_b(tmpb);
for (i = 2; i > -1; --i)
for (j = 2; j > -1; --j) {
popReal8(&(R->data[j + i*R->nrows]));
pose_paramsb->data[i + 1*pose_params->nrows] = pose_paramsb->data[
i + 1*pose_params->nrows] + R->data[j+i*R->nrows]*Rb->data[j+i
*R->nrows];
Rb->data[j + i*R->nrows] = pose_params->data[i+1*pose_params->
nrows]*Rb->data[j+i*R->nrows];
}
angle_axis_to_rotation_matrix_b(pose_params->data, pose_paramsb->data, R,
Rb);
get_new_matrix_b(3, 3, Rb);
}
void apply_global_transform_c(const Matrix *pose_params, Matrix *positions) {
int i, j;
Matrix *R;
R = get_new_matrix_c(3, 3);
angle_axis_to_rotation_matrix_c(pose_params->data, R);
for (i = 0; i < 3; ++i)
for (j = 0; j < 3; ++j)
R->data[j + i*R->nrows] *= pose_params->data[i + 1*pose_params->
nrows];
Matrix *tmp;
tmp = get_new_empty_matrix_c();
mat_mult_c(R, positions, tmp);
for (j = 0; j < positions->ncols; ++j)
for (i = 0; i < positions->nrows; ++i)
positions->data[i + j*positions->nrows] = tmp->data[i + j*tmp->
nrows] + pose_params->data[i + 2*pose_params->nrows];
delete_matrix_c(R);
delete_matrix_c(tmp);
}
/*
Differentiation of relatives_to_absolutes in reverse (adjoint) mode:
gradient of useful results: alloc(*(*dst.data)) alloc(*(*mat.data))
*(*absolutes.data) *(*relatives.data)
with respect to varying inputs: alloc(*(*mat.data)) *(*absolutes.data)
*(*relatives.data)
Plus diff mem management of: absolutes:in *absolutes.data:out
relatives:in
*/
void relatives_to_absolutes_b(int count, const Matrix *relatives, Matrix_diff
*relativesb, const int *parents, Matrix *absolutes, Matrix_diff *
absolutesb) {
int i;
int branch;
for (i = 0; i < count; ++i)
if (parents[i] == -1) {
pushInteger4(absolutes[i].nrows);
pushInteger4(absolutes[i].ncols);
pushPointer8(absolutes[i].data);
copy_c(&(absolutes[i]), &(relatives[i]));
pushControl1b(1);
} else {
pushInteger4(absolutes[i].nrows);
pushInteger4(absolutes[i].ncols);
pushReal8(*absolutes[i].data);
pushPointer8(absolutes[i].data);
pushReal8(*absolutes[parents[i]].data);
mat_mult_c(&(absolutes[parents[i]]), &(relatives[i]), &(absolutes[
i]));
pushControl1b(0);
}
for (i = count-1; i > -1; --i) {
popControl1b(&branch);
if (branch == 0) {
popReal8(absolutes[parents[i]].data);
popPointer8((void **)&(absolutes[i].data));
popReal8(absolutes[i].data);
popInteger4(&(absolutes[i].ncols));
popInteger4(&(absolutes[i].nrows));
mat_mult_b(&(absolutes[parents[i]]), &(absolutesb[parents[i]]), &(
relatives[i]), &(relativesb[i]), &(absolutes[i]), &(
absolutesb[i]));
} else {
popPointer8((void **)&(absolutes[i].data));
popInteger4(&(absolutes[i].ncols));
popInteger4(&(absolutes[i].nrows));
copy_b(&(absolutes[i]), &(absolutesb[i]), &(relatives[i]), &(
relativesb[i]));
}
}
}
void relatives_to_absolutes_c(int count, const Matrix *relatives, const int *
parents, Matrix *absolutes) {
int i;
for (i = 0; i < count; ++i)
if (parents[i] == -1)
copy_c(&(absolutes[i]), &(relatives[i]));
else
mat_mult_c(&(absolutes[parents[i]]), &(relatives[i]), &(absolutes[
i]));
}
/*
Differentiation of euler_angles_to_rotation_matrix in reverse (adjoint) mode:
gradient of useful results: alloc(*(*mat.data)) *(alloc(*mat).data)
alloc(*(*mat.data)) *(alloc(*mat).data) *(*R.data)
with respect to varying inputs: alloc(*(*mat.data)) *(alloc(*mat).data)
alloc(*(*mat.data)) *(alloc(*mat).data) *(*R.data)
Plus diff mem management of: alloc(*mat).data:in-out alloc(*mat).data:in-out
R:in *R.data:in-out
*/
void euler_angles_to_rotation_matrix_b(const double *xzy, Matrix *R,
Matrix_diff *Rb) {
double tx = xzy[0];
double ty = xzy[2];
double tz = xzy[1];
Matrix *Rx;
Matrix_diff *Rxb;
double tmp0;
double tmpb;
double tmp1;
double tmpb0;
double tmp2;
double tmpb1;
double tmp3;
double tmpb2;
double tmp4;
double tmpb3;
double tmp5;
double tmpb4;
int branch;
Rx = get_new_matrix_c(3, 3);
Matrix *Ry;
Matrix_diff *Ryb;
Ry = get_new_matrix_c(3, 3);
Matrix *Rz;
Matrix_diff *Rzb;
Rz = get_new_matrix_c(3, 3);
set_identity_c(Rx);
Rx->data[1 + 1*Rx->nrows] = cos(tx);
Rx->data[2 + 1*Rx->nrows] = sin(tx);
tmp0 = -Rx->data[2+1*Rx->nrows];
Rx->data[1 + 2*Rx->nrows] = tmp0;
tmp1 = Rx->data[1 + 1*Rx->nrows];
Rx->data[2 + 2*Rx->nrows] = tmp1;
set_identity_c(Ry);
Ry->data[0 + 0*Ry->nrows] = cos(ty);
Ry->data[0 + 2*Ry->nrows] = sin(ty);
tmp2 = -Ry->data[0+2*Ry->nrows];
Ry->data[2 + 0*Ry->nrows] = tmp2;
tmp3 = Ry->data[0 + 0*Ry->nrows];
Ry->data[2 + 2*Ry->nrows] = tmp3;
set_identity_c(Rz);
Rz->data[0 + 0*Rz->nrows] = cos(tz);
Rz->data[1 + 0*Rz->nrows] = sin(tz);
tmp4 = -Rz->data[1+0*Rz->nrows];
Rz->data[0 + 1*Rz->nrows] = tmp4;
tmp5 = Rz->data[0 + 0*Rz->nrows];
Rz->data[1 + 1*Rz->nrows] = tmp5;
Matrix *tmp;
Matrix_diff *tmpb5;
tmp = get_new_empty_matrix_c();
pushInteger4(tmp->nrows);
pushInteger4(tmp->ncols);
if (tmp->data) {
pushReal8(*tmp->data);
pushControl1b(1);
} else
pushControl1b(0);
pushPointer8(tmp->data);
mat_mult_c(Rz, Ry, tmp);
delete_matrix_b(tmp, tmpb5);
delete_matrix_b(Rz, Rzb);
delete_matrix_b(Ry, Ryb);
delete_matrix_b(Rx, Rxb);
mat_mult_b(tmp, tmpb5, Rx, Rxb, R, Rb);
popPointer8((void **)&(tmp->data));
popControl1b(&branch);
if (branch == 1)
popReal8(tmp->data);
popInteger4(&(tmp->ncols));
popInteger4(&(tmp->nrows));
mat_mult_b(Rz, Rzb, Ry, Ryb, tmp, tmpb5);
get_new_empty_matrix_b(tmpb5);
tmpb4 = Rzb->data[1 + 1*Rz->nrows];
Rzb->data[1 + 1*Rz->nrows] = 0.0;
Rzb->data[0 + 0*Rz->nrows] = Rzb->data[0 + 0*Rz->nrows] + tmpb4;
tmpb3 = Rzb->data[0 + 1*Rz->nrows];
Rzb->data[0 + 1*Rz->nrows] = 0.0;
Rzb->data[1 + 0*Rz->nrows] = 0.0;
Rzb->data[0 + 0*Rz->nrows] = 0.0;
set_identity_b(Rz, Rzb);
tmpb2 = Ryb->data[2 + 2*Ry->nrows];
Ryb->data[2 + 2*Ry->nrows] = 0.0;
Ryb->data[0 + 0*Ry->nrows] = Ryb->data[0 + 0*Ry->nrows] + tmpb2;
tmpb1 = Ryb->data[2 + 0*Ry->nrows];
Ryb->data[2 + 0*Ry->nrows] = 0.0;
Ryb->data[0 + 2*Ry->nrows] = 0.0;
Ryb->data[0 + 0*Ry->nrows] = 0.0;
set_identity_b(Ry, Ryb);
tmpb0 = Rxb->data[2 + 2*Rx->nrows];
Rxb->data[2 + 2*Rx->nrows] = 0.0;
Rxb->data[1 + 1*Rx->nrows] = Rxb->data[1 + 1*Rx->nrows] + tmpb0;
tmpb = Rxb->data[1 + 2*Rx->nrows];
Rxb->data[1 + 2*Rx->nrows] = 0.0;
Rxb->data[2 + 1*Rx->nrows] = 0.0;
Rxb->data[1 + 1*Rx->nrows] = 0.0;
set_identity_b(Rx, Rxb);
get_new_matrix_b(3, 3, Rzb);
get_new_matrix_b(3, 3, Ryb);
get_new_matrix_b(3, 3, Rxb);
}
void euler_angles_to_rotation_matrix_c(const double *xzy, Matrix *R) {
double tx = xzy[0];
double ty = xzy[2];
double tz = xzy[1];
Matrix *Rx;
Rx = get_new_matrix_c(3, 3);
Matrix *Ry;
Ry = get_new_matrix_c(3, 3);
Matrix *Rz;
Rz = get_new_matrix_c(3, 3);
set_identity_c(Rx);
Rx->data[1 + 1*Rx->nrows] = cos(tx);
Rx->data[2 + 1*Rx->nrows] = sin(tx);
Rx->data[1 + 2*Rx->nrows] = -Rx->data[2+1*Rx->nrows];
Rx->data[2 + 2*Rx->nrows] = Rx->data[1 + 1*Rx->nrows];
set_identity_c(Ry);
Ry->data[0 + 0*Ry->nrows] = cos(ty);
Ry->data[0 + 2*Ry->nrows] = sin(ty);
Ry->data[2 + 0*Ry->nrows] = -Ry->data[0+2*Ry->nrows];
Ry->data[2 + 2*Ry->nrows] = Ry->data[0 + 0*Ry->nrows];
set_identity_c(Rz);
Rz->data[0 + 0*Rz->nrows] = cos(tz);
Rz->data[1 + 0*Rz->nrows] = sin(tz);
Rz->data[0 + 1*Rz->nrows] = -Rz->data[1+0*Rz->nrows];
Rz->data[1 + 1*Rz->nrows] = Rz->data[0 + 0*Rz->nrows];
Matrix *tmp;
tmp = get_new_empty_matrix_c();
mat_mult_c(Rz, Ry, tmp);
mat_mult_c(tmp, Rx, R);
delete_matrix_c(Rx);
delete_matrix_c(Ry);
delete_matrix_c(Rz);
delete_matrix_c(tmp);
}
/*
Differentiation of get_posed_relatives in reverse (adjoint) mode:
gradient of useful results: alloc(*(*mat.data)) *(alloc(*mat).data)
alloc(*(*mat.data)) *(alloc(*mat).data) *(*relatives.data)
with respect to varying inputs: alloc(*(*mat.data)) *(alloc(*mat).data)
Plus diff mem management of: alloc(*mat).data:in-out alloc(*mat).data:in-out
*pose_params.data:in base_relatives:in relatives:in
*/
void get_posed_relatives_b(int bone_count, const Matrix *base_relatives,
Matrix_diff *base_relativesb, const Matrix *pose_params, Matrix_diff *
pose_paramsb, Matrix *relatives, Matrix_diff *relativesb) {
int i;
int offset = 3;
Matrix *tr;
Matrix_diff *trb;
double* arg1;
int branch;
tr = get_new_matrix_c(4, 4);
Matrix *R;
Matrix_diff *Rb;
R = get_new_matrix_c(3, 3);
for (i = 0; i < bone_count; ++i) {
set_identity_c(tr);
arg1 = pose_params->data + (i+offset)*pose_params->nrows;
if (arg1) {
pushReal8(*arg1);
pushControl1b(1);
} else
pushControl1b(0);
pushInteger4(R->nrows);
pushInteger4(R->ncols);
if (R->data) {
pushReal8(*R->data);
pushControl1b(1);
} else
pushControl1b(0);
pushPointer8(R->data);
euler_angles_to_rotation_matrix_c(arg1, R);
set_block_c(tr, 0, 0, R);
pushInteger4(relatives[i].nrows);
pushInteger4(relatives[i].ncols);
pushReal8(*relatives[i].data);
pushPointer8(relatives[i].data);
if (tr->data) {
pushReal8(*tr->data);
pushControl1b(1);
} else
pushControl1b(0);
mat_mult_c(&(base_relatives[i]), tr, &(relatives[i]));
}
delete_matrix_b(R, Rb);
delete_matrix_b(tr, trb);
for (i = bone_count-1; i > -1; --i) {
popControl1b(&branch);
if (branch == 1)
popReal8(tr->data);
popPointer8((void **)&(relatives[i].data));
popReal8(relatives[i].data);
popInteger4(&(relatives[i].ncols));
popInteger4(&(relatives[i].nrows));
*base_relativesb->data = 0.0;
mat_mult_b(&(base_relatives[i]), &(base_relativesb[i]), tr, trb, &(
relatives[i]), &(relativesb[i]));
set_block_b(tr, trb, 0, 0, R, Rb);
arg1 = pose_params->data + (i+offset)*pose_params->nrows;
popPointer8((void **)&(R->data));
popControl1b(&branch);
if (branch == 1)
popReal8(R->data);
popInteger4(&(R->ncols));
popInteger4(&(R->nrows));
euler_angles_to_rotation_matrix_b(arg1, R, Rb);
popControl1b(&branch);
if (branch == 1)
popReal8(arg1);
set_identity_b(tr, trb);
}
get_new_matrix_b(3, 3, Rb);
get_new_matrix_b(4, 4, trb);
}
void get_posed_relatives_c(int bone_count, const Matrix *base_relatives, const
Matrix *pose_params, Matrix *relatives) {
int i;
int offset = 3;
Matrix *tr;
double* arg1;
tr = get_new_matrix_c(4, 4);
Matrix *R;
R = get_new_matrix_c(3, 3);
for (i = 0; i < bone_count; ++i) {
set_identity_c(tr);
arg1 = pose_params->data + (i+offset)*pose_params->nrows;
euler_angles_to_rotation_matrix_c(arg1, R);
set_block_c(tr, 0, 0, R);
mat_mult_c(&(base_relatives[i]), tr, &(relatives[i]));
}
delete_matrix_c(tr);
delete_matrix_c(R);
}
/*
Differentiation of get_skinned_vertex_positions in reverse (adjoint) mode:
gradient of useful results: alloc(*(*mat.data)) *(alloc(*mat).data)
*(*pose_params.data) *(*positions.data)
with respect to varying inputs: alloc(*(*mat.data)) *(alloc(*mat).data)
*(*pose_params.data) *(*positions.data)
Plus diff mem management of: alloc(*mat).data:in-out alloc(*mat).data:in-out
pose_params:in *pose_params.data:in base_positions:in
*base_positions.data:in positions:in *positions.data:in-out
inverse_base_absolutes:in
*/
void get_skinned_vertex_positions_b(int bone_count, const Matrix *
base_relatives, const int *parents, const Matrix *
inverse_base_absolutes, Matrix_diff *inverse_base_absolutesb, const
Matrix *base_positions, Matrix_diff *base_positionsb, const Matrix *
weights, int is_mirrored, const Matrix *pose_params, Matrix_diff *
pose_paramsb, Matrix *positions, Matrix_diff *positionsb, int
apply_global) {
int i;
Matrix *relatives;
Matrix_diff *relativesb;
int branch;
double tmp;
double tmpb;
Matrix_diff *base_relativesb;
relatives = get_matrix_array_c(bone_count);
Matrix *absolutes;
Matrix_diff *absolutesb;
absolutes = get_matrix_array_c(bone_count);
Matrix *transforms;
Matrix_diff *transformsb;
pushInteger4(relatives->nrows);
pushInteger4(relatives->ncols);
if (relatives->data) {
pushReal8(*relatives->data);
pushControl1b(1);
} else
pushControl1b(0);
pushPointer8(relatives->data);
get_posed_relatives_c(bone_count, base_relatives, pose_params, relatives);
pushInteger4(absolutes->nrows);
pushInteger4(absolutes->ncols);
if (absolutes->data) {
pushReal8(*absolutes->data);
pushControl1b(1);
} else
pushControl1b(0);
pushPointer8(absolutes->data);
if (relatives->data) {
pushReal8(*relatives->data);
pushControl1b(1);
} else
pushControl1b(0);
relatives_to_absolutes_c(bone_count, relatives, parents, absolutes);
// Get bone transforms->
for (i = 0; i < bone_count; ++i) {
pushInteger4(transforms[i].nrows);
pushInteger4(transforms[i].ncols);
if (transforms[i].data) {
pushReal8(*transforms[i].data);
pushControl1b(1);
} else
pushControl1b(0);
pushPointer8(transforms[i].data);
if (absolutes[i].data) {
pushReal8(*absolutes[i].data);
pushControl1b(1);
} else
pushControl1b(0);
mat_mult_c(&(absolutes[i]), &(inverse_base_absolutes[i]), &(transforms
[i]));
}
// Transform vertices by necessary transforms-> + apply skinning
resize_c(positions, 3, base_positions->ncols);
fill_c(positions, 0.0);
Matrix *curr_positions;
Matrix_diff *curr_positionsb;
curr_positions = get_new_matrix_c(4, base_positions->ncols);
int i_bone, i_vert;
for (i_bone = 0; i_bone < bone_count; ++i_bone) {
pushInteger4(curr_positions->nrows);
pushInteger4(curr_positions->ncols);
if (curr_positions->data) {
pushReal8(*curr_positions->data);
pushControl1b(1);
} else
pushControl1b(0);
pushPointer8(curr_positions->data);
if (transforms[i_bone].data) {
pushReal8(*transforms[i_bone].data);
pushControl1b(1);
} else
pushControl1b(0);
mat_mult_c(&(transforms[i_bone]), base_positions, curr_positions);
for (i_vert = 0; i_vert < positions->ncols; ++i_vert)
for (i = 0; i < 3; ++i) {
tmp = positions->data[i + i_vert*positions->nrows] +
curr_positions->data[i+i_vert*curr_positions->nrows]*
weights->data[i_bone+i_vert*weights->nrows];
positions->data[i + i_vert*positions->nrows] = tmp;
}
}
if (is_mirrored) {
for (i = 0; i < positions->ncols; ++i)
positions->data[0 + i*positions->nrows] = positions->data[0+i*
positions->nrows]*-1;
pushControl1b(0);
} else
pushControl1b(1);
if (apply_global)
pushControl1b(0);
else
pushControl1b(1);
delete_light_matrix_array_b(transforms, transformsb, bone_count);
delete_light_matrix_array_b(absolutes, absolutesb, bone_count);
delete_light_matrix_array_b(relatives, relativesb, bone_count);
delete_matrix_b(curr_positions, curr_positionsb);
popControl1b(&branch);
if (branch == 0)
apply_global_transform_b(pose_params, pose_paramsb, positions,
positionsb);
popControl1b(&branch);
if (branch == 0)
for (i = positions->ncols-1; i > -1; --i)
positionsb->data[0 + i*positions->nrows] = -positionsb->data[0+i*
positions->nrows];
for (i_bone = bone_count-1; i_bone > -1; --i_bone) {
for (i_vert = positions->ncols-1; i_vert > -1; --i_vert)
for (i = 2; i > -1; --i) {
tmpb = positionsb->data[i + i_vert*positions->nrows];
positionsb->data[i + i_vert*positions->nrows] = tmpb;
curr_positionsb->data[i + i_vert*curr_positions->nrows] =
curr_positionsb->data[i + i_vert*curr_positions->nrows] +
weights->data[i_bone+i_vert*weights->nrows]*tmpb;
}
popControl1b(&branch);
if (branch == 1)
popReal8(transforms[i_bone].data);
popPointer8((void **)&(curr_positions->data));
popControl1b(&branch);
if (branch == 1)
popReal8(curr_positions->data);
popInteger4(&(curr_positions->ncols));
popInteger4(&(curr_positions->nrows));
*base_positionsb->data = 0.0;
mat_mult_b(&(transforms[i_bone]), &(transformsb[i_bone]),
base_positions, base_positionsb, curr_positions,
curr_positionsb);
}
get_new_matrix_b(4, base_positions->ncols, curr_positionsb);
fill_b(positions, positionsb, 0.0);
resize_b(positions, positionsb, 3, base_positions->ncols);
for (i = bone_count-1; i > -1; --i) {
popControl1b(&branch);
if (branch == 1)
popReal8(absolutes[i].data);
popPointer8((void **)&(transforms[i].data));
popControl1b(&branch);
if (branch == 1)
popReal8(transforms[i].data);
popInteger4(&(transforms[i].ncols));
popInteger4(&(transforms[i].nrows));
*inverse_base_absolutesb->data = 0.0;
mat_mult_b(&(absolutes[i]), &(absolutesb[i]), &(inverse_base_absolutes
[i]), &(inverse_base_absolutesb[i]), &(transforms[i]), &(
transformsb[i]));
}
popControl1b(&branch);
if (branch == 1)
popReal8(relatives->data);
popPointer8((void **)&(absolutes->data));
popControl1b(&branch);
if (branch == 1)
popReal8(absolutes->data);
popInteger4(&(absolutes->ncols));
popInteger4(&(absolutes->nrows));
relatives_to_absolutes_b(bone_count, relatives, relativesb, parents,
absolutes, absolutesb);
popPointer8((void **)&(relatives->data));
popControl1b(&branch);
if (branch == 1)
popReal8(relatives->data);
popInteger4(&(relatives->ncols));
popInteger4(&(relatives->nrows));
get_posed_relatives_b(bone_count, base_relatives, base_relativesb,
pose_params, pose_paramsb, relatives, relativesb);
get_matrix_array_b(bone_count, transformsb);
get_matrix_array_b(bone_count, absolutesb);
}
void get_skinned_vertex_positions_c(int bone_count, const Matrix *
base_relatives, const int *parents, const Matrix *
inverse_base_absolutes, const Matrix *base_positions, const Matrix *
weights, int is_mirrored, const Matrix *pose_params, Matrix *positions
, int apply_global) {
int i;
Matrix *relatives;
relatives = get_matrix_array_c(bone_count);
Matrix *absolutes;
absolutes = get_matrix_array_c(bone_count);
Matrix *transforms;
transforms = get_matrix_array_c(bone_count);
get_posed_relatives_c(bone_count, base_relatives, pose_params, relatives);
relatives_to_absolutes_c(bone_count, relatives, parents, absolutes);
// Get bone transforms->
for (i = 0; i < bone_count; ++i)
mat_mult_c(&(absolutes[i]), &(inverse_base_absolutes[i]), &(transforms
[i]));
// Transform vertices by necessary transforms-> + apply skinning
resize_c(positions, 3, base_positions->ncols);
fill_c(positions, 0.0);
Matrix *curr_positions;
curr_positions = get_new_matrix_c(4, base_positions->ncols);
int i_bone, i_vert;
for (i_bone = 0; i_bone < bone_count; ++i_bone) {
mat_mult_c(&(transforms[i_bone]), base_positions, curr_positions);
for (i_vert = 0; i_vert < positions->ncols; ++i_vert)
for (i = 0; i < 3; ++i)
positions->data[i + i_vert*positions->nrows] += curr_positions
->data[i+i_vert*curr_positions->nrows]*weights->data[i_bone+
i_vert*weights->nrows];
}
if (is_mirrored)
for (i = 0; i < positions->ncols; ++i)
positions->data[0 + i*positions->nrows] *= -1;
if (apply_global)
apply_global_transform_c(pose_params, positions);
delete_matrix_c(curr_positions);
delete_light_matrix_array_c(relatives, bone_count);
delete_light_matrix_array_c(absolutes, bone_count);
delete_light_matrix_array_c(transforms, bone_count);
}
/*
Differentiation of to_pose_params in reverse (adjoint) mode:
gradient of useful results: alloc(*(*mat.data)) *(*pose_params.data)
with respect to varying inputs: *theta
Plus diff mem management of: pose_params:in *pose_params.data:in-out
theta:in
*/
//% !!!!!!! fixed order pose_params !!!!!
//% 1) global_rotation 2) scale 3) global_translation
//% 4) wrist
//% 5) thumb1, 6)thumb2, 7) thumb3, 8) thumb4
//% similarly: index, middle, ring, pinky
//% end) forearm
void to_pose_params_b(int count, const double *theta, double *thetab, const
char **bone_names, Matrix *pose_params, Matrix_diff *pose_paramsb) {
int i;
int arg1;
int branch;
arg1 = count + 3;
resize_c(pose_params, 3, arg1);
for (i = 0; i < pose_params->nrows; ++i) {
pose_params->data[i] = theta[i];
pose_params->data[i + 1*pose_params->nrows] = 1.0;
}
int i_theta = 6;
int i_pose_params = 5;
int n_fingers = 5;
int i_finger;
for (i_finger = 0; i_finger < n_fingers; ++i_finger) {
for (i = 2; i < 5; ++i) {
pose_params->data[0 + i_pose_params*pose_params->nrows] = theta[
i_theta];
i_theta++;
if (i == 2) {
pose_params->data[1 + i_pose_params*pose_params->nrows] =
theta[i_theta];
i_theta++;
pushControl1b(0);
} else
pushControl1b(1);
i_pose_params++;
}
i_pose_params++;
}
*thetab = 0.0;
for (i_finger = n_fingers-1; i_finger > -1; --i_finger) {
--i_pose_params;
for (i = 4; i > 1; --i) {
--i_pose_params;
popControl1b(&branch);
if (branch == 0) {
--i_theta;
thetab[i_theta] = thetab[i_theta] + pose_paramsb->data[1 +
i_pose_params*pose_params->nrows];
pose_paramsb->data[1 + i_pose_params*pose_params->nrows] = 0.0
;
}
--i_theta;
thetab[i_theta] = thetab[i_theta] + pose_paramsb->data[0 +
i_pose_params*pose_params->nrows];
pose_paramsb->data[0 + i_pose_params*pose_params->nrows] = 0.0;
}
}
for (i = pose_params->nrows-1; i > -1; --i) {
thetab[i + 3] = thetab[i + 3] + pose_paramsb->data[i + 2*pose_params->
nrows];
pose_paramsb->data[i + 2*pose_params->nrows] = 0.0;
pose_paramsb->data[i + 1*pose_params->nrows] = 0.0;
thetab[i] = thetab[i] + pose_paramsb->data[i];
pose_paramsb->data[i] = 0.0;
}
resize_b(pose_params, pose_paramsb, 3, arg1);
}
//% !!!!!!! fixed order pose_params !!!!!
//% 1) global_rotation 2) scale 3) global_translation
//% 4) wrist
//% 5) thumb1, 6)thumb2, 7) thumb3, 8) thumb4
//% similarly: index, middle, ring, pinky
//% end) forearm
void to_pose_params_c(int count, const double *theta, const char **bone_names,
Matrix *pose_params) {
int i;
int arg1;
arg1 = count + 3;
resize_c(pose_params, 3, arg1);
fill_c(pose_params, 0.0);
for (i = 0; i < pose_params->nrows; ++i) {
pose_params->data[i] = theta[i];
pose_params->data[i + 1*pose_params->nrows] = 1.0;
pose_params->data[i + 2*pose_params->nrows] = theta[i + 3];
}
int i_theta = 6;
int i_pose_params = 5;
int n_fingers = 5;
int i_finger;
for (i_finger = 0; i_finger < n_fingers; ++i_finger) {
for (i = 2; i < 5; ++i) {
pose_params->data[0 + i_pose_params*pose_params->nrows] = theta[
i_theta];
i_theta++;
if (i == 2) {
pose_params->data[1 + i_pose_params*pose_params->nrows] =
theta[i_theta];
i_theta++;
}
i_pose_params++;
}
i_pose_params++;
}
}
/*
Differentiation of hand_objective in reverse (adjoint) mode:
gradient of useful results: *err
with respect to varying inputs: *err *theta
RW status of diff variables: *err:in-out *theta:out
Plus diff mem management of: alloc(*mat).data:in-out alloc(*mat).data:in-out
err:in base_positions:in *base_positions.data:in
theta:in
*/
void hand_objective_b(const double *theta, double *thetab, int bone_count,
const char **bone_names, const int *parents, Matrix *base_relatives,
Matrix *inverse_base_absolutes, Matrix *base_positions, Matrix *weights, const Triangle *triangles, int
is_mirrored, int corresp_count, const int *correspondences, Matrix *
points, double *err, double *errb) {
Matrix_diff *base_positionsb;
Matrix *pose_params;
Matrix_diff *pose_paramsb;
int branch;
Matrix_diff *inverse_base_absolutesb;
pose_params = get_new_empty_matrix_c();
pushInteger4(pose_params->nrows);
pushInteger4(pose_params->ncols);
pushPointer8(pose_params->data);
to_pose_params_c(bone_count, theta, bone_names, pose_params);
Matrix *vertex_positions;
Matrix_diff *vertex_positionsb;
vertex_positions = get_new_empty_matrix_c();
pushInteger4(vertex_positions->nrows);
pushInteger4(vertex_positions->ncols);
if (vertex_positions->data) {
pushReal8(*vertex_positions->data);
pushControl1b(1);
} else
pushControl1b(0);
pushPointer8(vertex_positions->data);
pushInteger4(pose_params->nrows);
pushInteger4(pose_params->ncols);
if (pose_params->data) {
pushReal8(*pose_params->data);
pushControl1b(1);
} else
pushControl1b(0);
pushPointer8(pose_params->data);
get_skinned_vertex_positions_c(bone_count, base_relatives, parents,
inverse_base_absolutes, base_positions,
weights, is_mirrored, pose_params,
vertex_positions, 1);
int i, j;
delete_matrix_b(vertex_positions, vertex_positionsb);
delete_matrix_b(pose_params, pose_paramsb);
for (i = corresp_count-1; i > -1; --i)
for (j = 2; j > -1; --j) {
vertex_positionsb->data[j + correspondences[i]*vertex_positions->
nrows] = vertex_positionsb->data[j + correspondences[i]*
vertex_positions->nrows] - errb[i*3 + j];
errb[i*3 + j] = 0.0;
}
popPointer8((void **)&(pose_params->data));
popControl1b(&branch);
if (branch == 1)
popReal8(pose_params->data);
popInteger4(&(pose_params->ncols));
popInteger4(&(pose_params->nrows));
popPointer8((void **)&(vertex_positions->data));
popControl1b(&branch);
if (branch == 1)
popReal8(vertex_positions->data);
popInteger4(&(vertex_positions->ncols));
popInteger4(&(vertex_positions->nrows));
get_skinned_vertex_positions_b(bone_count, base_relatives, parents,
inverse_base_absolutes,
inverse_base_absolutesb, base_positions,
base_positionsb, weights, is_mirrored,
pose_params, pose_paramsb, vertex_positions
, vertex_positionsb, 1);
get_new_empty_matrix_b(vertex_positionsb);
popPointer8((void **)&(pose_params->data));
popInteger4(&(pose_params->ncols));
popInteger4(&(pose_params->nrows));
to_pose_params_b(bone_count, theta, thetab, bone_names, pose_params,
pose_paramsb);
get_new_empty_matrix_b(pose_paramsb);
}
}
#endif