diff --git a/xs/src/libslic3r/TransformationMatrix.cpp b/xs/src/libslic3r/TransformationMatrix.cpp new file mode 100644 index 000000000..46508a37e --- /dev/null +++ b/xs/src/libslic3r/TransformationMatrix.cpp @@ -0,0 +1,332 @@ +//#define Testumgebung +//#include +//enum Axis { X = 0, Y, Z }; +// +//void CONFESS(std::string content) {}; +// +// +#include "TransformationMatrix.hpp" +#include +#include + +#ifdef SLIC3R_DEBUG +#include "SVG.hpp" +#endif + +namespace Slic3r { + + TransformationMatrix::TransformationMatrix() + { + *this = mat_eye(); + } + + TransformationMatrix::TransformationMatrix(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34) + { + this->m11 = m11; this->m12 = m12; this->m13 = m13; this->m14 = m14; + this->m21 = m21; this->m22 = m22; this->m23 = m23; this->m21 = m24; + this->m31 = m31; this->m32 = m32; this->m33 = m33; this->m34 = m34; + } +#ifndef Testumgebung + TransformationMatrix::TransformationMatrix(std::vector &entries_row_maj) + { + if (entries_row_maj.size() != 12) + { + *this = mat_eye(); + CONFESS("Invalid number of entries when initalizing TransformationMatrix. Vector length must be 12."); + return; + } + m11 = entries_row_maj[0]; m12 = entries_row_maj[1]; m13 = entries_row_maj[2]; m14 = entries_row_maj[3]; + m21 = entries_row_maj[4]; m22 = entries_row_maj[5]; m23 = entries_row_maj[6]; m24 = entries_row_maj[7]; + m31 = entries_row_maj[8]; m32 = entries_row_maj[9]; m33 = entries_row_maj[10]; m34 = entries_row_maj[11]; + } +#endif + TransformationMatrix::TransformationMatrix(const TransformationMatrix &other) + { + this->m11 = other.m11; this->m12 = other.m12; this->m13 = other.m13; this->m14 = other.m14; + this->m11 = other.m11; this->m22 = other.m22; this->m23 = other.m23; this->m24 = other.m24; + this->m31 = other.m31; this->m32 = other.m32; this->m33 = other.m33; this->m34 = other.m34; + } + + TransformationMatrix& TransformationMatrix::operator= (TransformationMatrix other) + { + this->swap(other); + return *this; + } + + void + TransformationMatrix::swap(TransformationMatrix &other) + { + std::swap(this->m11, other.m11); std::swap(this->m12, other.m12); + std::swap(this->m13, other.m13); std::swap(this->m14, other.m14); + std::swap(this->m21, other.m21); std::swap(this->m22, other.m22); + std::swap(this->m23, other.m23); std::swap(this->m24, other.m24); + std::swap(this->m31, other.m31); std::swap(this->m32, other.m32); + std::swap(this->m33, other.m33); std::swap(this->m34, other.m34); + } + + float* TransformationMatrix::matrix3x4f() + { + float mat[12]; + mat[0] = this->m11; mat[1] = this->m12; mat[2] = this->m13; mat[3] = this->m14; + mat[4] = this->m21; mat[5] = this->m22; mat[6] = this->m23; mat[7] = this->m24; + mat[8] = this->m31; mat[9] = this->m32; mat[10] = this->m33; mat[11] = this->m34; + return mat; + } + + float TransformationMatrix::determinante() + { + // translation elements don't influence the determinante + // because of the 0s on the other side of main diagonal + return m11*(m22*m33 - m23*m32) - m12*(m21*m33 - m23*m31) + m13*(m21*m32 - m31*m22); + } + + bool TransformationMatrix::inverse(TransformationMatrix* inverse) + { + // from http://mathworld.wolfram.com/MatrixInverse.html + // and https://math.stackexchange.com/questions/152462/inverse-of-transformation-matrix + TransformationMatrix mat; + float det = this->determinante(); + if (abs(det) < 1e-9) + return false; + float fac = 1.0f / det; + + mat.m11 = fac*(this->m22*this->m33 - this->m23*this->m32); + mat.m12 = fac*(this->m13*this->m32 - this->m12*this->m33); + mat.m13 = fac*(this->m12*this->m23 - this->m13*this->m22); + mat.m21 = fac*(this->m23*this->m31 - this->m21*this->m33); + mat.m22 = fac*(this->m11*this->m33 - this->m13*this->m31); + mat.m23 = fac*(this->m13*this->m21 - this->m11*this->m23); + mat.m31 = fac*(this->m21*this->m32 - this->m22*this->m31); + mat.m32 = fac*(this->m12*this->m31 - this->m11*this->m32); + mat.m33 = fac*(this->m11*this->m22 - this->m12*this->m21); + + mat.m14 = -(mat.m11*this->m14 + mat.m12*this->m24 + mat.m13*this->m34); + mat.m24 = -(mat.m21*this->m14 + mat.m22*this->m24 + mat.m23*this->m34); + mat.m34 = -(mat.m31*this->m14 + mat.m32*this->m24 + mat.m33*this->m34); + + inverse = &mat; + return true; + } + + void TransformationMatrix::translate(float x, float y, float z) + { + TransformationMatrix mat = mat_translation(x, y, z); + this->multiplyLeft(mat); + } + + void TransformationMatrix::scale(float factor) + { + this->scale(factor, factor, factor); + } + + void TransformationMatrix::scale(float x, float y, float z) + { + TransformationMatrix mat = mat_scale(x, y, z); + this->multiplyLeft(mat); + } + + void TransformationMatrix::mirror(const Axis &axis) + { + TransformationMatrix mat = mat_mirror(axis); + this->multiplyLeft(mat); + } + + void TransformationMatrix::mirror(const Pointf3 & normal) + { + TransformationMatrix mat = mat_mirror(normal); + this->multiplyLeft(mat); + } + + void TransformationMatrix::rotate(float angle_rad, const Axis & axis) + { + TransformationMatrix mat = mat_rotation(angle_rad, axis); + this->multiplyLeft(mat); + } + + void TransformationMatrix::rotate(float angle_rad, const Pointf3 & axis) + { + TransformationMatrix mat = mat_rotation(angle_rad, axis); + this->multiplyLeft(mat); + } + + void TransformationMatrix::rotate(float q1, float q2, float q3, float q4) + { + TransformationMatrix mat = mat_rotation(q1, q2, q3, q4); + this->multiplyLeft(mat); + } + + void TransformationMatrix::multiplyLeft(TransformationMatrix &left) + { + *this = multiply(left, *this); + } + + void TransformationMatrix::multiplyRight(TransformationMatrix &right) + { + *this = multiply(*this, right); + } + + TransformationMatrix TransformationMatrix::multiply(const TransformationMatrix &left, const TransformationMatrix &right) + { + TransformationMatrix trafo; + + trafo.m11 = left.m11*right.m11 + left.m12*right.m21 + left.m13 + right.m31; + trafo.m12 = left.m11*right.m12 + left.m12*right.m22 + left.m13 + right.m32; + trafo.m13 = left.m11*right.m13 + left.m12*right.m23 + left.m13 + right.m33; + trafo.m14 = left.m11*right.m14 + left.m12*right.m24 + left.m13 + right.m34 + left.m14; + + trafo.m21 = left.m21*right.m11 + left.m22*right.m21 + left.m23 + right.m31; + trafo.m22 = left.m21*right.m12 + left.m22*right.m22 + left.m23 + right.m32; + trafo.m23 = left.m21*right.m13 + left.m22*right.m23 + left.m23 + right.m33; + trafo.m24 = left.m21*right.m14 + left.m22*right.m24 + left.m23 + right.m34 + left.m24; + + trafo.m31 = left.m31*right.m11 + left.m32*right.m21 + left.m33 + right.m31; + trafo.m32 = left.m31*right.m12 + left.m32*right.m22 + left.m33 + right.m32; + trafo.m33 = left.m31*right.m13 + left.m32*right.m23 + left.m33 + right.m33; + trafo.m34 = left.m31*right.m14 + left.m32*right.m24 + left.m33 + right.m34 + left.m34; + + return trafo; + } + + TransformationMatrix TransformationMatrix::mat_eye() + { + return TransformationMatrix( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f); + } + + TransformationMatrix TransformationMatrix::mat_translation(float x, float y, float z) + { + return TransformationMatrix( + 1.0f, 0.0f, 0.0f, x, + 0.0f, 1.0f, 0.0f, y, + 0.0f, 0.0f, 1.0f, z); + } + + TransformationMatrix TransformationMatrix::mat_scale(float x, float y, float z) + { + return TransformationMatrix( + x, 0.0f, 0.0f, 0.0f, + 0.0f, y, 0.0f, 0.0f, + 0.0f, 0.0f, z, 0.0f); + } + + TransformationMatrix TransformationMatrix::mat_scale(float scale) + { + return TransformationMatrix::mat_scale(scale, scale, scale); + } + + TransformationMatrix TransformationMatrix::mat_rotation(float angle_rad, const Axis &axis) + { + float s = sin(angle_rad); + float c = cos(angle_rad); + TransformationMatrix mat; // For RVO + switch (axis) + { + case X: + mat = TransformationMatrix( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, c, s, 0.0f, + 0.0f, -s, c, 0.0f); + break; + case Y: + mat = TransformationMatrix( + c, 0.0f, -s, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + s, 0.0f, c, 0.0f); + break; + case Z: + mat = TransformationMatrix( + c, s, 0.0f, 0.0f, + -s, c, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f); + break; + default: + CONFESS("Invalid Axis supplied to TransformationMatrix::mat_rotation"); + mat = TransformationMatrix(); + break; + } + return mat; + } + + TransformationMatrix TransformationMatrix::mat_rotation(float q1, float q2, float q3, float q4) + { + float factor = q1*q1 + q2*q2 + q3*q3 + q4*q4; + if (abs(factor - 1.0f) > 1e-9) + { + factor = 1.0f / sqrtf(factor); + q1 *= factor; + q2 *= factor; + q3 *= factor; + q4 *= factor; + } + // https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Quaternion-derived_rotation_matrix + return TransformationMatrix( + 1 - 2 * (q2*q2 + q3*q3), 2 * (q1*q2 - q3*q4), 2 * (q1*q3 + q2*q4), 0.0f, + 2 * (q1*q2 + q3*q4), 1 - 2 * (q1*q1 + q3*q3), 2 * (q2*q3 - q1*q4), 0.0f, + 2 * (q1*q3 - q2*q4), 2 * (q2*q3 + q1*q4), 1 - 2 * (q1*q1 + q2*q2), 0.0f); + } + + TransformationMatrix TransformationMatrix::mat_rotation(float angle_rad, const Pointf3 &axis) + { + float s, factor, q1, q2, q3, q4; + s = sin(angle_rad); + TransformationMatrix mat; // For RVO + factor = axis.x*axis.x + axis.y*axis.y + axis.z*axis.z; + factor = 1.0f / sqrtf(factor); + q1 = s*factor*axis.x; + q2 = s*factor*axis.y; + q3 = s*factor*axis.z; + q4 = cos(angle_rad); + return mat_rotation(q1, q2, q3, q4); + } + + TransformationMatrix TransformationMatrix::mat_mirror(const Axis &axis) + { + TransformationMatrix mat; // For RVO + switch (axis) + { + case X: + mat = TransformationMatrix( + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f); + break; + case Y: + mat = TransformationMatrix( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f); + break; + case Z: + mat = TransformationMatrix( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, -1.0f, 0.0f); + break; + default: + CONFESS("Invalid Axis supplied to TransformationMatrix::mat_mirror"); + mat = TransformationMatrix(); + break; + } + return mat; + } + + TransformationMatrix TransformationMatrix::mat_mirror(const Pointf3 &normal) + { + // Kovács, E. Rotation about arbitrary axis and reflection through an arbitrary plane, Annales Mathematicae + // et Informaticae, Vol 40 (2012) pp 175-186 + // http://ami.ektf.hu/uploads/papers/finalpdf/AMI_40_from175to186.pdf + float factor, c1, c2, c3; + factor = normal.x*normal.x + normal.y*normal.y + normal.z*normal.z; + factor = 1.0f / sqrtf(factor); + c1 = factor*normal.x; + c2 = factor*normal.y; + c3 = factor*normal.z; + return TransformationMatrix( + 1 - 2 * c1*c1, -2 * c2*c1, -2 * c3*c1, 0.0f, + -2 * c2*c1, 1 - 2 * c2*c2, -2 * c2*c3, 0.0f, + -2 * c1*c3, -2 * c2*c3, 1 - 2 * c3*c3, 0.0f); + } + +} diff --git a/xs/src/libslic3r/TransformationMatrix.hpp b/xs/src/libslic3r/TransformationMatrix.hpp new file mode 100644 index 000000000..d7bc43139 --- /dev/null +++ b/xs/src/libslic3r/TransformationMatrix.hpp @@ -0,0 +1,98 @@ +#ifndef slic3r_TriangleMatrix_hpp_ +#define slic3r_TriangleMatrix_hpp_ + +#ifndef Testumgebung +#include "libslic3r.h" +#include "Point.hpp" +#endif + +namespace Slic3r { + +class TransformationMatrix +{ +public: + TransformationMatrix(); +#ifndef Testumgebung + TransformationMatrix(std::vector &entries); +#endif + TransformationMatrix(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34); + TransformationMatrix(const TransformationMatrix &other); + TransformationMatrix& operator= (TransformationMatrix other); + void swap(TransformationMatrix &other); + + /// matrix entries + float m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34; + + /// Return the row-major form of the represented transformation matrix + float* matrix3x4f(); + + /// Return the determinante of the matrix + float determinante(); + + /// Returns the inverse of the matrix + bool inverse(TransformationMatrix * inverse); + + /// Perform Translation + void translate(float x, float y, float z); + + /// Perform uniform scale + void scale(float factor); + + /// Perform per-axis scale + void scale(float x, float y, float z); + + /// Perform mirroring along given axis + void mirror(const Axis &axis); + + /// Perform mirroring along given axis + void mirror(const Pointf3 &normal); + + /// Perform rotation around given axis + void rotate(float angle_rad, const Axis &axis); + + /// Perform rotation around arbitrary axis + void rotate(float angle_rad, const Pointf3 &axis); + + /// Perform rotation defined by unit quaternion + void rotate(float q1, float q2, float q3, float q4); + + /// Multiplies the Parameter-Matrix from the left (this=left*this) + void multiplyLeft(TransformationMatrix &left); + + /// Multiplies the Parameter-Matrix from the right (this=this*right) + void multiplyRight(TransformationMatrix &right); + + /// Generate an eye matrix. + static TransformationMatrix mat_eye(); + + /// Generate a per axis scaling matrix + static TransformationMatrix mat_scale(float x, float y, float z); + + /// Generate a uniform scaling matrix + static TransformationMatrix mat_scale(float scale); + + /// Generate a reflection matrix by coordinate axis + static TransformationMatrix mat_mirror(const Axis &axis); + + /// Generate a reflection matrix by arbitrary vector + static TransformationMatrix mat_mirror(const Pointf3 &normal); + + /// Generate a translation matrix + static TransformationMatrix mat_translation(float x, float y, float z); + + /// Generate a rotation matrix around coodinate axis + static TransformationMatrix mat_rotation(float angle_rad, const Axis &axis); + + /// Generate a rotation matrix defined by unit quaternion q1*i + q2*j + q3*k + q4 + static TransformationMatrix mat_rotation(float q1, float q2, float q3, float q4); + + /// Generate a rotation matrix around arbitrary axis + static TransformationMatrix mat_rotation(float angle_rad, const Pointf3 &axis); + + /// Performs a matrix multiplication + static TransformationMatrix multiply(const TransformationMatrix &left, const TransformationMatrix &right); +}; + +} + +#endif diff --git a/xs/t/02_transformationmatrix.t b/xs/t/02_transformationmatrix.t new file mode 100644 index 000000000..377d4a022 --- /dev/null +++ b/xs/t/02_transformationmatrix.t @@ -0,0 +1,141 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Slic3r::XS; +use Test::More tests => 49; + +use constant Z => 2; + +is Slic3r::TriangleMesh::hello_world(), 'Hello world!', + 'hello world'; + +my $cube = { + vertices => [ [20,20,0], [20,0,0], [0,0,0], [0,20,0], [20,20,20], [0,20,20], [0,0,20], [20,0,20] ], + facets => [ [0,1,2], [0,2,3], [4,5,6], [4,6,7], [0,4,7], [0,7,1], [1,7,6], [1,6,2], [2,6,5], [2,5,3], [4,0,3], [4,3,5] ], +}; + +{ + my $m = Slic3r::TriangleMesh->new; + $m->ReadFromPerl($cube->{vertices}, $cube->{facets}); + $m->repair; + my ($vertices, $facets) = ($m->vertices, $m->facets); + + is_deeply $vertices, $cube->{vertices}, 'vertices arrayref roundtrip'; + is_deeply $facets, $cube->{facets}, 'facets arrayref roundtrip'; + is scalar(@{$m->normals}), scalar(@$facets), 'normals returns the right number of items'; + + { + my $m2 = $m->clone; + is_deeply $m2->vertices, $cube->{vertices}, 'cloned vertices arrayref roundtrip'; + is_deeply $m2->facets, $cube->{facets}, 'cloned facets arrayref roundtrip'; + $m2->scale(3); # check that it does not affect $m + } + + { + my $stats = $m->stats; + is $stats->{number_of_facets}, scalar(@{ $cube->{facets} }), 'stats.number_of_facets'; + ok abs($stats->{volume} - 20*20*20) < 1E-2, 'stats.volume'; + } + + $m->scale(2); + ok abs($m->stats->{volume} - 40*40*40) < 1E-2, 'scale'; + + $m->scale_xyz(Slic3r::Pointf3->new(2,1,1)); + ok abs($m->stats->{volume} - 2*40*40*40) < 1E-2, 'scale_xyz'; + + $m->translate(5,10,0); + is_deeply $m->vertices->[0], [85,50,0], 'translate'; + + $m->align_to_origin; + is_deeply $m->vertices->[2], [0,0,0], 'align_to_origin'; + + is_deeply $m->size, [80,40,40], 'size'; + + $m->scale_xyz(Slic3r::Pointf3->new(0.5,1,1)); + $m->rotate(45, Slic3r::Point->new(20,20)); + ok abs($m->size->[0] - sqrt(2)*40) < 1E-4, 'rotate'; + + { + my $meshes = $m->split; + is scalar(@$meshes), 1, 'split'; + isa_ok $meshes->[0], 'Slic3r::TriangleMesh', 'split'; + is_deeply $m->bb3, $meshes->[0]->bb3, 'split populates stats'; + } + + my $m2 = Slic3r::TriangleMesh->new; + $m2->ReadFromPerl($cube->{vertices}, $cube->{facets}); + $m2->repair; + $m->merge($m2); + $m->repair; + is $m->stats->{number_of_facets}, 2 * $m2->stats->{number_of_facets}, 'merge'; + + { + my $meshes = $m->split; + is scalar(@$meshes), 2, 'split'; + } +} + +{ + my $m = Slic3r::TriangleMesh->new; + $m->ReadFromPerl($cube->{vertices}, $cube->{facets}); + $m->repair; + my @z = (0,2,4,8,6,8,10,12,14,16,18,20); + my $result = $m->slice(\@z); + my $SCALING_FACTOR = 0.000001; + for my $i (0..$#z) { + is scalar(@{$result->[$i]}), 1, "number of returned polygons per layer (z = " . $z[$i] . ")"; + is $result->[$i][0]->area, 20*20/($SCALING_FACTOR**2), 'size of returned polygon'; + } +} + +{ + my $m = Slic3r::TriangleMesh->new; + $m->ReadFromPerl( + [ [0,0,0],[0,0,20],[0,5,0],[0,5,20],[50,0,0],[50,0,20],[15,5,0],[35,5,0],[15,20,0],[50,5,0],[35,20,0],[15,5,10],[50,5,20],[35,5,10],[35,20,10],[15,20,10] ], + [ [0,1,2],[2,1,3],[1,0,4],[5,1,4],[0,2,4],[4,2,6],[7,6,8],[4,6,7],[9,4,7],[7,8,10],[2,3,6],[11,3,12],[7,12,9],[13,12,7],[6,3,11],[11,12,13],[3,1,5],[12,3,5],[5,4,9],[12,5,9],[13,7,10],[14,13,10],[8,15,10],[10,15,14],[6,11,8],[8,11,15],[15,11,13],[14,15,13] ], + ); + $m->repair; + { + # at Z = 10 we have a top horizontal surface + my $slices = $m->slice([ 5, 10 ]); + is $slices->[0][0]->area, $slices->[1][0]->area, 'slicing a top tangent plane includes its area'; + } + $m->mirror_z; + { + # this second test also checks that performing a second slice on a mesh after + # a transformation works properly (shared_vertices is correctly invalidated); + # at Z = -10 we have a bottom horizontal surface + my $slices = $m->slice([ -5, -10 ]); + is $slices->[0][0]->area, $slices->[1][0]->area, 'slicing a bottom tangent plane includes its area'; + } +} + +{ + my $m = Slic3r::TriangleMesh->new; + $m->ReadFromPerl($cube->{vertices}, $cube->{facets}); + $m->repair; + { + my $upper = Slic3r::TriangleMesh->new; + my $lower = Slic3r::TriangleMesh->new; + $m->cut(Z, 0, $upper, $lower); + $upper->repair; $lower->repair; + is $upper->facets_count, 12, 'upper mesh has all facets except those belonging to the slicing plane'; + is $lower->facets_count, 0, 'lower mesh has no facets'; + } + { + my $upper = Slic3r::TriangleMesh->new; + my $lower = Slic3r::TriangleMesh->new; + $m->cut(Z, 10, $upper, $lower); + #$upper->repair; $lower->repair; + # we expect: + # 2 facets on external horizontal surfaces + # 3 facets on each side = 12 facets + # 6 facets on the triangulated side (8 vertices) + is $upper->facets_count, 2+12+6, 'upper mesh has the expected number of facets'; + is $lower->facets_count, 2+12+6, 'lower mesh has the expected number of facets'; + } +} + +__END__ diff --git a/xs/xsp/TransformationMatrix.xsp b/xs/xsp/TransformationMatrix.xsp new file mode 100644 index 000000000..39f956c6f --- /dev/null +++ b/xs/xsp/TransformationMatrix.xsp @@ -0,0 +1,65 @@ +%module{Slic3r::XS}; + +%{ +#include +#include "libslic3r/TransformationMatrix.hpp" +%} + +%name{Slic3r::TransformationMatrix} class TransformationMatrix { + TransformationMatrix(); + ~TransformationMatrix(); + Clone clone() + %code{% RETVAL = THIS; %}; + + float m11; + %code%{ RETVAL = THIS->m11; %} + void set_m11(float value) + %code%{ THIS->m11 = value; %} + float m12; + %code%{ RETVAL = THIS->m12; %} + void set_m12(float value) + %code%{ THIS->m12 = value; %} + float m13; + %code%{ RETVAL = THIS->m13; %} + void set_m13(float value) + %code%{ THIS->m13 = value; %} + float m14; + %code%{ RETVAL = THIS->m14; %} + void set_m14(float value) + %code%{ THIS->m14 = value; %} + + float m21; + %code%{ RETVAL = THIS->m21; %} + void set_m21(float value) + %code%{ THIS->m21 = value; %} + float m22; + %code%{ RETVAL = THIS->m22; %} + void set_m22(float value) + %code%{ THIS->m22 = value; %} + float m23; + %code%{ RETVAL = THIS->m23; %} + void set_m23(float value) + %code%{ THIS->m23 = value; %} + float m24; + %code%{ RETVAL = THIS->m24; %} + void set_m24(float value) + %code%{ THIS->m24 = value; %} + + float m31; + %code%{ RETVAL = THIS->m31; %} + void set_m31(float value) + %code%{ THIS->m31 = value; %} + float m32; + %code%{ RETVAL = THIS->m32; %} + void set_m32(float value) + %code%{ THIS->m32 = value; %} + float m33; + %code%{ RETVAL = THIS->m33; %} + void set_m33(float value) + %code%{ THIS->m33 = value; %} + float m34; + %code%{ RETVAL = THIS->m34; %} + void set_m34(float value) + %code%{ THIS->m34 = value; %} + +};