add cylinder

This commit is contained in:
AndreaRigoni
2026-03-24 15:22:50 +00:00
parent b45cde0bad
commit 51e6dbb4f5
11 changed files with 523 additions and 121 deletions

View File

@@ -34,32 +34,32 @@
namespace uLib {
/**
* @brief Represents a cylindrical volume centered in the base circle.
* @brief Represents a cylindrical volume.
*
* Cylinder inherits from AffineTransform, which defines its parent
* coordinate system. It contains an internal local transformation (m_LocalT)
* that defines the cylinder's actual volume (radius and height)
* relative to the emitter's origin (base circle center).
* The cylinder orientation is defined by the Axis property (0=X, 1=Y, 2=Z).
* By default, it is aligned with the Y axis (Axis=1).
*/
class Cylinder : public AffineTransform, public Object {
typedef AffineTransform BaseClass;
public:
uLibTypeMacro(Cylinder, Object)
virtual const char * GetClassName() const { return "Cylinder"; }
virtual const char * GetClassName() const override { return "Cylinder"; }
/**
* @brief Default constructor.
* Initializes with radius 1 and height 1.
* @brief Default constructor. Aligns with Y by default.
*/
Cylinder() : m_LocalT(this), m_Radius(1.0), m_Height(1.0) {
Cylinder() : m_LocalT(this), Radius(1.0), Height(1.0), Axis(1) {
ULIB_ACTIVATE_PROPERTIES(*this);
UpdateLocalMatrix();
}
/**
* @brief Constructor with radius and height.
*/
Cylinder(float radius, float height) : m_LocalT(this), m_Radius(radius), m_Height(height) {
Cylinder(float radius, float height, int axis = 1)
: m_LocalT(this), Radius(radius), Height(height), Axis(axis) {
ULIB_ACTIVATE_PROPERTIES(*this);
UpdateLocalMatrix();
}
@@ -67,75 +67,115 @@ public:
* @brief Copy constructor.
*/
Cylinder(const Cylinder &copy)
: m_LocalT(this), AffineTransform(copy) {
this->SetRadius(copy.GetRadius());
this->SetHeight(copy.GetHeight());
: m_LocalT(this), AffineTransform(copy), Radius(copy.Radius), Height(copy.Height), Axis(copy.Axis) {
ULIB_ACTIVATE_PROPERTIES(*this);
this->UpdateLocalMatrix();
}
/**
* @brief Serialization template for property registration and persistence.
*/
template <class ArchiveT>
void serialize(ArchiveT & ar, const unsigned int version) {
ar & HRP(Radius);
ar & HRP(Height);
ar & HRP(Axis);
}
/** Sets the radius of the cylinder */
inline void SetRadius(float r) {
m_Radius = r;
Radius = r;
UpdateLocalMatrix();
}
/** Gets the radius of the cylinder */
inline float GetRadius() const { return m_Radius; }
inline float GetRadius() const { return Radius; }
/** Sets the height of the cylinder */
inline void SetHeight(float h) {
m_Height = h;
Height = h;
UpdateLocalMatrix();
}
/** Gets the height of the cylinder */
inline float GetHeight() const { return m_Height; }
inline float GetHeight() const { return Height; }
/** Sets the main axis (0=X, 1=Y, 2=Z) */
inline void SetAxis(int axis) {
Axis = axis;
UpdateLocalMatrix();
}
/** Gets the main axis */
inline int GetAxis() const { return Axis; }
/**
* @brief Returns the world transformation matrix of the cylinder's volume.
* @brief Returns the world transformation matrix.
*/
Matrix4f GetWorldMatrix() const { return m_LocalT.GetWorldMatrix(); }
/**
* @brief Returns the local transformation matrix of the cylinder's volume.
* @brief Returns the local transformation matrix.
*/
Matrix4f GetLocalMatrix() const { return m_LocalT.GetMatrix(); }
/**
* @brief Transforms local cylindrical coordinates to world space.
* @param r Local radius (absolute).
* @param theta Local angle in radians.
* @param z Local height (absolute, relative to base circle).
* @return Transformed point in world space.
* @param r Local radius.
* @param theta Local angle in radians (around main axis).
* @param h Local height along main axis.
*/
inline Vector4f GetWorldPoint(float r, float theta, float z) const {
return BaseClass::GetWorldMatrix() * Vector4f(r * std::cos(theta), r * std::sin(theta), z, 1.0f);
inline Vector4f GetWorldPoint(float r, float theta, float h) const {
Vector3f p;
if (Axis == 0) p = Vector3f(h, r * std::cos(theta), r * std::sin(theta));
else if (Axis == 1) p = Vector3f(r * std::cos(theta), h, r * std::sin(theta));
else p = Vector3f(r * std::cos(theta), r * std::sin(theta), h);
return AffineTransform::GetWorldMatrix() * Vector4f(p.x(), p.y(), p.z(), 1.0f);
}
/**
* @brief Transforms a world point to cylindrical local space.
* @return Vector3f(r, theta, z)
* @return Vector3f(r, theta, h)
*/
inline Vector3f GetCylindricalLocal(const Vector4f &world_v) const {
Vector4f local_v = BaseClass::GetWorldMatrix().inverse() * world_v;
float r = std::sqrt(local_v.x() * local_v.x() + local_v.y() * local_v.y());
float theta = std::atan2(local_v.y(), local_v.x());
return Vector3f(r, theta, local_v.z());
Vector4f local_v = AffineTransform::GetWorldMatrix().inverse() * world_v;
float r, theta, h;
if (Axis == 0) {
h = local_v.x();
r = std::sqrt(local_v.y() * local_v.y() + local_v.z() * local_v.z());
theta = std::atan2(local_v.z(), local_v.y());
} else if (Axis == 1) {
h = local_v.y();
r = std::sqrt(local_v.x() * local_v.x() + local_v.z() * local_v.z());
theta = std::atan2(local_v.z(), local_v.x());
} else {
h = local_v.z();
r = std::sqrt(local_v.x() * local_v.x() + local_v.y() * local_v.y());
theta = std::atan2(local_v.y(), local_v.x());
}
return Vector3f(r, theta, h);
}
signals:
/** Signal emitted when the cylinder geometry or transform is updated */
virtual void Updated() override { ULIB_SIGNAL_EMIT(Cylinder::Updated); }
private:
/** Recalculates the internal local matrix based on radius and height */
void UpdateLocalMatrix() {
m_LocalT = AffineTransform(this); // BaseClass is parent
m_LocalT.Scale(Vector3f(m_Radius, m_Radius, m_Height));
this->Updated();
/** Signal emitted when properties change */
virtual void Updated() override {
this->UpdateLocalMatrix();
ULIB_SIGNAL_EMIT(Cylinder::Updated);
}
float m_Radius;
float m_Height;
private:
/** Recalculates the internal local matrix based on dimensions and axis */
void UpdateLocalMatrix() {
m_LocalT = AffineTransform(this);
if (Axis == 0) m_LocalT.Scale(Vector3f(Height, Radius, Radius));
else if (Axis == 1) m_LocalT.Scale(Vector3f(Radius, Height, Radius));
else m_LocalT.Scale(Vector3f(Radius, Radius, Height));
}
float Radius;
float Height;
int Axis;
AffineTransform m_LocalT;
};