OverviewFilesCommitsIssuesDocsReleasesPeers

proc-nodes / src / nodes / rotation_nodes.h

341 lines · c ref:
#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