Add custom types for position (#15204)

This commit is contained in:
Scott Lahteine
2019-09-29 04:25:39 -05:00
committed by GitHub
parent 43d6e9fa43
commit 50e4545255
227 changed files with 3147 additions and 3264 deletions

View File

@ -339,19 +339,19 @@ bool L6470_Marlin::get_user_input(uint8_t &driver_count, uint8_t axis_index[3],
// Position calcs & checks
//
const float center[] = {
LOGICAL_X_POSITION(current_position[X_AXIS]),
LOGICAL_Y_POSITION(current_position[Y_AXIS]),
LOGICAL_Z_POSITION(current_position[Z_AXIS]),
current_position[E_AXIS]
const xyze_pos_t center = {
LOGICAL_X_POSITION(current_position.x),
LOGICAL_Y_POSITION(current_position.y),
LOGICAL_Z_POSITION(current_position.z),
current_position.e
};
switch (axis_mon[0][0]) {
default: position_max = position_min = 0; break;
case 'X': {
position_min = center[X_AXIS] - displacement;
position_max = center[X_AXIS] + displacement;
position_min = center.x - displacement;
position_max = center.x + displacement;
echo_min_max('X', position_min, position_max);
if (false
#ifdef X_MIN_POS
@ -367,8 +367,8 @@ bool L6470_Marlin::get_user_input(uint8_t &driver_count, uint8_t axis_index[3],
} break;
case 'Y': {
position_min = center[Y_AXIS] - displacement;
position_max = center[Y_AXIS] + displacement;
position_min = center.y - displacement;
position_max = center.y + displacement;
echo_min_max('Y', position_min, position_max);
if (false
#ifdef Y_MIN_POS
@ -384,8 +384,8 @@ bool L6470_Marlin::get_user_input(uint8_t &driver_count, uint8_t axis_index[3],
} break;
case 'Z': {
position_min = center[Z_AXIS] - displacement;
position_max = center[Z_AXIS] + displacement;
position_min = center.z - displacement;
position_max = center.z + displacement;
echo_min_max('Z', position_min, position_max);
if (false
#ifdef Z_MIN_POS
@ -401,8 +401,8 @@ bool L6470_Marlin::get_user_input(uint8_t &driver_count, uint8_t axis_index[3],
} break;
case 'E': {
position_min = center[E_AXIS] - displacement;
position_max = center[E_AXIS] + displacement;
position_min = center.e - displacement;
position_max = center.e + displacement;
echo_min_max('E', position_min, position_max);
} break;
}

View File

@ -65,6 +65,9 @@ inline void incremental_WLSF(struct linear_fit_data *lsf, const float &x, const
lsf->max_absx = _MAX(ABS(wx), lsf->max_absx);
lsf->max_absy = _MAX(ABS(wy), lsf->max_absy);
}
inline void incremental_WLSF(struct linear_fit_data *lsf, const xy_pos_t &pos, const float &z, const float &w) {
incremental_WLSF(lsf, pos.x, pos.y, z, w);
}
inline void incremental_LSF(struct linear_fit_data *lsf, const float &x, const float &y, const float &z) {
lsf->xbar += x;
@ -80,5 +83,8 @@ inline void incremental_LSF(struct linear_fit_data *lsf, const float &x, const f
lsf->max_absy = _MAX(ABS(y), lsf->max_absy);
lsf->N += 1.0;
}
inline void incremental_LSF(struct linear_fit_data *lsf, const xy_pos_t &pos, const float &z) {
incremental_LSF(lsf, pos.x, pos.y, z);
}
int finish_incremental_LSF(struct linear_fit_data *);

View File

@ -30,7 +30,6 @@ Nozzle nozzle;
#include "../Marlin.h"
#include "../module/motion.h"
#include "point_t.h"
#if ENABLED(NOZZLE_CLEAN_FEATURE)
@ -38,30 +37,30 @@ Nozzle nozzle;
* @brief Stroke clean pattern
* @details Wipes the nozzle back and forth in a linear movement
*
* @param start point_t defining the starting point
* @param end point_t defining the ending point
* @param start xyz_pos_t defining the starting point
* @param end xyz_pos_t defining the ending point
* @param strokes number of strokes to execute
*/
void Nozzle::stroke(const point_t &start, const point_t &end, const uint8_t &strokes) {
void Nozzle::stroke(const xyz_pos_t &start, const xyz_pos_t &end, const uint8_t &strokes) {
#if ENABLED(NOZZLE_CLEAN_GOBACK)
const float ix = current_position[X_AXIS], iy = current_position[Y_AXIS], iz = current_position[Z_AXIS];
const xyz_pos_t oldpos = current_position;
#endif
// Move to the starting point
#if ENABLED(NOZZLE_CLEAN_NO_Z)
do_blocking_move_to_xy(start.x, start.y);
do_blocking_move_to_xy(start);
#else
do_blocking_move_to(start.x, start.y, start.z);
do_blocking_move_to(start);
#endif
// Start the stroke pattern
for (uint8_t i = 0; i < (strokes >> 1); i++) {
do_blocking_move_to_xy(end.x, end.y);
do_blocking_move_to_xy(start.x, start.y);
do_blocking_move_to_xy(end);
do_blocking_move_to_xy(start);
}
#if ENABLED(NOZZLE_CLEAN_GOBACK)
do_blocking_move_to(ix, iy, iz);
do_blocking_move_to(oldpos);
#endif
}
@ -69,29 +68,29 @@ Nozzle nozzle;
* @brief Zig-zag clean pattern
* @details Apply a zig-zag cleaning pattern
*
* @param start point_t defining the starting point
* @param end point_t defining the ending point
* @param start xyz_pos_t defining the starting point
* @param end xyz_pos_t defining the ending point
* @param strokes number of strokes to execute
* @param objects number of triangles to do
*/
void Nozzle::zigzag(const point_t &start, const point_t &end, const uint8_t &strokes, const uint8_t &objects) {
const float diffx = end.x - start.x, diffy = end.y - start.y;
if (!diffx || !diffy) return;
void Nozzle::zigzag(const xyz_pos_t &start, const xyz_pos_t &end, const uint8_t &strokes, const uint8_t &objects) {
const xy_pos_t diff = end - start;
if (!diff.x || !diff.y) return;
#if ENABLED(NOZZLE_CLEAN_GOBACK)
const float ix = current_position[X_AXIS], iy = current_position[Y_AXIS], iz = current_position[Z_AXIS];
const xyz_pos_t back = current_position;
#endif
#if ENABLED(NOZZLE_CLEAN_NO_Z)
do_blocking_move_to_xy(start.x, start.y);
do_blocking_move_to_xy(start);
#else
do_blocking_move_to(start.x, start.y, start.z);
do_blocking_move_to(start);
#endif
const uint8_t zigs = objects << 1;
const bool horiz = ABS(diffx) >= ABS(diffy); // Do a horizontal wipe?
const float P = (horiz ? diffx : diffy) / zigs; // Period of each zig / zag
const point_t *side;
const bool horiz = ABS(diff.x) >= ABS(diff.y); // Do a horizontal wipe?
const float P = (horiz ? diff.x : diff.y) / zigs; // Period of each zig / zag
const xyz_pos_t *side;
for (uint8_t j = 0; j < strokes; j++) {
for (int8_t i = 0; i < zigs; i++) {
side = (i & 1) ? &end : &start;
@ -110,7 +109,7 @@ Nozzle nozzle;
}
#if ENABLED(NOZZLE_CLEAN_GOBACK)
do_blocking_move_to(ix, iy, iz);
do_blocking_move_to(back);
#endif
}
@ -118,21 +117,21 @@ Nozzle nozzle;
* @brief Circular clean pattern
* @details Apply a circular cleaning pattern
*
* @param start point_t defining the middle of circle
* @param start xyz_pos_t defining the middle of circle
* @param strokes number of strokes to execute
* @param radius radius of circle
*/
void Nozzle::circle(const point_t &start, const point_t &middle, const uint8_t &strokes, const float &radius) {
void Nozzle::circle(const xyz_pos_t &start, const xyz_pos_t &middle, const uint8_t &strokes, const float &radius) {
if (strokes == 0) return;
#if ENABLED(NOZZLE_CLEAN_GOBACK)
const float ix = current_position[X_AXIS], iy = current_position[Y_AXIS], iz = current_position[Z_AXIS];
const xyz_pos_t back = current_position;
#endif
#if ENABLED(NOZZLE_CLEAN_NO_Z)
do_blocking_move_to_xy(start.x, start.y);
do_blocking_move_to_xy(start);
#else
do_blocking_move_to(start.x, start.y, start.z);
do_blocking_move_to(start);
#endif
for (uint8_t s = 0; s < strokes; s++)
@ -143,10 +142,10 @@ Nozzle nozzle;
);
// Let's be safe
do_blocking_move_to_xy(start.x, start.y);
do_blocking_move_to_xy(start);
#if ENABLED(NOZZLE_CLEAN_GOBACK)
do_blocking_move_to(ix, iy, iz);
do_blocking_move_to(back);
#endif
}
@ -158,21 +157,21 @@ Nozzle nozzle;
* @param argument depends on the cleaning pattern
*/
void Nozzle::clean(const uint8_t &pattern, const uint8_t &strokes, const float &radius, const uint8_t &objects, const uint8_t cleans) {
point_t start = NOZZLE_CLEAN_START_POINT;
point_t end = NOZZLE_CLEAN_END_POINT;
xyz_pos_t start = NOZZLE_CLEAN_START_POINT, end = NOZZLE_CLEAN_END_POINT;
if (pattern == 2) {
if (!(cleans & (_BV(X_AXIS) | _BV(Y_AXIS)))) {
SERIAL_ECHOLNPGM("Warning : Clean Circle requires XY");
return;
}
end = NOZZLE_CLEAN_CIRCLE_MIDDLE;
constexpr xyz_pos_t middle NOZZLE_CLEAN_CIRCLE_MIDDLE;
end = middle;
}
else {
if (!TEST(cleans, X_AXIS)) start.x = end.x = current_position[X_AXIS];
if (!TEST(cleans, Y_AXIS)) start.y = end.y = current_position[Y_AXIS];
if (!TEST(cleans, X_AXIS)) start.x = end.x = current_position.x;
if (!TEST(cleans, Y_AXIS)) start.y = end.y = current_position.y;
}
if (!TEST(cleans, Z_AXIS)) start.z = end.z = current_position[Z_AXIS];
if (!TEST(cleans, Z_AXIS)) start.z = end.z = current_position.z;
switch (pattern) {
case 1: zigzag(start, end, strokes, objects); break;
@ -185,7 +184,7 @@ Nozzle nozzle;
#if ENABLED(NOZZLE_PARK_FEATURE)
void Nozzle::park(const uint8_t z_action, const point_t &park/*=NOZZLE_PARK_POINT*/) {
void Nozzle::park(const uint8_t z_action, const xyz_pos_t &park/*=NOZZLE_PARK_POINT*/) {
constexpr feedRate_t fr_xy = NOZZLE_PARK_XY_FEEDRATE, fr_z = NOZZLE_PARK_Z_FEEDRATE;
switch (z_action) {
@ -194,14 +193,14 @@ Nozzle nozzle;
break;
case 2: // Raise by Z-park height
do_blocking_move_to_z(_MIN(current_position[Z_AXIS] + park.z, Z_MAX_POS), fr_z);
do_blocking_move_to_z(_MIN(current_position.z + park.z, Z_MAX_POS), fr_z);
break;
default: // Raise to at least the Z-park height
do_blocking_move_to_z(_MAX(park.z, current_position[Z_AXIS]), fr_z);
do_blocking_move_to_z(_MAX(park.z, current_position.z), fr_z);
}
do_blocking_move_to_xy(park.x, park.y, fr_xy);
do_blocking_move_to_xy(park, fr_xy);
report_current_position();
}

View File

@ -22,7 +22,6 @@
#pragma once
#include "../inc/MarlinConfig.h"
#include "point_t.h"
/**
* @brief Nozzle class
@ -38,32 +37,32 @@ class Nozzle {
* @brief Stroke clean pattern
* @details Wipes the nozzle back and forth in a linear movement
*
* @param start point_t defining the starting point
* @param end point_t defining the ending point
* @param start xyz_pos_t defining the starting point
* @param end xyz_pos_t defining the ending point
* @param strokes number of strokes to execute
*/
static void stroke(const point_t &start, const point_t &end, const uint8_t &strokes) _Os;
static void stroke(const xyz_pos_t &start, const xyz_pos_t &end, const uint8_t &strokes) _Os;
/**
* @brief Zig-zag clean pattern
* @details Apply a zig-zag cleaning pattern
*
* @param start point_t defining the starting point
* @param end point_t defining the ending point
* @param start xyz_pos_t defining the starting point
* @param end xyz_pos_t defining the ending point
* @param strokes number of strokes to execute
* @param objects number of objects to create
*/
static void zigzag(const point_t &start, const point_t &end, const uint8_t &strokes, const uint8_t &objects) _Os;
static void zigzag(const xyz_pos_t &start, const xyz_pos_t &end, const uint8_t &strokes, const uint8_t &objects) _Os;
/**
* @brief Circular clean pattern
* @details Apply a circular cleaning pattern
*
* @param start point_t defining the middle of circle
* @param start xyz_pos_t defining the middle of circle
* @param strokes number of strokes to execute
* @param radius radius of circle
*/
static void circle(const point_t &start, const point_t &middle, const uint8_t &strokes, const float &radius) _Os;
static void circle(const xyz_pos_t &start, const xyz_pos_t &middle, const uint8_t &strokes, const float &radius) _Os;
#endif // NOZZLE_CLEAN_FEATURE
@ -84,7 +83,7 @@ class Nozzle {
#if ENABLED(NOZZLE_PARK_FEATURE)
static void park(const uint8_t z_action, const point_t &park=NOZZLE_PARK_POINT) _Os;
static void park(const uint8_t z_action, const xyz_pos_t &park=NOZZLE_PARK_POINT) _Os;
#endif
};

View File

@ -1,55 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <math.h>
/**
* @brief Cartesian Point
* @details Represents a three dimensional point on Cartesian coordinate system,
* using an additional fourth dimension for the extrusion length.
*
* @param x The x-coordinate of the point.
* @param y The y-coordinate of the point.
* @param z The z-coordinate of the point.
*/
struct point_t {
float x, y, z;
/**
* @brief Three dimensional point constructor
*
* @param x The x-coordinate of the point.
* @param y The y-coordinate of the point.
* @param z The z-coordinate of the point.
*/
point_t(const float x, const float y, const float z) : x(x), y(y), z(z) {}
/**
* @brief Two dimensional point constructor
*
* @param x The x-coordinate of the point.
* @param y The y-coordinate of the point.
*/
point_t(const float x, const float y) : point_t(x, y, NAN) {}
};

View File

@ -47,81 +47,74 @@
#include <math.h>
vector_3::vector_3() : x(0), y(0), z(0) { }
vector_3::vector_3(float x_, float y_, float z_) : x(x_), y(y_), z(z_) { }
/**
* vector_3
*/
vector_3 vector_3::cross(const vector_3 &left, const vector_3 &right) {
return vector_3(left.y * right.z - left.z * right.y,
left.z * right.x - left.x * right.z,
left.x * right.y - left.y * right.x);
const xyz_float_t &lv = left, &rv = right;
return vector_3(lv.y * rv.z - lv.z * rv.y, // YZ cross
lv.z * rv.x - lv.x * rv.z, // ZX cross
lv.x * rv.y - lv.y * rv.x); // XY cross
}
vector_3 vector_3::operator+(const vector_3 &v) { return vector_3(x + v.x, y + v.y, z + v.z); }
vector_3 vector_3::operator-(const vector_3 &v) { return vector_3(x - v.x, y - v.y, z - v.z); }
vector_3 vector_3::operator* (const float &v) { return vector_3(x * v, y * v, z * v); }
vector_3& vector_3::operator*=(const float &v) { x *= v; y *= v; z *= v; return *this; }
vector_3 vector_3::get_normal() const {
vector_3 normalized = vector_3(x, y, z);
vector_3 normalized = *this;
normalized.normalize();
return normalized;
}
float vector_3::get_length() const { return SQRT(sq(x) + sq(y) + sq(z)); }
void vector_3::normalize() {
const float inv_length = RSQRT(sq(x) + sq(y) + sq(z));
x *= inv_length;
y *= inv_length;
z *= inv_length;
*this *= RSQRT(sq(x) + sq(y) + sq(z));
}
// Apply a rotation to the matrix
void vector_3::apply_rotation(const matrix_3x3 &matrix) {
const float _x = x, _y = y;
x = _x * matrix.matrix[3 * 0 + 0] + _y * matrix.matrix[3 * 1 + 0] + z * matrix.matrix[3 * 2 + 0];
y = _x * matrix.matrix[3 * 0 + 1] + _y * matrix.matrix[3 * 1 + 1] + z * matrix.matrix[3 * 2 + 1];
z = _x * matrix.matrix[3 * 0 + 2] + _y * matrix.matrix[3 * 1 + 2] + z * matrix.matrix[3 * 2 + 2];
const float _x = x, _y = y, _z = z;
*this = matrix.vectors[0] * _x + matrix.vectors[1] * _y + matrix.vectors[2] * _z;
}
void vector_3::debug(PGM_P const title) {
serialprintPGM(title);
SERIAL_ECHOPAIR_F(" x: ", x, 6);
SERIAL_ECHOPAIR_F(" y: ", y, 6);
SERIAL_ECHOLNPAIR_F(" z: ", z, 6);
SERIAL_ECHOPAIR_F(" X", x, 6);
SERIAL_ECHOPAIR_F(" Y", y, 6);
SERIAL_ECHOLNPAIR_F(" Z", z, 6);
}
void apply_rotation_xyz(const matrix_3x3 &matrix, float &x, float &y, float &z) {
vector_3 vector = vector_3(x, y, z);
vector.apply_rotation(matrix);
x = vector.x;
y = vector.y;
z = vector.z;
/**
* matrix_3x3
*/
void apply_rotation_xyz(const matrix_3x3 &matrix, float &_x, float &_y, float &_z) {
vector_3 vec = vector_3(_x, _y, _z); vec.apply_rotation(matrix);
_x = vec.x; _y = vec.y; _z = vec.z;
}
// Reset to identity. No rotate or translate.
void matrix_3x3::set_to_identity() {
for (uint8_t i = 0; i < 3; i++)
for (uint8_t j = 0; j < 3; j++)
vectors[i][j] = float(i == j);
}
// Create a matrix from 3 vector_3 inputs
matrix_3x3 matrix_3x3::create_from_rows(const vector_3 &row_0, const vector_3 &row_1, const vector_3 &row_2) {
//row_0.debug(PSTR("row_0"));
//row_1.debug(PSTR("row_1"));
//row_2.debug(PSTR("row_2"));
matrix_3x3 new_matrix;
new_matrix.matrix[0] = row_0.x; new_matrix.matrix[1] = row_0.y; new_matrix.matrix[2] = row_0.z;
new_matrix.matrix[3] = row_1.x; new_matrix.matrix[4] = row_1.y; new_matrix.matrix[5] = row_1.z;
new_matrix.matrix[6] = row_2.x; new_matrix.matrix[7] = row_2.y; new_matrix.matrix[8] = row_2.z;
new_matrix.vectors[0] = row_0;
new_matrix.vectors[1] = row_1;
new_matrix.vectors[2] = row_2;
//new_matrix.debug(PSTR("new_matrix"));
return new_matrix;
}
void matrix_3x3::set_to_identity() {
matrix[0] = 1; matrix[1] = 0; matrix[2] = 0;
matrix[3] = 0; matrix[4] = 1; matrix[5] = 0;
matrix[6] = 0; matrix[7] = 0; matrix[8] = 1;
}
// Create a matrix rotated to point towards a target
matrix_3x3 matrix_3x3::create_look_at(const vector_3 &target) {
vector_3 z_row = target.get_normal(),
x_row = vector_3(1, 0, -target.x / target.z).get_normal(),
y_row = vector_3::cross(z_row, x_row).get_normal();
const vector_3 z_row = target.get_normal(),
x_row = vector_3(1, 0, -target.x / target.z).get_normal(),
y_row = vector_3::cross(z_row, x_row).get_normal();
// x_row.debug(PSTR("x_row"));
// y_row.debug(PSTR("y_row"));
@ -134,11 +127,12 @@ matrix_3x3 matrix_3x3::create_look_at(const vector_3 &target) {
return rot;
}
// Get a transposed copy of the matrix
matrix_3x3 matrix_3x3::transpose(const matrix_3x3 &original) {
matrix_3x3 new_matrix;
new_matrix.matrix[0] = original.matrix[0]; new_matrix.matrix[1] = original.matrix[3]; new_matrix.matrix[2] = original.matrix[6];
new_matrix.matrix[3] = original.matrix[1]; new_matrix.matrix[4] = original.matrix[4]; new_matrix.matrix[5] = original.matrix[7];
new_matrix.matrix[6] = original.matrix[2]; new_matrix.matrix[7] = original.matrix[5]; new_matrix.matrix[8] = original.matrix[8];
for (uint8_t i = 0; i < 3; i++)
for (uint8_t j = 0; j < 3; j++)
new_matrix.vectors[i][j] = original.vectors[j][i];
return new_matrix;
}
@ -147,13 +141,11 @@ void matrix_3x3::debug(PGM_P const title) {
serialprintPGM(title);
SERIAL_EOL();
}
uint8_t count = 0;
for (uint8_t i = 0; i < 3; i++) {
for (uint8_t j = 0; j < 3; j++) {
if (matrix[count] >= 0.0) SERIAL_CHAR('+');
SERIAL_ECHO_F(matrix[count], 6);
if (vectors[i][j] >= 0.0) SERIAL_CHAR('+');
SERIAL_ECHO_F(vectors[i][j], 6);
SERIAL_CHAR(' ');
count++;
}
SERIAL_EOL();
}

View File

@ -40,33 +40,40 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../core/types.h"
class matrix_3x3;
struct vector_3 {
float x, y, z;
struct vector_3 : xyz_float_t {
vector_3();
vector_3(float x, float y, float z);
vector_3(const float &_x, const float &_y, const float &_z) { set(_x, _y, _z); }
vector_3(const xy_float_t &in) { set(in.x, in.y); }
vector_3(const xyz_float_t &in) { set(in.x, in.y, in.z); }
vector_3(const xyze_float_t &in) { set(in.x, in.y, in.z); }
// Factory method
static vector_3 cross(const vector_3 &a, const vector_3 &b);
vector_3 operator+(const vector_3 &v);
vector_3 operator-(const vector_3 &v);
vector_3 operator* (const float &v);
vector_3& operator*=(const float &v);
// Modifiers
void normalize();
void apply_rotation(const matrix_3x3 &matrix);
// Accessors
float get_length() const;
vector_3 get_normal() const;
// Operators
FORCE_INLINE vector_3 operator+(const vector_3 &v) const { vector_3 o = *this; o += v; return o; }
FORCE_INLINE vector_3 operator-(const vector_3 &v) const { vector_3 o = *this; o -= v; return o; }
FORCE_INLINE vector_3 operator*(const float &v) const { vector_3 o = *this; o *= v; return o; }
void debug(PGM_P const title);
void apply_rotation(const matrix_3x3 &matrix);
};
struct matrix_3x3 {
float matrix[9];
abc_float_t vectors[3];
// Factory methods
static matrix_3x3 create_from_rows(const vector_3 &row_0, const vector_3 &row_1, const vector_3 &row_2);
static matrix_3x3 create_look_at(const vector_3 &target);
static matrix_3x3 transpose(const matrix_3x3 &original);
@ -76,5 +83,7 @@ struct matrix_3x3 {
void debug(PGM_P const title);
};
void apply_rotation_xyz(const matrix_3x3 &rotationMatrix, float &x, float &y, float &z);
FORCE_INLINE void apply_rotation_xyz(const matrix_3x3 &rotationMatrix, xyz_pos_t &pos) {
apply_rotation_xyz(rotationMatrix, pos.x, pos.y, pos.z);
}