#ifndef PROC_NODES_ROTATION_NODES_H
#define PROC_NODES_ROTATION_NODES_H
#include "../graph/proc_node.h"
#include <godot_cpp/variant/projection.hpp>
#include <godot_cpp/variant/quaternion.hpp>
namespace godot {
class AxisAngleToRotationNode : public ProcNode {
GDCLASS(AxisAngleToRotationNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "AxisAngleToRotation"; }
String get_node_title() const override { return "Axis Angle to Rotation"; }
String get_node_category() const override { return "Rotation"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
AxisAngleToRotationNode();
};
class EulerToRotationNode : public ProcNode {
GDCLASS(EulerToRotationNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "EulerToRotation"; }
String get_node_title() const override { return "Euler to Rotation"; }
String get_node_category() const override { return "Rotation"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
EulerToRotationNode();
// GLSL, because MTN_CellSpace's lattice rotation sits inside the bridged
// mountain's DENSITY cone -- the emitter refused the whole graph on it.
// ⚠ The euler order is PN_EULER_ORDER (ZYX): Blender's XYZ euler is Godot's
// ZYX, one naming the order rotations are APPLIED and the other the order
// matrices are MULTIPLIED. This is held to the CPU by
// tests/test_emitted_density_parity.cpp, which compares NUMBERS -- a check
// that asserted the spelling of an order certified the wrong one twice.
bool supports_gpu() const override { return true; }
String compile_glsl_prelude(int p_node_idx) const override;
String compile_glsl(const GlslEmitContext &p_ctx, int p_node_idx) const override;
};
class QuaternionToRotationNode : public ProcNode {
GDCLASS(QuaternionToRotationNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "QuaternionToRotation"; }
String get_node_title() const override { return "Quaternion to Rotation"; }
String get_node_category() const override { return "Rotation"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
QuaternionToRotationNode();
};
class RotationToAxisAngleNode : public ProcNode {
GDCLASS(RotationToAxisAngleNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "RotationToAxisAngle"; }
String get_node_title() const override { return "Rotation to Axis Angle"; }
String get_node_category() const override { return "Rotation"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
RotationToAxisAngleNode();
};
class RotationToEulerNode : public ProcNode {
GDCLASS(RotationToEulerNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "RotationToEuler"; }
String get_node_title() const override { return "Rotation to Euler"; }
String get_node_category() const override { return "Rotation"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
RotationToEulerNode();
};
class RotationToQuaternionNode : public ProcNode {
GDCLASS(RotationToQuaternionNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "RotationToQuaternion"; }
String get_node_title() const override { return "Rotation to Quaternion"; }
String get_node_category() const override { return "Rotation"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
RotationToQuaternionNode();
};
class InvertRotationNode : public ProcNode {
GDCLASS(InvertRotationNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "InvertRotation"; }
String get_node_title() const override { return "Invert Rotation"; }
String get_node_category() const override { return "Rotation"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
InvertRotationNode();
};
class RotateRotationNode : public ProcNode {
GDCLASS(RotateRotationNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "RotateRotation"; }
String get_node_title() const override { return "Rotate Rotation"; }
String get_node_category() const override { return "Rotation"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
RotateRotationNode();
};
class RotateVectorNode : public ProcNode {
GDCLASS(RotateVectorNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "RotateVector"; }
String get_node_title() const override { return "Rotate Vector"; }
String get_node_category() const override { return "Rotation"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
RotateVectorNode();
// GLSL, because MTN_CellSpace's lattice rotation sits inside the bridged
// mountain's DENSITY cone -- the emitter refused the whole graph on it.
// ⚠ The euler order is PN_EULER_ORDER (ZYX): Blender's XYZ euler is Godot's
// ZYX, one naming the order rotations are APPLIED and the other the order
// matrices are MULTIPLIED. This is held to the CPU by
// tests/test_emitted_density_parity.cpp, which compares NUMBERS -- a check
// that asserted the spelling of an order certified the wrong one twice.
bool supports_gpu() const override { return true; }
String compile_glsl_prelude(int p_node_idx) const override;
String compile_glsl(const GlslEmitContext &p_ctx, int p_node_idx) const override;
};
class InputRotationNode : public ProcNode {
GDCLASS(InputRotationNode, ProcNode);
protected:
static void _bind_methods();
Quaternion rotation;
public:
StringName get_node_type() const override { return "InputRotation"; }
String get_node_title() const override { return "Rotation"; }
String get_node_category() const override { return "Rotation"; }
// The value is a node PROPERTY on Blender's side too, so it arrives as one
// rather than as a socket default.
void set_rotation(const Quaternion &p_q) { rotation = p_q; }
Quaternion get_rotation() const { return rotation; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
InputRotationNode();
};
class RotateEulerNode : public ProcNode {
GDCLASS(RotateEulerNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "RotateEuler"; }
String get_node_title() const override { return "Rotate Euler"; }
String get_node_category() const override { return "Rotation"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
RotateEulerNode();
};
// Vector Rotate — Blender's, which has FIVE rotation types and an Invert flag.
// Ours implemented the free-axis one only and had no Rotation socket, so the
// three fixed-axis modes rotated about whatever was in Axis and EULER_XYZ had
// nothing to read.
class VectorRotateNode : public ProcNode {
GDCLASS(VectorRotateNode, ProcNode);
int rotation_type = 0; // AXIS, AXIS_X, AXIS_Y, AXIS_Z, EULER_XYZ
bool invert = false;
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "VectorRotate"; }
String get_node_title() const override { return "Vector Rotate"; }
String get_node_category() const override { return "Rotation"; }
void set_rotation_type(int p_t) { rotation_type = p_t; }
int get_rotation_type() const { return rotation_type; }
void set_invert(bool p_i) { invert = p_i; }
bool get_invert() const { return invert; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
VectorRotateNode();
};
class CombineMatrixNode : public ProcNode {
GDCLASS(CombineMatrixNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "CombineMatrix"; }
String get_node_title() const override { return "Combine Matrix"; }
String get_node_category() const override { return "Matrix"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
CombineMatrixNode();
};
class SeparateMatrixNode : public ProcNode {
GDCLASS(SeparateMatrixNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "SeparateMatrix"; }
String get_node_title() const override { return "Separate Matrix"; }
String get_node_category() const override { return "Matrix"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
SeparateMatrixNode();
};
class InvertMatrixNode : public ProcNode {
GDCLASS(InvertMatrixNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "InvertMatrix"; }
String get_node_title() const override { return "Invert Matrix"; }
String get_node_category() const override { return "Matrix"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
InvertMatrixNode();
};
class MatrixDeterminantNode : public ProcNode {
GDCLASS(MatrixDeterminantNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "MatrixDeterminant"; }
String get_node_title() const override { return "Matrix Determinant"; }
String get_node_category() const override { return "Matrix"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
MatrixDeterminantNode();
};
class MatrixMultiplyNode : public ProcNode {
GDCLASS(MatrixMultiplyNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "MatrixMultiply"; }
String get_node_title() const override { return "Multiply Matrices"; }
String get_node_category() const override { return "Matrix"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
MatrixMultiplyNode();
};
class TransposeMatrixNode : public ProcNode {
GDCLASS(TransposeMatrixNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "TransposeMatrix"; }
String get_node_title() const override { return "Transpose Matrix"; }
String get_node_category() const override { return "Matrix"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
TransposeMatrixNode();
};
} // namespace godot
#endif // PROC_NODES_ROTATION_NODES_H