mirror of
https://github.com/leozide/leocad.git
synced 2026-10-26 22:10:32 +00:00
Large models can extend beyond the default far plane after fitting, leaving the view blank or clipped. Pass an explicit adjustment flag through view, model, and camera fitting, and reuse the fitted bounds to expand clipping with a margin, rounded up to multiples of 10,000. Adjust restored ordinary cameras after applying their saved state. Preserve named cameras and explicit command-line clipping planes, and avoid recalculating clipping during redraws or navigation. Route output fitting through the view and move the bounds policy definition out of the precompiled header.
239 lines
6.7 KiB
C++
239 lines
6.7 KiB
C++
#pragma once
|
|
|
|
#include "object.h"
|
|
#include "lc_math.h"
|
|
|
|
enum class lcViewpoint
|
|
{
|
|
Front,
|
|
Back,
|
|
Top,
|
|
Bottom,
|
|
Left,
|
|
Right,
|
|
Home,
|
|
Count
|
|
};
|
|
|
|
enum class lcCameraProjection
|
|
{
|
|
Perspective,
|
|
Orthographic,
|
|
Count
|
|
};
|
|
|
|
enum lcCameraSection : quint32
|
|
{
|
|
LC_CAMERA_SECTION_INVALID = LC_OBJECT_SECTION_INVALID,
|
|
LC_CAMERA_SECTION_POSITION = 0,
|
|
LC_CAMERA_SECTION_TARGET,
|
|
LC_CAMERA_SECTION_UPVECTOR
|
|
};
|
|
|
|
struct lcCameraHistoryState
|
|
{
|
|
lcObjectId Id;
|
|
bool Hidden;
|
|
bool Simple;
|
|
float Fovy;
|
|
float NearPlane;
|
|
float FarPlane;
|
|
lcCameraProjection Projection;
|
|
lcObjectProperty<lcVector3> Position;
|
|
lcObjectProperty<lcVector3> TargetPosition;
|
|
lcObjectProperty<lcVector3> UpVector;
|
|
QString Name;
|
|
|
|
bool operator==(const lcCameraHistoryState& Other) const
|
|
{
|
|
return Id == Other.Id && Hidden == Other.Hidden && Simple == Other.Simple && Fovy == Other.Fovy &&
|
|
NearPlane == Other.NearPlane && FarPlane == Other.FarPlane && Projection == Other.Projection &&
|
|
Position == Other.Position && TargetPosition == Other.TargetPosition && UpVector == Other.UpVector && Name == Other.Name;
|
|
}
|
|
};
|
|
|
|
class lcCamera : public lcObject
|
|
{
|
|
public:
|
|
lcCamera();
|
|
lcCamera(bool Simple);
|
|
lcCamera(bool Simple, const lcVector3& Position, const lcVector3& TargetPosition);
|
|
virtual ~lcCamera();
|
|
|
|
lcCamera(const lcCamera&) = delete;
|
|
lcCamera(lcCamera&&) = delete;
|
|
lcCamera& operator=(const lcCamera&) = delete;
|
|
lcCamera& operator=(lcCamera&&) = delete;
|
|
|
|
static QString GetCameraProjectionString(lcCameraProjection CameraProjection);
|
|
static QStringList GetCameraProjectionStrings();
|
|
static lcViewpoint GetViewpoint(const QString& ViewpointName);
|
|
|
|
QString GetName() const override
|
|
{
|
|
return mName;
|
|
}
|
|
|
|
bool SetName(const QString& Name);
|
|
void CreateName(const std::vector<std::unique_ptr<lcCamera>>& Cameras);
|
|
|
|
bool IsSimple() const
|
|
{
|
|
return mSimple;
|
|
}
|
|
|
|
lcCameraProjection GetProjection() const
|
|
{
|
|
return mProjection;
|
|
}
|
|
|
|
bool SetProjection(lcCameraProjection CameraProjection);
|
|
bool SetFOV(float Fovy);
|
|
bool SetNearPlane(float NearPlane);
|
|
bool SetFarPlane(float FarPlane);
|
|
|
|
quint32 GetAllowedTransforms() const override
|
|
{
|
|
return LC_OBJECT_TRANSFORM_MOVE_XYZ;
|
|
}
|
|
|
|
lcVector3 GetSectionPosition(quint32 Section) const override
|
|
{
|
|
switch (Section)
|
|
{
|
|
case LC_CAMERA_SECTION_POSITION:
|
|
return mPosition;
|
|
|
|
case LC_CAMERA_SECTION_TARGET:
|
|
return mTargetPosition;
|
|
|
|
case LC_CAMERA_SECTION_UPVECTOR:
|
|
return lcMul31(lcVector3(0, 25, 0), lcMatrix44AffineInverse(mWorldView));
|
|
}
|
|
|
|
return lcVector3(0.0f, 0.0f, 0.0f);
|
|
}
|
|
|
|
lcMatrix33 GetRelativeRotation() const
|
|
{
|
|
const quint32 Section = GetFocusSection();
|
|
|
|
if (Section == LC_CAMERA_SECTION_POSITION)
|
|
return lcMatrix33(mWorldView);
|
|
else
|
|
return lcMatrix33Identity();
|
|
}
|
|
|
|
lcVector3 GetRotationCenter() const
|
|
{
|
|
const quint32 Section = GetFocusSection();
|
|
|
|
if (Section != LC_CAMERA_SECTION_TARGET)
|
|
{
|
|
return mPosition;
|
|
}
|
|
else
|
|
{
|
|
return mTargetPosition;
|
|
}
|
|
}
|
|
|
|
void SaveLDraw(QTextStream& Stream) const;
|
|
bool ParseLDrawLine(QTextStream& Stream);
|
|
|
|
public:
|
|
bool IsVisible() const
|
|
{
|
|
return !mHidden;
|
|
}
|
|
|
|
bool IsHidden() const
|
|
{
|
|
return mHidden;
|
|
}
|
|
|
|
void SetHidden(bool Hidden)
|
|
{
|
|
mHidden = Hidden;
|
|
}
|
|
|
|
void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey)
|
|
{
|
|
mPosition.ChangeKey(Position, Step, AddKey);
|
|
}
|
|
|
|
void SetTargetPosition(const lcVector3& TargetPosition, lcStep Step, bool AddKey)
|
|
{
|
|
mTargetPosition.ChangeKey(TargetPosition, Step, AddKey);
|
|
}
|
|
|
|
void SetUpVector(const lcVector3& UpVector, lcStep Step, bool AddKey)
|
|
{
|
|
mUpVector.ChangeKey(UpVector, Step, AddKey);
|
|
}
|
|
|
|
float GetOrthoHeight() const
|
|
{
|
|
// Compute the FOV/plane intersection radius.
|
|
// d d
|
|
// a = 2 atan(------) => ~ a = --- => d = af
|
|
// 2f f
|
|
const float f = (mPosition - mTargetPosition).Length();
|
|
return (m_fovy * f) * (LC_PI / 180.0f);
|
|
}
|
|
|
|
public:
|
|
void RayTest(lcObjectRayTest& ObjectRayTest) const override;
|
|
void BoxTest(lcObjectBoxTest& ObjectBoxTest) const override;
|
|
void DrawInterface(lcContext* Context, const lcScene& Scene) const override;
|
|
QVariant GetPropertyValue(lcObjectPropertyId PropertyId) const override;
|
|
bool SetPropertyValue(lcObjectPropertyId PropertyId, lcStep Step, bool AddKey, QVariant Value) override;
|
|
bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override;
|
|
bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override;
|
|
void RemoveKeyFrames() override;
|
|
lcCameraHistoryState GetHistoryState(const lcModel* Model) const;
|
|
void SetHistoryState(const lcCameraHistoryState& State, const lcModel* Model);
|
|
|
|
void InsertTime(lcStep Start, lcStep Time);
|
|
void RemoveTime(lcStep Start, lcStep Time);
|
|
|
|
static bool FileLoad(lcFile& file);
|
|
|
|
void CompareBoundingBox(lcVector3& Min, lcVector3& Max);
|
|
void UpdatePosition(lcStep Step) override;
|
|
void CopyPosition(const lcCamera* Camera);
|
|
void CopySettings(const lcCamera* Camera);
|
|
|
|
void ZoomExtents(float AspectRatio, const lcVector3& Center, const std::vector<lcVector3>& Points, lcStep Step, bool AddKey, bool AdjustFarPlane);
|
|
void ExpandFarPlane(const std::vector<lcVector3>& Points);
|
|
void ZoomRegion(float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners, lcStep Step, bool AddKey);
|
|
void Zoom(float Distance, lcStep Step, bool AddKey);
|
|
void Pan(const lcVector3& Distance, lcStep Step, bool AddKey);
|
|
void Orbit(float DistanceX, float DistanceY, const lcVector3& CenterPosition, lcStep Step, bool AddKey);
|
|
void Roll(float Distance, lcStep Step, bool AddKey);
|
|
void Center(const lcVector3& NewCenter, lcStep Step, bool AddKey);
|
|
void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance);
|
|
void MoveRelative(const lcVector3& Distance, lcStep Step, bool AddKey);
|
|
void Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame);
|
|
void SetViewpoint(lcViewpoint Viewpoint);
|
|
void SetViewpoint(const lcVector3& Position);
|
|
void SetViewpoint(const lcVector3& Position, const lcVector3& Target, const lcVector3& Up);
|
|
void GetAngles(float& Latitude, float& Longitude, float& Distance) const;
|
|
void SetAngles(float Latitude, float Longitude, float Distance);
|
|
|
|
float m_fovy = 30.0f;
|
|
float m_zNear = 25.0f;
|
|
static constexpr float DefaultFarPlane = 50000.0f;
|
|
float m_zFar = DefaultFarPlane;
|
|
|
|
lcMatrix44 mWorldView;
|
|
lcObjectProperty<lcVector3> mPosition = lcObjectProperty<lcVector3>(lcVector3(0.0f, 0.0f, 0.0f));
|
|
lcObjectProperty<lcVector3> mTargetPosition = lcObjectProperty<lcVector3>(lcVector3(0.0f, 0.0f, 0.0f));
|
|
lcObjectProperty<lcVector3> mUpVector = lcObjectProperty<lcVector3>(lcVector3(0.0f, 0.0f, 0.0f));
|
|
|
|
protected:
|
|
QString mName;
|
|
bool mSimple = true;
|
|
lcCameraProjection mProjection = lcCameraProjection::Perspective;
|
|
};
|